Manejo de colisión de componentes jQuery

14 abr 2012, 16:45:30
Vistas: 849
Votos: 4

En el desarrollo de plugins, ¿cuál es la mejor práctica para prevenir colisiones de componentes jQuery en el front-end?

Por ejemplo, supongamos que incluyo el diálogo jQuery Apprise en un plugin que lo carga en el front-end para algo, pero otro plugin podría hacer lo mismo. Debido a que esto se carga y declara dos veces, o quizás uno está bifurcado y personalizado mientras que el mío no, obtenemos errores de Javascript en el frontend (asumo).

(Nota que estoy siguiendo la mejor práctica de usar la estrategia wp_register_script() y wp_enqueue_script() a través de un evento de acción wp_head() para cargar un componente jQuery en el frontend).

1
Comentarios
Todas las respuestas a la pregunta 3
2

Mi sugerencia sería usar una combinación de aislamiento de código en una función anónima y verificar si jQuery ya está presente.

Aquí tienes un ejemplo:

(function() {

var jQuery;  // tu variable jquery

// verificar si jQuery está presente y si tiene la versión que deseas
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.8.3') {

    // cargar la biblioteca jQuery desde las librerías alojadas en Google
    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");

    // esperar a que cargue la biblioteca jQuery
    if (script_tag.readyState) {
      script_tag.onreadystatechange = function () { // versiones antiguas de IE
          if (this.readyState == 'complete' || this.readyState == 'loaded') {
              jqueryLoadHandler();
          }
      };
    } else { // para otros navegadores
      script_tag.onload = jqueryLoadHandler;
    }

    // Intentar encontrar el head, de lo contrario usar documentElement por defecto
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

} else {

    // El sitio ya está usando el jQuery que deseas, así que simplemente apunta tu variable a ese jQuery
    jQuery = window.jQuery;
    main();
}

// tan pronto como jQuery se cargue
function jqueryLoadHandler() {
    // Restaurar $ y window.jQuery a sus valores anteriores y almacenar el
    // nuevo jQuery en nuestra variable local jQuery
    jQuery = window.jQuery.noConflict(true);

    // Llamar a la función principal del plugin
    main(); 
}

// función principal del plugin
function main() { 
    jQuery(document).ready(function($) { 
        // Aquí puedes usar $ sin ningún problema
    });
}

})(); // Llamamos inmediatamente a nuestra función anónima

De esta manera puedes usar jQuery sin problemas en tu plugin, incluso si otros plugins usaron jQuery sin wp_enqueue_script. Todas las variables y funciones que uses dentro de esta función anónima no interferirán con el resto de la página.

Quizás esto podría funcionar aún mejor si se integrara con wp_enqueue_script.

Puedes leer más sobre este enfoque de cargar jQuery dentro de una función anónima en http://alexmarandon.com/articles/web_widget_jquery/

14 dic 2012 13:02:34
Comentarios

Nota: esta pregunta es sobre bibliotecas de terceros (plugins, etc.).

fuxia fuxia
14 dic 2012 13:04:52

sí, lo entiendo. Es solo una sugerencia. Por ejemplo, en esta situación si jquery apprise se cargara de esta manera, no interferiría con otros apprise cargados por otros plugins.

dbeja dbeja
14 dic 2012 13:14:06
0

El problema con el núcleo de jQuery es muy común y muchos plugins tienen varias formas de prevenirlo.

Cuando hablamos de plugins para jQuery existe otro problema pero puedes eliminarlo de manera similar.

En tu situación prefiero la solución común de agregar un interruptor de inclusión en la página de configuración de tu plugin - creo que esto es muy popular para plugins con el núcleo de jQuery, pero también puedes usarlo para plugins de jQuery.

Otra solución es escribir un script en js para verificar si el método extra de jQuery (del plugin) está definido, cuando no lo esté puedes incluir el plugin en tu script. Esta solución solo funcionará si agregas un hook para scripts con una prioridad muy baja. Se ejecutará después de otros plugins y esta condición funcionará.

16 dic 2012 15:35:09
0

La mejor práctica para encolar o registrar scripts es usar wp_register_script y wp_enqueue_script. Los plugins y temas que no usan estas funciones para agregar sus scripts no deberían utilizarse.

La razón es simple: con wp_register_script() podemos obtener mucha información sobre los scripts registrados. Especialmente si una fuente determinada ya está registrada o no.

Escribí una clase simple para probar si una fuente ya está registrada. La clase puede desregistrar el script y registrar el nuevo script o omitir el nuevo script. Esta clase debería ser un punto de partida para tu propio desarrollo. ¡No es para entornos de producción!

¿Cómo funciona la clase?

La clase recupera un array con los scripts que deben registrarse. Luego compara los nombres de archivo (y solo los nombres de archivo) de cada script registrado con los nombres de archivo de los scripts que deben registrarse. Si el script/nombre de archivo no está registrado, su handle se agregará a un array y se registrará más adelante.

La clase se puede extender para comparar la ruta completa del script, la versión o lo que sea necesario para decidir si el script debe registrarse o no.

Un ejemplo 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'] );

Primero definimos un array con todos nuestros scripts para registrar. La clase recorrerá nuestros scripts y comparará si la fuente ya está registrada.

  • El script foo siempre se registrará porque la fuente no está registrada.
  • El script bar nunca se registrará porque su fuente ya está registrada.
  • El script jquery es un caso especial. Ya existe un handle llamado jquery, pero el segundo parámetro en la llamada a la clase indica que esta fuente de script debe reemplazarse por la nueva fuente.

Como puedes ver en el var_dump(), la fuente del script jquery fue reemplazada por la clase. Entonces, si extiendes la clase y ajustas la prueba (fuente, nombre de archivo js, versión, scripts encolados, etc.), podría ayudar a minimizar las colisiones de js.

16 dic 2012 22:38:01