Ich habe ein Modul, das einen Knoten über Ajax aktualisiert, wenn auf einen Link geklickt wird.
Der Link ist ein Umschalter. Er sollte den Knoten beim ersten Klicken mit dem Wert 1 und beim nächsten Klicken mit dem Wert 0 aktualisieren. Zum Beispiel, wenn Sie etwas ein- oder ausschalten.
Der folgende Code funktioniert beim ersten Klicken nach dem Laden der Seite, jedoch nicht bei nachfolgenden Klicks. Ich glaube, Drupal.attachBehaviors muss nach jedem Klick aufgerufen / ausgelöst werden, aber ich kann nicht herausfinden, wie das geht.
Das Modul
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);
Was ich bisher versucht habe:
(a) Fügen ajax_command_invoke(NULL, 'mymodule');
Sie dem Array $ ajax_commands ein hinzu , das mit einer $.fn.mymodule
Funktion gekoppelt ist
(b) $('body').ajaxSuccess(Drupal.attachBehaviors);
Zu meinem Javascript hinzufügen. ajaxComplete hat es ebenfalls versucht. Versuchte es auch auf dem Dokument.
(c) Erstellen Sie einen benutzerdefinierten Befehl, wie hier beschrieben. http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7
Hinweis: Ich weiß, dass es nur darum geht, attachBehaviors nach jedem Klick auszulösen, um das neue HTML, das eingefügt / geändert wird, zu "ajaxifizieren". Wenn ich auf den Link klicke und dann Drupal.attachBehaviors () in die Konsole eingebe, wird der Link von meinem Javascript erneut verarbeitet, was durch das Hinzufügen der Klasse 'middone' belegt wird, und kann erneut angeklickt werden.
Hinweis: Interessant ist auch, dass $ajax_commands
der Link beim ersten und den folgenden Klicks anklickbar bleibt , wenn ich das Feld leer lasse und es (leeres Array) am Ende der Rückruffunktion zurückgebe. Es wird die Funktionalität haben, die ich suche (ein Umschalter). Da jedoch nach jedem Klick keine Änderungen am HTML vorgenommen werden, kann der Benutzer nicht feststellen, ob der Schalter ein- oder ausgeschaltet ist.
Alle Hinweise wäre sehr dankbar.
================================================== =====
Eine teilweise Antwort:
Die Erfolgsfunktion von Drupal ajax.j fügt nur Verhaltensweisen für Formulare wieder hinzu (glaube ich?)
if (this.form) {
var settings = this.settings || Drupal.settings;
Drupal.attachBehaviors(this.form, settings);
}
Deshalb habe ich beschlossen, alle Erfolgsfunktionen meiner Ajax-Objekte zu hacken.
Das Javascript wird jetzt
(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);
Die Erfolgsfunktion ist ein Kopieren und Einfügen der Standardeinstellung aus ajax.js mit einer zusätzlichen Zeile für das erneute Anhängen von Verhalten. Aus irgendeinem Grund Drupal.attachBehaviors
muss innerhalb eines Timers sein. Ich kann es aus einem Grund, den ich ignoriere, nicht einfach alleine haben.
Ich werde diese Frage für einige offen lassen, falls jemand entweder eine elegantere Lösung finden und / oder die Seltsamkeit des Timers erklären kann.
Danke vielmals
quelle
Antworten:
Es kann schwierig sein, Ajax-Verhalten an Inhalte anzuhängen, die von einer Ajax-Anforderung selbst zurückgegeben werden. Es ist jedoch möglich.
Obwohl Ihr Hook_menu-Code-Snippet unvollständig aussieht, vorausgesetzt, es ist korrekt (gibt $ items zurück und die Funktion ist geschlossen) - In Ihrem Fall müssen Sie möglicherweise nur den Rückruf für die Zustellung auf 'ajax_deliver' anpassen.
dh:
quelle
Nach einigem Debuggen wurde mir klar, dass das Problem nicht mit meinem Code zusammenhängt.
Das Problem lag bei einem anderen Modul, in meinem Fall dem Colorbox-Modul, das die Ursache für einen js-Fehler in seiner eigenen Verhaltensfunktion war. Ich glaube, der Fehler hat dazu geführt, dass der Prozess zum Anhängen von Verhaltensweisen angehalten wurde, und daher wurde meine eigene Verhaltensfunktion nicht erneut angehängt. Der Fehler wurde in der Konsole angezeigt.
Der Colorbox-Fehler: in 7.24
und in 7.25
Meine Lösung bestand darin, das Colorbox-Modul zu deaktivieren.
Vielen Dank an alle, die geholfen haben.
quelle
Ich kann die erste Antwort nicht kommentieren , aber Sie können die Eigenschaft für das Farbfeld in den Einstellungen festlegen. Zum Beispiel:
quelle