6. Ajax in Drupal using jQuery
Ajax is a particular type of functionality that enables your pages to retrieve and display information from a resource on the server without the need to reload. jQuery provides a few different Ajax commands, depending on your exact requirements. Here is the simplest Ajax call you can make with jQuery:
$(‘#someDiv’).load(url);What this is saying is "Find the div with the id of 'someDiv' and load the html that you find at the location 'url' into this div". Actually, this example is really AHAH and not Ajax, because it returns straight html and does not need to be parsed. On the other hand, Ajax, in its strictest sense, retrieves XML data from a server resource, which then needs to be parsed before being displayed on your page. But in fact, very few Ajax applications actually return XML data these days. A much more common format for data to be sent back from the server is JSON. And this is how we do it in Drupal.
The jQuery utility functions below provide for the extra flexibility you need when dealing with data coming back from the server that needs to be parsed.
$.get(url, parameters, callback);
$.post(url, parameters, callback);
$.ajax(options);The only difference between $.get and $.post is the http request method used to send your parameters (an array passed as the second argument) to the server. Very often in Drupal, you won't need to send any parameters because the url you will be calling will be a menu callback you have set up as, for example, 'ajax/get/node_details' taking one argument, 'nid' and so you would simply make the call to 'ajax/get/node_details/123' and not need to send your nid parameter as a parameter in the second argument.
So, here's a very simple example of how this would work. Suppose you have a slideshow page on your site, similar to what you often see on news sites, where underneath the main image are numbered buttons and clicking on these instantly changes the image displayed, without reloading the page. Well, to set up something like this you would first of all set up the page so that it outputs a container for the first image (for the purposes of this example we'll assume it loads the first image as normal; also, all images are nodes) and then all the required numbered buttons. Then, to add some ajax action, you'll need to build a custom module that defines your ajax callback. Set up a menu callback in your .module file, something like this:
<?php
/**
* Implementation of hook_menu().
*/
function myModule_menu() {
$items['photos/get/photos'] = array(
'page callback' => 'mymodule_get_photos_ajax',
'type' => MENU_CALLBACK,
'access arguments' => array('access content'),
);
return $items;
}
function mymodule_get_photos_ajax($nid) {
$photo = mymodule_get_photo($nid); // returns the filepath of my photo
$image = theme('image', $photo);
echo drupal_to_js(array('image'=>$image));
exit;
}
?>Our JavaScript is going to make a request to the path photos/get/photos/123, where 123 is the nid of the photo it's looking for, and the function mymodule_get_photos_ajax() will take that nid and do the required php to be able to send back the image path in a JSON object, to be parsed by the JavaScript.
Here's what our JavaScript will look like:
Drupal.behaviors.myModule = function() {
$('a.photo_button:not(.mymodule-processed)', context).addClass('mymodule-processed')
.bind('click', function(){
$.get('/photos/get/photos/'+ parseInt(this.id, 10), null, imageDetails);
return false;
});
}
var imageDetails = function(data) {
var result = Drupal.parseJson(data);
$('div.field-type-image div.field-item').html(result['image']);
}The first function here is binding the ajax behaviour to the onclick event of all buttons with the class "photo_button". It's using $.get, meaning it will make a http GET request to the path passed in as the first argument. Notice that it's getting the nid of the required node by parsing the id of the button - an easier way would have been to make the href of the button the ajax path itself but that would have nasty results for users without JavaScript. So the href is just going to go to the node and the JavaScript retrieves the nid by other means. We pass in null as the second argument because we don't need to pass in any additional parameters, we're already sending the nid in the url. And finally we specify the callback function, imageDetails, to be called when the request has been successful. The imageDetails function parses the JSON object that our PHP function has sent back and loads the 'image' portion of the result into our container div.
Also worth noting: in Drupal 6, you wrap all your module’s jQuery behaviors in a function assigned to Drupal.behaviors.myModule; there's no need to call it within $(document).ready() as Drupal automatically does it for you; all behaviors can then be reattached to DOM elements that have come from an AJAX call. For more information on this look at the Drupal JavaScript API documentation
Note
You could also replace
echo drupal_to_js(array('image'=>$image));with
drupal_json(array('image'=>$image));
Basic Tutorial
Thanks for posting this. It helped a lot to help me ajaxify my site.
I've wrote a short but helpfull (I hope :) ) step by step tutorial to show how to set up a module that handles ajax requests.
I hope it helps other people, as I found it hard to find something similar elsewhere.