Hi,

For example, If i need to call a custom javascript function that is globally available, after a form ajax succes, what would be the best way to do it? The javascript code would be generated in the ajax submit callback.

Comments

Jaypan’s picture

edit: sorry, wrong version of drupal.

cesarpo’s picture

thank you anyway!

anyone else?

kenianbei’s picture

I'm looking for the same, I need to add a js file after ajax_deliver() returns the page.

kenianbei’s picture

I was able to accomplish what I needed with ajax_command_invoke.
http://api.drupal.org/api/drupal/includes--ajax.inc/function/ajax_comman...

cesarpo’s picture

Would you please be so kind and tell me how you did it?

In the end i coded the ajax by my own, but would like to know the 'Drupal way' :)

StryKaizer’s picture

Looking for the drupal-solution too

StryKaizer’s picture

I made a custom jquery function to call my function. If there is a better solution, feel free to correct.

In my callback function:

$commands[] = ajax_command_invoke(NULL, "myJavascriptFunction", array($myCustomParameters) );

return array(
        '#type' => 'ajax',
        '#commands' => $commands,
);

In a custom javascript, I created a jquery function

(function($) {
	$.fn.myJavascriptFunction = function(data) {
		alert(data);
	};
})(jQuery);
basserc999’s picture

Just wanted to add a quick note here that this solution worked great for me. Thanks for posting your code!

For my use, I wanted to call a custom javascript command and then do the normal behavior of inserting a rebuilt form element into ajax['#wrapper']. I did this using something similar to the following code in my callback function:

  $commands[] = ajax_command_invoke(NULL, 'myJavascriptFunction', array($foo));
  $html = drupal_render($form['bar']);
  $commands[] = ajax_command_insert(NULL, $html);

  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );

If anyone has any feedback on this approach, it would be great to hear.

damien_vancouver’s picture

This solution helped me out too! I wanted to use jQuery to modify field values, because I wasn't actually rebuilding a form. So I accomplished it like this, without using the .js file and a myJavascriptFunction:

  // inside Ajax callback function

  $commands = array();

  // set Title and body form elements using jQuery's .val().
  $commands[] = ajax_command_invoke('#edit-body-title', 'val', array('new Title'));
  $commands[] = ajax_command_invoke('#edit-body-und-0-value', 'val', array('New body Text'));
  // Use ajax_command_html to replace the contents of <div id="div-ajax-form"> with an empty string
  $commands[] = ajax_command_html('#div-ajax-form','');   // Hide contents of ajax form

  return array('#type' => 'ajax', '#commands' => $commands);

Works great! But now what I really want to do is run other Javascript commands without using the .js file, ie. something like:

   // This doesn't work
   $commands[]  = ajax_command_invoke('Window','alert',array('Hi there!'));
   // Nor does this, which is really what I'd like to accomplish without needing to wrap it in a .js file function
   $commands[] = ajax_command_invoke(NULL,'Drupal.ckeditorOff',array('edit-body')

Does anyone have any insight as to how I can run commands like Window.alert() or Drupal.ckeditorOff() using an Ajax command array?

rszrama’s picture

You're going to have to do what the solution above indicates; define a jQuery plugin function that executes whatever other JavaScript you want to execute and invoke it using ajax_command_invoke(). Here's a tutorial on the subject I found helpful: http://addictedtonew.com/archives/414/creating-a-jquery-plugin-from-scra...

petu’s picture

The link is broken :(

This article helped me: Drupal 7 execute javascript code after a ajax call

elephant.jim’s picture

As an alternative, you can insert a script tag into the document.

$commands[] = ajax_command_append('body', '<script>alert("foo");</script>');

YMMV. I wanted to do it this way because I couldn't rely on my jQuery function definition being loaded after the function that I needed to call. Just thought I'd toss this out there for anyone else looking for another way.

gamilsm’s picture

Great answer, thanks for posting...

matzie’s picture

The solution suggested for Drupal 6 (Calling a function after an AHAH event in Drupal 6) works for me also fine in 7 and is quite straightforward. I've added the javascript inline:

drupal_add_js('jQuery(document).ajaxComplete(function(){		
			// the code to be fired after the AJAX is completed											
		});', 'inline');
bwt604’s picture

For me, .ajaxcomplete fired even when my form validation wasn't successful. The best way around this was to write a custom ajax plugin.

I included something like this in my active .js file:

$(function () {
  if (!Drupal.Ajax) return;
  Drupal.Ajax.plugins.yourAction = function (hook, args) {
    if (hook == 'message' && args.data.form_id == 'your_form' && args.data.status == true) {
      // args.data.status is true only after validation clears
      // Your js here
    }
  };
});

You can get a good look at the structure of your args with console.log(), then drill down so your code only executes exactly when you need it to. The ajax plugins are called in ajax.js, if you want to take a look.

Jaypan’s picture

It will work, but actually I've since written a tutorial on how to do it in D7 now using ajax commands (which is the way to do it in D7). Calling a function after an #AJAX event (Drupal 7)

Shashwat Purav’s picture

This is very nice tutorial. Saved the day. :)

Thank You,
Shashwat Purav

sillo’s picture

I have been searching for this function for a very long time... Thank you!

mahipal46’s picture

$( document ).ajaxStop(function() {
// call your js code
});

asghar’s picture

(function($) {

  Drupal.testAjax = {
    // Our form
    form_id: Your-Form-ID'  //Yes, I tested on my extended node creation form
  };

  Drupal.behaviors.testAjax = {
      
    attach: function(context, settings) {
      // We extend Drupal.ajax objects for all AJAX elements in our form 
      for (ajax_el in settings.ajax) {
        if (typeof Drupal.ajax[ajax_el] != 'undefined' && Drupal.ajax[ajax_el].element.form) {
          if (Drupal.ajax[ajax_el].element.form.id === Drupal.testAjax.form_id) {
            Drupal.ajax[ajax_el].beforeSend = Drupal.testAjax.beforeSend;
            Drupal.ajax[ajax_el].success = Drupal.testAjax.success;
            Drupal.ajax[ajax_el].error = Drupal.testAjax.error;
          }
        }
      }
    }   
  };

  // Disable form
  Drupal.testAjax.beforeSend = function (first, second) {
     console.log("Before Submit");
    // Call Drupal parent method 
    Drupal.ajax.prototype.beforeSend.call(this, first, second);
  }



  Drupal.testAjax.success = function (response, status) {
      console.log("On Success");
    // Call original method with main functionality
    Drupal.ajax.prototype.success.call(this, response, status);
  }
  Drupal.testAjax.error = function (response, uri) {
            console.log("Error");

    Drupal.testAjax.enableForm(this.element.form);
    
    // Call original method with main functionality
    Drupal.ajax.prototype.error.call(this, response, uri);
  }

})(jQuery);
Jaypan’s picture

This will work, but it adds extra overhead. Using the ajax_command_() series of functions provided by Drupal requires less scripting, and will have less overhead, as it is not called on every ajax command like the above code is.

d70rr3s’s picture

In my case I'm working with the IEF module and I needed to execute an JS function (as the answer) with updated settings passed back by a submit function (without hacking IEF module or process) and occurs when you make a CTA to a form or link by Ajax you could use drupal_add_js function and sent anything you may need back to the browser as par of the global response object with no need to overwrite your previous Ajax callback.

Myko’s picture

For me perfect and fastest solution

$( document ).ajaxStop(function() {
    // call your js code
});
Jaypan’s picture

It's an easy solution, but note that the code will be executed after every single AJAX request on the site - which can potentially cause a lot of overhead.

8bitplateau’s picture

wish I could vote this up !

gumrol’s picture

Late post I know, but in case it helps someone:
I was looking for something less global than ajaxStop or ajaxComplete(multiple panels on a checkout ajaxing at different times. So I used a little workaround leveraging Drupal's behaviour re-attachment. I wanted to add a spinner on very specific items on the page and remove them when specific ajax callbacks were complete so:
In my JS file, I attached a behavior, with a once to the html element being returned/ replaced by the specific ajax command that I want to target. In this way, your code will always run when that ajax call has stopped. More detail:
 

(function ($, Drupal, window, document, undefined) {
    // my behavior:
    Drupal.behaviors.orders_checkout = {
        // attachment: can add many 'once' in here
        attach: function(context, settings) {
            // select the dom item being replaced by the specific ajax call 
            // you want to target
            $('#ajax-replaced-dom', context).once('ajax-ended', function(){
                var $actionableDomItem = $('#dom-item-to-target');

                // remove on re-attach: if you don't want this to run on first
                // attachment, you'll need a global boolean to switch here
                $actionableDomItem.removeClass('busy-overlay');

                //NB! very specific attachment point so that the busy-overlay 
                //disappears when ajax is reload
                $(this).find('input[type=radio]').change(function(){
                    $actionableDomItem.addClass('busy-overlay');
                });
            });
        },
    };

})(jQuery, Drupal, this, this.document);

Hope it helps someone