Ho un modulo che aggiorna un nodo tramite Ajax quando si fa clic su un collegamento.
Il collegamento è un interruttore, dovrebbe aggiornare il nodo con il valore 1 al primo clic, quindi con il valore 0 a un clic successivo, ecc. Come accendere / spegnere qualcosa.
Il codice seguente funziona al primo clic dopo il caricamento della pagina, ma non ai clic successivi. Credo che Drupal.attachBehaviors debba essere chiamato / attivato dopo ogni clic, ma non riesco a capire come farlo.
Il modulo
function mymodule_menu() { $items['mypath/%/%/ajax'] = array( 'title' => 'My title', 'page callback' => 'mymodule_ajax_callback', 'page arguments' => array(1,2), 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); ... } function mymodule_ajax_callback($id, $status) { //Validation[...] //Node Update using $id as the nid and $status as the field value[...] // Define a new array to hold our AJAX commands. $ajax_commands = array(); // Create a new AJAX command that replaces the #div. $replacedivid = '#status'.$id; $replacestring = '<div id="status'.$id.'"><a data-url="'.base_path().'mypath/'.$id.'/'.$new_status.'/ajax" title="This item is marked as '.$status_text.'" id="statuslink'.$id.'" class="midui">'.$status_text.'</a></div>'; $ajax_commands[] = ajax_command_replace($replacedivid, $replacestring); return drupal_json_output($ajax_commands); }
Javascript
(function ($) { Drupal.behaviors.mymodule = { attach: function(context, settings) { var $uilink = $('.midui'); //find all links for (var i=0;i<$uilink.length;i++) { //Loop var $link = $('#' + $uilink[i].id); if (!$link.hasClass("middone")) { new Drupal.ajax('#' + $uilink[i].id, $link, { url: $link.attr('data-url'), effect: 'fade', settings: {}, progress: { type: 'throbber' }, event: 'click tap' }); $link.addClass("middone"); //add class when we're done } } } } })(jQuery);
Quello che ho provato finora:
(a) Aggiungi un ajax_command_invoke(NULL, 'mymodule');
array di $ ajax_commands accoppiato con una $.fn.mymodule
funzione
(b) Aggiungi $('body').ajaxSuccess(Drupal.attachBehaviors);
al mio javascript. ajaxComplete anche provato. Ho provato anche sul documento.
(c) Crea un comando personalizzato come dettagliato qui http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7
Nota: so che è solo una questione di innescare attachBehaviors dopo ogni clic per "ajaxify" il nuovo codice HTML da inserire / modificare. Se faccio clic sul collegamento e digito Drupal.attachBehaviors () nella console, il collegamento verrà nuovamente elaborato dal mio javascript, come evidenziato dall'aggiunta della classe 'middone', e può essere nuovamente cliccato.
Nota: anche di interesse, se lascio il $ajax_commands
vuoto e lo restituisco (array vuoto) alla fine della funzione di callback, il collegamento rimarrà cliccabile sul primo e sui successivi clic. Avrà la funzionalità che sto cercando (un interruttore). Tuttavia, poiché non viene apportata alcuna modifica all'html dopo ogni clic, l'utente non può sapere se l'interruttore è attivato o disattivato.
Qualsiasi suggerimento sarebbe molto apprezzato.
================================================== =====
Una risposta parziale:
La funzione di successo drupal ajax.js ricollega i comportamenti solo per i moduli (penso?)
if (this.form) {
var settings = this.settings || Drupal.settings;
Drupal.attachBehaviors(this.form, settings);
}
così ho deciso di hackerare la funzione di successo di tutti i miei oggetti ajax.
Il Javascript ora diventa
(function ($) {
Drupal.behaviors.mymodule = {
attach: function(context, settings) {
var $uilink = $('.midui'); //find all links
for (var i=0;i<$uilink.length;i++) { //Loop
var $link = $('#' + $uilink[i].id);
if (!$link.hasClass("middone")) {
myAjax = new Drupal.ajax('#' + $uilink[i].id, $link, {
url: $link.attr('data-url'),
effect: 'fade',
settings: {},
progress: {
type: 'throbber'
},
event: 'click tap'
});
myAjax.options.success = function (response, status) {
//Trigger Attach Behaviors
setTimeout(function(){Drupal.attachBehaviors($(myAjax.selector))}, 0);
// Sanity check for browser support (object expected).
// When using iFrame uploads, responses must be returned as a string.
if (typeof response == 'string') {
response = $.parseJSON(response);
}
return myAjax.success(response, status);
}
$link.addClass("middone"); //add class when we're done
}
}
}
}
})(jQuery);
La funzione di successo è una copia incolla del valore predefinito da ajax.js con una riga aggiunta per ricollegare i comportamenti. Per qualche motivo, Drupal.attachBehaviors
deve essere all'interno di un timer. Non posso averlo da solo per un motivo che ignoro.
Lascerò questa domanda aperta per pochi nel caso in cui qualcuno possa trovare una soluzione più elegante e / o spiegare la stranezza del timer.
Grazie molto