it-swarm.com.de

Elegant mit JavaScript auf Widget-Admin-Formularen

Ich arbeite an einem Projekt mit vielen Widgets, und ich denke, es wäre großartig, einen Abschnitt "Weitere Optionen" mit jQuery UI Accordion zu erstellen, der beim Klicken erweitert wird.

Also habe ich 'jquery-ui-accordion' mit der Aktion 'admin_enqueue_scripts' in die Warteschlange gestellt:

function add_my_deps() {
    wp_enqueue_script('jquery-ui-accordion');
}    
add_action( 'admin_enqueue_scripts', 'add_my_deps' );

... und mein JavaScript sieht ungefähr so ​​aus:

(function($){
    $('.more-options-expansible').accordion();
})(jQuery)

Was jetzt?

Wenn ich dies über die Aktion "add_my_deps" in die Warteschlange stelle, funktioniert dies nur, wenn ich die Seite neu lade (dh wenn das Widget platziert wird, wird das JavaScript vor dem Erstellen des Elements instanziiert. Wenn das Widget gespeichert wird, wird das JavaScript wie gewohnt in die Warteschlange gestellt und es wird wie gewohnt instanziiert.).

Wenn ich das in einem <script> -Tag am Ende meiner HTML-Ausgabe in der form() -Methode meines Widgets platziere, wird die folgende Ausnahme angezeigt: Uncaught TypeError: Object [object Object] has no method 'accordion'. Dies liegt daran, dass das Akkordeon scheinbar über den Inline-Code <script> instanziiert wird, bevor die jQuery UI Accordion-Bibliothek geladen wird.

Gibt es etwas, das ich vermisse? Ich verwende eine einfache jQuery-Instanziierung für dieses Beispiel, aber es scheint, als hätte ich noch schlimmere Probleme, wenn ich versucht hätte, etwas mit AJAX zu tun (wie würde ich nämlich das entsprechende Element auswählen, um das zu platzieren?) Antwort in? Muss ich Backbone.js verwenden, um dies zu erreichen?).

Irgendeine Hilfe?

2
aendrew

Ich habe meine Antwort mit meinen Erkenntnissen aus einer früheren Frage bearbeitet, dies sollte Sie jetzt gerade stellen.

Es wird fehlschlagen, da es beim Ausführen von JS gegen das versteckte Widget-Formular auf der linken Seite instanziiert wird. Wenn Sie das Widget in eine aktive Seitenleiste ziehen, wird das ausgeblendete Formular tatsächlich in die rechte Seite geklont, anstatt den Inhalt zu beeinträchtigen. Das heißt, für das neue Widget, das Sie bereits hinzugefügt haben, wurde accordion instanziiert, aber aufgrund des Klonens funktionieren die Dinge anfangs nicht so gut. Natürlich funktioniert es nach einer Seitenaktualisierung einwandfrei.

Damit es beim Hinzufügen eines neuen Widgets wie vorgesehen funktioniert, müssen wir unseren Formularinhalt auf der rechten Seite der Seite ausrichten. Anstatt zu laden, können wir uns auch an das Ereignis ajaxstop binden. Dies liegt daran, dass WordPress nach dem Ablegen des geklonten Widgets auf der rechten Seite eine Ajax-Anfrage zum Speichern der Position des Widgets sendet.

$(document).on('ajaxstop', '#widget-right .more-options-expansible', function(e){
    $(this).accordion();
});    

Dies führt zu einer besseren Lösung als das Hinzufügen der JS-Inline und ermöglicht es Ihnen, die Skripte in der Fußzeile zu belassen.

1
MichaelJames

Eine Möglichkeit, die ich seit dem Posten der obigen Frage gefunden habe, besteht darin, über WP_Widget::form() inline zu instanziieren, wobei wp_enqueue_script() das erforderliche JavaScript lädt (genau wie oben erwähnt) - außer, und hier ist der Schlüsselteil, das JavaScript in den Header zu laden anstelle der Fußzeile (fünftes Argument von wp_enqueue_script()).

Das macht jetzt sehr viel Sinn, wenn ich darüber nachdenke.

Trotzdem hasse ich es, jemals Inline-JavaScript zu verwenden, und alles in den Header zu laden, ist alles andere als ideal.

Lassen Sie diese Frage offen, falls jemand eine bessere Idee hat.

1
aendrew

WordPress hat einige JavaScript-Ereignisse hinzugefügt, 'Widget hinzugefügt', 'Widget aktualisiert', 'Widget synchronisiert', sodass Sie das Ajax-Ereignis nicht mehr hacken müssen.

https://core.trac.wordpress.org/ticket/19675

Ich denke, Sie sollten den Code in Ihrer externen JS-Datei folgendermaßen aktualisieren:

$(document).on('widget-added', function(event, widget) {
   $(widget).find('.more-options-expansible').accordion();
}

Wahrscheinlich müssen Sie ähnliche Elemente für "Widget aktualisiert" und "Widget synchronisiert" hinzufügen, da sie sich alle auf Ihren Dom auswirken.

0
scottsawyer