Using Jquery, JSON, and AJAX in Drupal

I recently had the opportunity to dig into drupal's activemenu module, a seldom-used and not-entirely-functional ajax framework that can be used to build menus/trees on the fly.  It provided a good roadmap that I was able to customize to work well for a project I did with

Here's a quick screencast overview of the project and what it entailed:

I've used AJAX and jquery before occasionally, but it's not my specialty, so I had to learn a few things to pull this project together.  I suspect most readers won't need to be bored by the details of what I had to learn, so I'll just include a few quick solutions to some of the obstacles I encountered:

  • Some JSON data, especially the more complex items involving arrays, was not properly handled by drupal_to_js, as a result of which I needed to use json_encode() instead (the server callback ends in my code now ends with  print json_encode ($items) ; exit;
  • Using <a href=""> to store the path for subsequent calls to the server was not cross-browser compatible for my application, so I instead stored the path in an attribute of the <li> element.  Here's my code in the js where I construct each li item, which is then appended into the <ul> containing element, which is in turn appended into the <li> containing element:
    • 				$.each( datax , function(i,item){ 
       if (item.children) { $leaf_class = '';  } 
         else { $leaf_class = 'leaf';} 
       $newchildren += '<li class="collapsed '  
      + $leaf_class + ' "data-activemenu-ajax-path="'+item.path+' " >' 
      + item.title + '</li>' ;
  • I needed to use a slightly different test in the jquery click function to determine whether an element processing the click should do an ajax expand.  I added the following code so that clicks on an interior child list element did not invoke an additional unnecessary double expansion of its parent:
    • 				var $click_is_real = 1 ;
      var yoffset = Drupal.mousePosition(e).y - $(this).offset().top;   
      if (  $(this).is('.leaf')  ) {     $click_is_real = 0 ; }  // we don't want clicks of expanded children to affect parents.
      if ($click_is_real) { 
  • Finally, in order to allow the entire text of the <li> <span> elements to expand the li using the toggle function, I had to add the following to the beginning of Drupal.activemenuToggle:
    • 				if ( == menu ) {