Pages

Thursday 29 August 2013

Drupal behaviors: A quick how to

If you’re adding JavaScript to your custom module it is very easy and tempting to simply add it like this:
jQuery(document).ready(function($){ alert(‘hot dog flavored water’); }); 
Now this code works perfectly fine but what if your JavaScript needs to be executed on page load and after an AJAX request? Imagine you have a view that uses “Views Infinite Scroll” and you want add a CSS class to every result like this:
jQuery(document).ready(function($){ $('.view-display-id-page .views-row').addClass('fancy-pants'); }); 
This will work for the results that are displayed initially but for all the results that are loaded by Infinite Scroll's AJAX call the class is not added. That’s where Drupal behaviors come in handy.  The behaviors will be executed on every request including AJAX requests, so let's do the equivalent of the code above but this time using this method:
Drupal.behaviors.infiniteScrollAddClass = { attach: function (context, settings) { $('.view-display-id-page .views-row').addClass('fancy-pants'); } }; 
I admit that was quick - so here are some explanations:
  • infiniteScrollAddClass: This is your namespace and should be unique. For example, this is typically the name of your module, but it isn't mandatory.
  • context: This is actually really really cool, on page load the context will contain the entire document and after an AJAX request will have all the newly loaded elements. This way you can treat content that is loaded in via AJAX differently than others.
  • settings: This contains information passed on to JavaScript via PHP, it is similar to accessing it via Drupal.settings. For further comprehension I recommend this source.
There obviously are cases where some functionality should not be executed on every request. In such a case its great to use jQuery's .once() method. So let's say we want to give all the initially loaded results in our view an additional class, for something like this we would proceed like so:
Drupal.behaviors.infiniteScrollAddClass = { attach: function (context, settings) { // these are the elements loaded in first $('.view-display-id-page').once(function(){ $(this).find('.views-row').addClass('i-was-here-first'); });  // everybody $('.view-display-id-page .views-row').addClass('fancy-pants'); } }; 
This will add the class “i-was-here-first” to all the view results present on page load, everybody else joining in via AJAX will just get the “fancy-pants” class.
So that’s a quick look at Drupal behaviors, if you haven’t used it do use it!
If you are looking for additional theoretical insight into this topic I can recommend these two sources for further reading:

No comments:

Post a Comment