Drupal Theming + jQuery Basics (inc. Drupal Behaviors)

In this tutorial you'll see how to implement a toggling effect using jQuery within your Drupal theme whilst utilising Drupal behaviors.

The finished effect can be seen in this Drupal jQuery demo.

The toggle is achieved via a two-step process:

  • Step 1 - add content and markup to a node
  • Step 2 - implement jQuery, utilising Drupal behaviors, which will enable the toggling to work

Step 1 - add content and markup to a node

First add the following code to your node body (remembering to set the input format to Full HTML in order to avoid the div tags getting ignored):

<a href="#" id="togg-link">Click this link to toggle the content displayed below</a>
<div id="togg">
This content will be toggled open and closed using jQuery.
Blah, blah, blah.
</div>

There are two key elements within the code:

  • the element which, when clicked on, will execute the toggle (in this case the link with an id of 'togg-link')
  • the element which will be toggled (in this case the div with an id of 'togg')

Step 2 - implement the jQuery, utilising Drupal behaviors, which will enable the toggling to work

In this tutorial, we'll be implementing our jQuery via a new 'script.js' file which will sit in our theme folder.

Drupal 6 helps us greatly when it comes to including jQuery in themes by doing the following:

  • automatically finding this new 'script.js' file and including it (source - Structure of the .info file - scripts)
  • auto-including the main 'jquery.js' and 'drupal.js' files for us when it recognises that a certain page requires them

meaning that, in short, all we have to do is write the required jQuery code for the toggle in our new 'script.js' file and it'll work!

So, to start, create a new .js file named 'script.js' and save it within your theme's root folder. i.e.:

/sites/all/themes/mytheme/script.js

(replace 'mytheme' with your theme's actual name e.g. 'my_great_theme')

Please note: the file will not automatically be found if you place it within a different location (e.g. /sites/all/themes/mytheme/otherfiles/script.js). Furthermore, if you have already declared other .js files via your theme's .info file you will also have to declare this new file.

Then add the following code to the 'script.js' file:

//togg
Drupal.behaviors.togg = function (context) {
  $('a#togg-link:not(.togg-processed)', context).addClass('togg-processed').each(function () {
    $(this).click(function() {
      $("div#togg").toggle(400);
      return false;
    });
  });
};

Nice huh! Err...but what the heck does it all mean? Let's break it down:

Drupal.behaviors.togg = function (context) {

};

Create a Drupal behavior (which is simply a function), attach it to the 'Drupal.behaviors' object, and pass in the 'context' object.

$('a#togg-link:not(.togg-processed)', context).addClass('togg-processed').each(function () {

});

Loop through all instances of 'a#togg-link' which do not already have a class of 'togg-processed', add a class of 'togg-processed' and...

$(this).click(function() {

});

...attach a click function, which will execute when '$(this)' (i.e. our link) is clicked.

$("div#togg").toggle(400);

When the click function is executed, toggle the div with an id of 'togg' at a speed of 400 milliseconds...

return false;

... and prevent the link from working (ordinarily clicking on a link whose destination is a pound sign '#' would jump the user to the top of the page).

Empty cache

If you haven't yet done so empty the cache and enjoy your new Drupal jQuery toggling goodness!
See the section marked 'Empty the cache' in the 'creating custom regions in drupal 6 themes' post for two ways to do so.

Limitations

As stated in the title, this is a basic example. In a more complex scenario where, for example, you wished to apply toggling to multiple items within a node it would be more practical to do so by dynamically assigning ids... although that's a discussion for another post...

Drupal jQuery Book


Drupal 6 JavaScript and jQuery
by Matt Butcher

Useful jQuery Links

jquery.com
visualjquery.com
Working with JavaScript and jQuery

22 comments

Neil July 28th, 2009 @ 8:39pm

How do you feel about this method? I'm not criticizing, I'm just curious on the difference.

Keep the HTML the same

script.js:

if (Drupal.jsEnabled) {
  $(document).ready(function() {
    $('#togg-link').click(function() {
      $("#togg").toggle(400);
      })
    return false;
    });
  });
}
jadwigo July 28th, 2009 @ 8:45pm

Nice writeup, wanted to find an easy way for drupal to do stuff like that, but never got around to finding out how to.

One comment though: event.preventDefault(); is the recommended way for jQuery to make links do nothing when you click them: http://docs.jquery.com/Events/jQuery.Event#Methods

that would make the code like:

$(this).click(function(e) {
  e.preventDefault();
  $("div#togg").toggle(400);
});
Sidharth July 28th, 2009 @ 9:16pm

Curious to know the answer raised by Neil. Why use Drupal.behaviors and not $(document).ready() ?

Laurence July 28th, 2009 @ 10:59pm

Hi all,
thanks for the comments.

@Neil and @Sidharth - I'd suggest the main advantage of using Drupal behaviors is that they are re-attachable, which becomes very useful when utilising AHAH/AJAX. Using '$(document).ready()' within 'script.js' means it will run only once (once the DOM is ready) each page load, whereas behaviors will be attached each time 'Drupal.attachBehaviors()' is called (and in Drupal 6 the 'drupal.js' file (/misc/drupal.js) is already set up to attach all behaviors for us upon intital page load).

Check out the following for further Drupal behaviors discussion:

@jadwigo - interesting - thx, I will check that out :)

Drupal Theme Garden July 29th, 2009 @ 10:54am

Really nice article. Thanks.

BTW, it's nice to see that you are writing again :-)

Neil July 30th, 2009 @ 8:15pm

Thanks. It's time for me to adjust.

Oto Araba August 10th, 2009 @ 4:38pm

good stuff, im trying to get the best out of jquery atm. helpful post, thx.

sila August 18th, 2009 @ 6:26pm

Great tip! Thanks a lot,
one question though, i can't manage to make the div invisible as default state. Any clue?

coolo August 18th, 2009 @ 11:52pm

Thanks for the tips. This got me started. However...

"In a more complex scenario where, for example, you wished to apply toggling to multiple items within a node it would be more practical to do so by dynamically assigning ids... although that's a discussion for another post..."

Any idea of where I could find a resource to help me out with doing what you said in your last paragraph?

Laurence August 19th, 2009 @ 2:48pm

@sila - you can hide the #togg div by default using an additional behavior in your 'script.js' file, like so:

Drupal.behaviors.toggdiv = function (context) {
  $('div#togg:not(.toggdiv-processed)', context).addClass('toggdiv-processed').each(function () {
    $(this).hide();
  });
};

@coolo - good question! I started writing you an answer and realised that it really does require a full post to cover everything (with examples etc.) - so I will publish that in the near future.

Basically, you can loop through all of your content divs (which contain the content you want to toggle) assigning each an id or class and then loop through all of your toggle links assigning each a corresponding id or class and attaching a click function which will toggle the relevant content when clicked.

It's all done utilising jQuery's each() function and, specifically, using an index (i) - a basic example being:

$(document.body).click(function () {
  $("div").each(function (i) {
    $(this).addClass("example" + i);
  });
});

Of course in Drupal we can put the js code inside of a behavior, but I'll add all that in the main post :)
Hope that helps you out for now.

OZz September 14th, 2009 @ 9:28am

I'm also one of the jquery beginners so this tutorial really helped me too .. Thanks!

drupal theming October 7th, 2009 @ 11:35am

thanks, for this useful information..i am new to drupal and learning from your blogs a lot..

mahi November 27th, 2009 @ 7:29am

great job buddy...
i am a beginner.. and my question is how can i have multiple toggle on the same page??
please help me out.

Drupal Templates February 20th, 2010 @ 11:00am

Thanks a lot! Websites with jQuery contribute a lot more professional and look more beautiful. Your introduction has given us great help on.

Find The Best April 19th, 2010 @ 9:14pm

At first I thought I wasn't going to get much out of this one, but the comments regarding using Drupal.behaviors vs. the standard $(document).ready() approach was very enlightening. Our site uses a fair amount of AJAX and I've found myself having to work around this in other ways.

Very helpful. Thanks!

abitofcode April 26th, 2010 @ 12:52am

"I'd suggest the main advantage of using Drupal behaviors is that they are re-attachable, which becomes very useful when utilising AHAH/AJAX."

Finally a clear explanation, thank you for a great article. In combination with the following post it's clicked and I have a working dynamic select drilldown;

http://groups.drupal.org/node/20318

:D

SJL Perth May 9th, 2010 @ 7:43pm

Thanks for the great piece of jQuery Laurence, I'm going to try and expand upon it for my next Drupal website.

Britta Stender June 14th, 2010 @ 7:36am

Great tutorial! :)

However, I would love if you added a few lines to this tutorial, describing how to do if you want the togg closed at start and then to push the link to open it.

Nico June 15th, 2010 @ 5:12pm

Great Job Laurence, thank you for this tutorial. Have sought for some time after such a tutorial.

J. Sedwick June 15th, 2010 @ 9:38pm

This is the first article and related comments I've found that explains Drupal Behaviors well. Great work.

Doug June 25th, 2010 @ 12:08am

Anyone else having problems with this not working in Safari 5.0 - Windows?

Doug June 25th, 2010 @ 12:10am

Scratch that. It's working now. Don't know why it wasn't....

Comments are closed

If you want to ask a question or have something to add please contact me.