Drupal - How can I trigger a javascript function when a Drupal ajax call is complete?
I ended up adding some additions commands to the page that is being returned by the ajax handler like this:
$commands = array();
$commands[] = ajax_command_invoke(NULL, 'grid_content_loading', array('argument1', 'argument2'));
$commands[] = ajax_command_append('#grid-content-target', $html);
$commands[] = ajax_command_invoke(NULL, 'grid_content_loaded', array('argument1', 'argument2'));
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
And on the client side I created 2 javascript funtions through jQuery:
(function($) {
$.fn.grid_content_loading = function($argument1, $argument2) {
...
};
$.fn.grid_content_loaded = function($argument1, $argument2) {
...
};
})(jQuery);
In my project, I had already written well-defined JavaScript code that updated the page stats after an AJAX call.
Since I wanted to reuse the functions without going to the extent of "extending jQuery", I ended up with the following solution, using an existing jQuery function, instead of defining a new one. This was inspired by what the 'flags' module does -- it simply triggers an event, and allows many Javascript event listeners to act in response, as opposed to having just a single hard-coded, custom jQuery plugin/extension as in the solution explored in the previous answers.
In a Drupal Module:
// in_some_ajax_function()
$commands[] = ajax_command_invoke('html', 'trigger', array('MY_EVENT'));
In Javascript:
// Added an event binding to my $(document).ready();
$(document).ready(function(){
$(document).bind('MY_EVENT', function() {
alert('MY_EVENT');
});
});
I had to note that the first parameter for ajax_command_invoke is NEVER any native JavaScript objects, so the following never works, because it translates into a 'document' (element) selector:
// This tries to select $('document')
// ... which is nothing, since there are no 'document' elements.
$commands[] = ajax_command_invoke('document', 'trigger', array('MY_EVENT'));
Curiously, binding on $(document)
and triggering on $('html')
are compatible. I suppose you can get very creative, and bind/trigger on more specific, deeper-level elements. If you can think of a scenario where doing so makes more sense than a top-level event trigger, please comment!
Code sample:
$commands = array();
$commands[] = array(
'command' => 'your_js_callback', // the name of your javascript callback
'value1' => 'My first value',
'value2' => 'My second value',
);
ajax_render($commands);
JS Code:
(function($, Drupal) {
Drupal.ajax.prototype.commands.your_js_callback = function(ajax, response, status) {
alert(response.value1);
alert(response.value2);
}
})(jQuery, Drupal);