Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After remapping jQuery to $ in my WordPress theme, I can no longer trigger functions from outside the js file

I'm working on a WordPress theme with a lot of jQuery in it. By default, WordPress doesn't allow you to use the $ shortcut and you have to use the full jQuery instead - e.g. jQuery('.class') rather than $('.class').

This isn't too much of a hassle over a few lines of code, but I've got a lot now, so I remapped jQuery to $ using:

(function($){

    ...my functions here...

})(window.jQuery);

This works fine for functions triggered from within that file, but if I use any inline triggers in the PHP, they no longer work. For example:

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

worked fine before remapping but doesn't now. I can't bind the event as usual within the js file, because I won't be able to access the PHP and WordPress functions I need - unless I'm missing something. For example, this wouldn't work:

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

Is there any way around this?

like image 428
Sinister Beard Avatar asked Oct 15 '15 13:10

Sinister Beard


1 Answers

The issue is that your functions are no longer globals. This is a Good Thing™. (See below for why.)

Is there any way around this?

By far the best way would be to not hook up events like that. Instead, keep your code and markup separate, and hook up your functions using jQuery's on and similar. See below for more.

But if you feel you have to, you can make your functions globals by assigning them as properties on window:

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

or

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

    window.loadFullPost = loadFullPost;
)(jQuery);

So how would you do

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

...without using a global function? Like this:

<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>

and then one handler for them

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

Or if you wanted to use your existing loadFullPost function:

$(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)
    );
});

I should mention that you'll get people telling you to access those data-* attributes via the data function. You can do that, but unless you're using the various additional features of data, it's unnecessary overhead (creating jQuery's cache for the data, etc.). data is not an accessor function for data-* attributes, it's much more (and less) than that.

You can also pass your information as 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>

(or something like that, my PHP-fu is weak)

Then:

$(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
    );
});

Why making your functions non-global is a Good Thing™: The global namespace is very crowded, particularly when you're dealing with multiple scripts and plugins and Wordpress itself. The more globals you create, the greater the odds of conflicting with one from another script. By having your functions nicely contained inside your scoping function, you avoid the possibility of stomping on someone else's function/element/whatever and vice-versa.

like image 170
T.J. Crowder Avatar answered Oct 20 '22 10:10

T.J. Crowder