web-dev-qa-db-fra.com

Utilisation élégante de JavaScript dans les formulaires d'administration de widgets

Je travaille sur un projet impliquant de nombreux widgets, et je pense que ce serait vraiment génial de créer une section "Plus d'options" construite à l'aide de jQuery UI Accordion, qui se développe lorsque l'utilisateur clique dessus.

J'ai donc mis en file d'attente 'jquery-ui-accordéion' en utilisant l'action 'admin_enqueue_scripts':

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

... Et mon JavaScript ressemble à ceci:

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

Maintenant quoi?

Si je l'envoie en file d'attente via l'action "add_my_deps" ci-dessus, cela ne fonctionne que si je recharge la page (c'est-à-dire, lors du placement du widget, le JavaScript est instancié avant la création de l'élément; si le widget est enregistré, son JavaScript est mis en file d'attente normalement. et il instancie comme d'habitude.).

Si je place cela dans une balise <script> à la fin de ma sortie HTML dans la méthode form() de mon widget, j'obtiens l'exception suivante: Uncaught TypeError: Object [object Object] has no method 'accordion'. En effet, il semble instancier l’accordéon via le <script> inline avant le chargement de la bibliothèque Accordion de jQuery UI.

Y a-t-il quelque chose d'évident qui me manque? J'utilise une instanciation jQuery simple pour cet exemple, mais il semble que j'aurais des problèmes encore plus graves si j'essayais de faire quoi que ce soit avec AJAX (comment choisirais-je l'élément approprié pour placer le Est-ce quelque chose que je dois commencer à utiliser Backbone.js pour accomplir?).

De l'aide?

2
aendrew

J'ai corrigé ma réponse avec les résultats d'une question précédente, cela devrait maintenant vous redresser la tête.

Cela va échouer car, lorsque le JS s'exécute, il est instancié par rapport au formulaire de widget masqué dans la partie gauche. Il s'avère que lorsque vous faites glisser le widget vers une barre latérale active, il clone en fait la forme masquée dans le côté droit, par opposition à une forme ajaxée de son contenu. Cela signifie que le nouveau widget que vous avez déjà ajouté a la variable accordion contre celle-ci, mais que, en raison du clonage, les choses ne fonctionnent pas très bien au départ. Bien évidemment après un rafraîchissement de page cela fonctionnera parfaitement.

Pour que cela fonctionne comme prévu lorsque nous ajoutons un nouveau widget, nous devons cibler le contenu de notre formulaire qui se trouve dans le côté droit de la page. Nous pouvons également accrocher l'événement ajaxstop au lieu de charger. En effet, une fois que le widget cloné est déposé à droite, WordPress envoie une demande ajax pour enregistrer la position des widgets.

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

Cela conduit à une solution plus agréable que l’ajout de JS inline et vous permet de conserver les scripts dans le pied de page.

1
MichaelJames

Depuis que je pose la question ci-dessus, une des solutions consiste à instancier en ligne via WP_Widget::form(), avec wp_enqueue_script() chargeant le code JavaScript nécessaire (exactement comme mentionné ci-dessus) - à l'exception de la partie clé qui charge le code JavaScript dans l'en-tête. au lieu du pied de page (cinquième argument de wp_enqueue_script()).

Ce qui a beaucoup de sens maintenant que j'y pense.

Même quand même, je déteste utiliser du JavaScript inline - de tout temps - et tout charger dans l'en-tête n'est pas idéal.

En tant que tel, je laisse cette question ouverte au cas où quelqu'un aurait une meilleure idée.

1
aendrew

WordPress a ajouté quelques événements JavaScript, 'ajout de widget', 'mis à jour', 'synchronisé' pour que vous n'ayez plus besoin de pirater l'événement ajax.

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

Donc, je pense que vous devriez mettre à jour le code avec quelque chose comme ça dans votre fichier js externe:

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

Vous aurez probablement besoin d'ajouter des mots-clés similaires pour 'widget-updated' et 'widget-synchronisé', car ils affectent tous votre domaine.

0
scottsawyer