Después de reasignar jQuery a $ en mi tema de WordPress, ya no puedo activar funciones desde fuera del archivo js

4 minutos de lectura

avatar de usuario
Barba Siniestra

Estoy trabajando en un tema de WordPress con mucho jQuery. Por defecto, WordPress no le permite usar el $ atajo y tienes que usar todo el jQuery en cambio – por ejemplo jQuery('.class') más bien que $('.class').

Esto no es demasiado complicado con unas pocas líneas de código, pero ahora tengo mucho, así que reasigné jQuery a $ usando:

(function($){

    ...my functions here...

})(window.jQuery);

Esto funciona bien para las funciones activadas desde dentro de ese archivo, pero si utilizo activadores en línea en PHP, ya no funcionan. Por ejemplo:

<a onclick="loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)">Read more</a>

funcionó bien antes de la reasignación, pero ahora no. No puedo vincular el evento como de costumbre dentro del archivo js, ​​porque no podré acceder a las funciones de PHP y WordPress que necesito, a menos que me falte algo. Por ejemplo, esto no funcionaría:

$( "#target" ).click(function() {    
    loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)    
});

¿Hay alguna forma de evitar esto?

avatar de usuario
TJ Crowder

El problema es que sus funciones ya no son globales. Esto es algo bueno™. (Vea a continuación por qué).

¿Hay alguna forma de evitar esto?

Con mucho, la mejor manera sería no conectar eventos como ese. En su lugar, mantenga su código y marcado separados, y conecte sus funciones usando jQuery’s on y similares Vea a continuación para obtener más información.

Pero si siente que tiene que hacerlo, puede hacer que sus funciones sean globales asignándolas como propiedades en window:

(function($) {
    window.loadFullPost = function() {
        // ...
    };
)(jQuery);

o

(function($) {
    function loadFullPost() {
        // ...
    }

    window.loadFullPost = loadFullPost;
)(jQuery);

Entonces, ¿cómo harías?

<a onclick="loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)">Read more</a>

…sin usar una función global? Como esto:

<a class="load-full-post" data-permalink="<?=get_permalink()?>" data-ajax=true data-post-name="<?=$post->post_name?>" data-post-id="<?=$post->ID?>">Read more</a>

y luego un controlador para ellos

$(document).on("click", ".load-full-post", function() {
    var link = $(this);
    // Use the values from link.attr("data-permalink") and such
    // to do the work
});

O si desea utilizar su actual loadFullPost función:

$(document).on("click", ".load-full-post", function() {
    var link = $(this);
    return loadFullPost(
        link.attr("data-permalink"),
        link.attr("data-ajax") === "true",
        link.attr("data-post-name"),
        +link.attr("data-post-id")  // (+ converts string to number)
    );
});

Debo mencionar que obtendrá personas que le dirán que acceda a esos data-* atributos a través de data función. Tú pueden hacer eso, pero a menos que esté utilizando las diversas características adicionales de dataes una sobrecarga innecesaria (crear el caché de jQuery para los datos, etc.). data es no una función accesoria para data-* atributos, es mucho más (y menos) que eso.

También puede pasar su información como JSON:

<a class="load-full-post" data-postinfo="<?=htmlspecialchars(json_encode(array("permalink" => get_permalink(), "ajax" => true, "name" => $post->post_name, "id" => $post->ID))0?>">Read more</a>

(o algo así, mi PHP-fu es débil)

Después:

$(document).on("click", ".load-full-post", function() {
    var postInfo = JSON.parse($(this).attr("data-postinfo"));
    return loadFullPost(
        postInfo.permalink,
        postInfo.ajax,
        postInfo.name,
        postInfo.id
    );
});

Por qué hacer que sus funciones no sean globales es algo bueno™: El espacio de nombres global es muy abarrotado, particularmente cuando se trata de múltiples scripts y complementos y WordPress mismo. Cuantos más elementos globales cree, mayores serán las probabilidades de que entren en conflicto con uno de otro script. Al tener sus funciones bien contenidas dentro de su función de alcance, evita la posibilidad de pisotear la función/elemento/lo que sea de otra persona y viceversa.

  • excelente respuesta y explicacion

    – Tiempo de estudio

    16 de octubre de 2015 a las 7:27

  • Gracias por esto: excelente explicación no solo del cómo sino también del por qué. ¡Funciona, y más rápido que antes! Usé el segundo ejemplo (llamar con una función no global pero usando la función existente) ya que también se llama en otros lugares. Se requirió un cambio muy leve en el sentido de que los criterios ajax en realidad se establecen como parte del enlace en lugar de su propia entrada de datos, pero esto no quedó claro en mi pregunta.

    – Barba Siniestra

    16 de octubre de 2015 a las 7:57

Puede agregar una función desde su gabinete a una ventana así:

(function($){

    function loadFullPost(...) {
        ...
    }

    window.loadFullPost = loadFullPost;

}).(window.jQuery);

Entonces su función será visible para el atributo onlick, etc.

¿Ha sido útil esta solución?