web-dev-qa-db-fra.com

Comment puis-je déclencher une fonction javascript lorsqu'un appel Drupal ajax est terminé?

J'ai besoin de faire des choses supplémentaires après Drupal ajax a fini d'insérer des trucs dans le DOM. Avec jQuery, c'était simple, mais je ne peux pas pour la vie de moi comprendre comment pour le faire en Drupal 7: s

Dois-je ajouter quelque chose à mon lien ajaxifié? J'ai lu quelque chose sur l'attachement à un comportement ... la confusion s'installe ...

7
SomethingOn

J'ai fini par ajouter des commandes d'ajouts à la page qui est retournée par le gestionnaire ajax comme ceci:

$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);

Et côté client, j'ai créé 2 fonctions javascript via jQuery:

(function($) {
$.fn.grid_content_loading = function($argument1, $argument2) {
   ...
};

$.fn.grid_content_loaded = function($argument1, $argument2) {
   ...
};
})(jQuery);
6
SomethingOn

Dans mon projet, j'avais déjà écrit du code JavaScript bien défini qui mettait à jour les statistiques de la page après un appel AJAX.

Comme je voulais réutiliser les fonctions sans aller jusqu'à "étendre jQuery", je me suis retrouvé avec la solution suivante, en utilisant une fonction jQuery existante, au lieu d'en définir une nouvelle. Cela a été inspiré par ce que fait le module `` flags '' - il déclenche simplement un événement et permet à de nombreux écouteurs d'événements Javascript d'agir en réponse, au lieu d'avoir un seul plugin/extension jQuery personnalisé codé en dur comme dans la solution exploré dans les réponses précédentes.

Dans un module Drupal:

// in_some_ajax_function()

$commands[] = ajax_command_invoke('html', 'trigger', array('MY_EVENT'));

En Javascript:

// Added an event binding to my $(document).ready();

$(document).ready(function(){

  $(document).bind('MY_EVENT', function() {
    alert('MY_EVENT');
  });

});

J'ai dû noter que le premier paramètre pour ajax_command_invoke n'est JAMAIS un objet JavaScript natif, donc ce qui suit ne fonctionne jamais, car il se traduit par un sélecteur de document (élément):

// This tries to select $('document')
// ... which is nothing, since there are no 'document' elements.

$commands[] = ajax_command_invoke('document', 'trigger', array('MY_EVENT'));

Curieusement, la liaison sur $(document) et le déclenchement sur $('html') sont compatibles. Je suppose que vous pouvez devenir très créatif et lier/déclencher sur des éléments plus spécifiques et plus profonds. Si vous pouvez penser à un scénario où cela aurait plus de sens qu'un déclencheur d'événement de niveau supérieur, veuillez commenter!

3
starlocke

Je pense que la meilleure option est d'utiliser la fonction jQuery ajaxComplete:

(function($){ 
   $(document).ajaxComplete(function(e, xhr, settings)
   {
     alert(settings.url);
   });
}(jQuery));

Et si vous souhaitez utiliser la fonction pour une fonction ajax spécifique, vous pouvez utiliser le settings.url identifié pour votre champ et le changer en:

(function($) {
    $(document).ajaxComplete(function(e, xhr, settings){ 
    if (settings.url == "the path from step 1") {
        // Code to populate your fields here
    }
 });
}(jQuery));

Cela a fonctionné pour moi pour les Drupal 7 et 8.

2
valdeci

Échantillon de code:

$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);

Code JS:

(function($, Drupal) {
    Drupal.ajax.prototype.commands.your_js_callback = function(ajax, response, status) {
        alert(response.value1);
        alert(response.value2);
    }
})(jQuery, Drupal);
1
Muhammad Reda

J'ai posté une réponse à cette question donc

https://stackoverflow.com/a/19404566/894487

Je ne suis pas sûr des vraies différences entre l'extension Drupal.ajax.prototype.commands ou $.fn

J'imagine que le premier serait plus efficace car il n'y a pas de traversée de dom requise pour atteindre votre fonction. Je ne sais pas si c'est important.

0
ErichBSchulz

J'ai écrit un tutoriel sur la façon de le faire dans Drupal 7: https://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal- 7

0
Jaypan

Solution de piratage rapide: placez une image dans le contenu chargé et attribuez-lui l'attribut onload="[javascript function]()". Vous n'êtes pas sûr que ce soit ce que vous cherchez ... Ou si c'est plus facile que la bonne façon ... Mais peut-être mieux que rien?

0
Kirk Twist