web-dev-qa-db-fra.com

Traitement de la collision de composants jQuery

Dans le développement de plug-in, quelle est la meilleure pratique pour éviter les collisions de composants jQuery sur le front-end?

Par exemple, supposons que j'inclue la boîte de dialogue jQuery Apprise dans un plug-in qui le charge sur le serveur pour quelque chose, mais qu'un autre plug-in peut faire de même. Parce que cela est chargé et déclaré deux fois, ou peut-être un est-il créé et personnalisé alors que le mien ne l'est pas, nous avons des erreurs Javascript sur le front-end (je suppose).

(Notez que je m'engage à utiliser les stratégies wp_register_script () et wp_enqueue_script () via un événement d'action wp_head () afin de charger un composant jQuery sur l'interface.)

4
Volomike

Le problème avec le noyau jQuery est très courant et de nombreux plugins ont beaucoup de façons de le prévenir.

Lorsque nous parlons de plugins pour jQuery, il existe un autre problème, mais vous pouvez le supprimer de manière similaire.

Dans votre sittuation, je préfère une solution courante pour ajouter un commutateur à la page des paramètres de votre plugin - Je pense que cela est très populaire pour les plugins avec peut aussi l’utiliser pour les plugins jQuery.

Une autre solution consiste à écrire un script en js pour vérifier si la méthode jQuery extra (à partir du plugin) est définie. Sinon, vous pouvez inclure un plugin dans votre script. Cette solution ne fonctionnera que si vous ajoutez un hook pour les scripts avec une priorité très basse. Il fonctionnera après d'autres plugins et cette condition fonctionnera.

1
Maciej Płusa

La meilleure pratique pour mettre en file d'attente ou enregistrer des scripts est d'utiliser wp_register_script et wp_enqueue_script. Les plugins et les thèmes qui n'utilisent pas cette fonction pour ajouter leurs scripts ne doivent pas être utilisés.

La raison est simple: avec wp_register_script(), nous sommes en mesure de récupérer beaucoup d’informations sur les scripts enregistrés. Surtout si une source donnée est déjà enregistrée ou non.

J'ai écrit une classe simple pour vérifier si une source est déjà enregistrée. La classe peut désenregistrer le script et enregistrer le nouveau script ou ignorer le nouveau script. Cette classe devrait être un point de départ pour votre propre développement. C'est pas pour l'environnement de production!

Comment fonctionne la classe?

La classe récupère un tableau avec les scripts à enregistrer. Ensuite, comparez les noms de fichiers (et uniquement les noms de fichiers) de chaque script enregistré avec les noms de fichier des scripts à enregistrer. Si le script/nom de fichier n'est pas déjà enregistré, son handle sera ajouté à un tableau et sera enregistré à un moment ultérieur.

La classe peut être étendue pour comparer le chemin d'accès complet du script ou de la version, ou tout autre élément nécessaire pour décider si le script doit être enregistré ou non.

Un exemple simple

    $my_scripts = array(

            'foo' => array(
                    'src' => 'external/ressource/foo.js',
                    'deps' => array( 'jquery' ),
                    'version' => false,
                    'in_footer' => true
                    ),

            'bar' => array(
                    'src' => home_url( '/wp-admin/js/common.min.js' ),
                    'deps' => false,
                    'version' => false,
                    'in_footer' => true
                    ),

            'jquery' => array(
                    'src' => '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js',
                    'deps' => false,
                    'version' => '1.8.3',
                    'in_footer' => true
                    ),

    );

    $safe_register = new Safe_Registering_Scripts( $my_scripts, true );

    global $wp_scripts;

    var_dump( $wp_scripts->registered['jquery'] );

Au début, nous définissons un tableau avec tous nos scripts à enregistrer. La classe parcourra nos scripts et comparera si la source est déjà enregistrée.

  • le script foo sera toujours enregistré car la source n'est pas enregistrée.
  • le script bar ne sera jamais enregistré car sa source est déjà enregistrée.
  • le script jquery est un cas particulier. Il existe déjà un descripteur appelé jquery mais le deuxième paramètre de l'appel de classe indique que cette source de script doit être remplacée par la nouvelle source.

Comme vous pouvez le constater dans var_dump(), la source du script jquery a été remplacée par la classe. Ainsi, si vous étendez la classe et ajustez le test (source, nom de fichier js, version, scripts en file d'attente, etc.), il pourrait être utile de minimiser les collisions js.

1
Ralf912

Ma suggestion serait d'utiliser un mélange d'isolation de code dans une fonction anonyme et de vérifier si jquery est déjà présent.

Voici un exemple:

(function() {

var jQuery;  // your jquery variable

// check if jquery is present and if it has the version you want
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.8.3') {

    // load jquery lib from google hosted libraries
    var script_tag = document.createElement('script');
    script_tag.setAttribute("type","text/javascript");
    script_tag.setAttribute("src","http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js");

    // wait for jquery lib to load
    if (script_tag.readyState) {
      script_tag.onreadystatechange = function () { // old versions of IE
          if (this.readyState == 'complete' || this.readyState == 'loaded') {
              jqueryLoadHandler();
          }
      };
    } else { // for other browsers
      script_tag.onload = jqueryLoadHandler;
    }

    // Try to find the head, otherwise default to the documentElement
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

} else {

    // The current site is already using the jquery you want, so just point your variable to that jquery
    jQuery = window.jQuery;
    main();
}

// as soons as jquery is loaded
function jqueryLoadHandler() {
    // Restore $ and window.jQuery to their previous values and store the
    // new jQuery in our local jQuery variable
    jQuery = window.jQuery.noConflict(true);

    // Call plugin main function
    main(); 
}

// plugin main function
function main() { 
    jQuery(document).ready(function($) { 
        // Here you can use the $ without any problems
    });
}

})(); // We call our anonymous function immediately

De cette façon, vous pouvez utiliser jQuery sans problème dans votre plugin, même si d'autres plugins utilisaient jQuery sans wp_enqueue_script. Toutes les variables et fonctions que vous utilisez dans cette fonction anonyme n'interféreront pas avec le reste de la page.

Peut-être que cela pourrait fonctionner encore mieux s'il était intégré à wp_enqueue_script.

Vous pouvez en savoir plus sur cette approche de chargement de jquery dans une fonction anonyme dans http://alexmarandon.com/articles/web_widget_jquery/

1
dbeja