Why is jQuery Not Working in Drupal 8?

I was editing a custom block in a Drupal 8 site that I’m working on and needed to use jQuery for a quick image swap. While it would have been possible to accomplish what I was looking for in straight JavaScript, doing it in jQuery made things much easier. The only problem was that jQuery wasn’t working and I was getting the “Uncaught ReferenceError: $ is not defined” message. I knew that jQuery was already being called by my theme, so why wasn’t it working?

After a bit of digging, I discovered two things that were keeping jQuery from working in my Drupal block:

  1. Drupal uses jQuery.noConflict() mode, so the $ shorthand won’t work out of the box. This means, to select the div1 div, for example, you’d need to use jQuery.('#div1') instead of $('#div1'). Or, apparently, you can “include jQuery and Drupal as dependencies in the library definition in your MODULE.libraries.yml and add a wrapper around your function,” but that sounds like a lot of work. I chose to go the easy route for this one because it was such a small bit of code.
  2. To improve performance, Drupal calls jQuery from the very bottom of the page so, if you’re including JavaScript in a custom block, it’s going to fire before jQuery is available. (Yes, I know that it would theoretically be better to put all the JavaScript into an external file, but when it’s just a couple lines of code, that feels like more effort than it’s worth.) The good news is that there’s an easy fix: You can keep your script from firing until jQuery has loaded with window.onload.

Put together, here’s what those workarounds look like:

<script>
window.onload = function() {
	jQuery('#div1').hover(
		function() { jQuery('#div1 img').attr('src','image2.jpg'); },
		function() { jQuery('#div1 img').attr('src','image1.jpg'); }
	);
};
</script>

Problem solved! The above works from within a Drupal 8 custom block.

This also works as a cheap way to get jQuery code to run from within the body of any Drupal 8 content node. Here’s a quick test I used to make sure it was working:

<script>
window.onload = function() {
	jQuery('h1').fadeOut();
};
</script>

Without the window.onload you get “Uncaught ReferenceError: jQuery is not defined,” but with it there, your title fades out as soon as the page finishes loading.

If you’ve discovered a better way of getting around this, I’d love to hear about it. Share with us in the comments below.

Comments

Loading…

This article was first published on September 21st, 2017 and last updated on September 14th, 2018 by Robert James Reese in the following categories: Drupal, JavaScript, and jQuery. Before using any of the code or other content in this post, you must read and agree to our terms of use.