Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

In my theme's functions.php, I'm calling an add_action in order to gain a measure of control on where jquery is loaded (in the footer along with my theme's other scripts).

The problem I'm having is that when I use add_action('wp_enqueue_scripts'), it only appears to fire if no plugins are loaded. However, the add_action('init') method works in all cases.

I can't recall why, but I believe that add_action('wp_enqueue_scripts') is preferred in this case. If that's true, how can I get it to work in all cases?

In functions.php

//if(!is_admin()){add_action('init', 'my_theme_init');} //THIS WORKS ALL THE TIME
//add_action('wp_enqueue_scripts', 'my_theme_init'); //THIS ONLY WORKS WHEN NO PLUGINS PRESENT

if(!is_admin())
{
    require_once(TEMPLATEPATH . '/functions_public.php');   
}

In functions_public.php

function my_theme_init()
{

/* PREVENT DUPLICATE COPIES OF JQUERY FROM PLUGINS
**************************************************/
wp_deregister_script('jquery');

/* LOAD THE LOCAL WORDPRESS COPY OF JQUERY AND THEME CUSTOM SCRIPTS IN THE FOOTER
***********************************************/
wp_register_script('jquery', get_bloginfo('template_directory').'/scripts.mythemescripts.js',false,false,true);

wp_enqueue_script('jquery');

}

The 2nd method, using add_action('wp_enqueue_scripts') apparently does not get executed in conditions where a plugin is present that writes out script dependencies to the theme.

share|improve this question
3  
Please don't register your own copy of jquery - use the version shipped with WordPress, else you'll end up breaking plug-ins :) –  Stephen Harris Jun 20 '12 at 15:02
    
I agree, actually I am using the one shipped with jQuery. I'm just loading it into a single .js (mythemescripts.js) along with the other js files my theme needs, in order to reduce http requests. –  N2Mystic Jun 20 '12 at 15:11
    
In all browsers, once the script is requested from your site once, it's cached locally. You'll only have the extra HTTP request on the very first page load. If you combine all of the scripts into a single one, you'll be forced to change this every time WP releases an update with a new version of jQuery. This == maintenance nightmare. –  EAMann Jun 20 '12 at 15:17
2  
@EAMann, when the theme is first installed, and each time my theme options page is saved thereafter, I'm rewriting the mythemescripts.js, loading the latest copy of the jquery library into it. If the user updates their WP version, my theme options routine loads the jquery that comes with that. Its always up to date. –  N2Mystic Jun 20 '12 at 15:22
    
Noted. And fantastic! –  EAMann Jun 20 '12 at 15:29

2 Answers 2

up vote 9 down vote accepted

A lot of plugin developers don't do things the right way. The right way is to hook on to wp_enqueue_scripts like you're trying to do.

However, here's the order of the hooks run in a typical request:

  • muplugins_loaded
  • registered_taxonomy
  • registered_post_type
  • plugins_loaded
  • sanitize_comment_cookies
  • setup_theme
  • load_textdomain
  • after_setup_theme
  • auth_cookie_malformed
  • auth_cookie_valid
  • set_current_user
  • init
  • widgets_init
  • register_sidebar
  • wp_register_sidebar_widget
  • wp_default_scripts
  • wp_default_stypes
  • admin_bar_init
  • add_admin_bar_menus
  • wp_loaded
  • parse_request
  • send_headers
  • parse_query
  • pre_get_posts
  • posts_selection
  • wp
  • template_redirect
  • get_header
  • wp_head
  • wp_enqueue_scripts
  • wp_print_styles
  • wp_print_scripts
  • ... a lot more

The thing is, several developers were originally told to hook on to init for enqueue-ing their scripts. Back before we had a wp_enqueue_script hook, that was the "correct" way to do things, and tutorials perpetuating the practice are still floating around on the Internet corrupting otherwise good developers.

My recommendation would be to split your function into two parts. Do your wp_deregister_script/wp_register_script on the init hook and use the wp_enqueue_scripts hook when you actually enqueue jQuery.

This will keep you in the world of "doing it right" for enqueue-ing your scripts, and will help protect you from the hundreds of developers still "doing it wrong" by swapping jQuery for your concatenated version before they add it to the queue.

You'll also want to add your init hook with a high priority:

add_action( 'init', 'swap_out_jquery', 1 );
function swap_out_jquery() {
    // ...
}
share|improve this answer
    
+1 Very helpful answer. Testing it now. –  N2Mystic Jun 20 '12 at 15:49
    
I was going to recommend this, but then I realized that the OP was actually deregistering jQuery, and then registering a different script entirely and calling it "jquery". I don't think that's a good practice to encourage, and think that a better route would be simply to dequeue jQuery entirely, and then enqueue the custom script using a custom handle. –  Chip Bennett Jun 20 '12 at 15:51

There are multiple issues here, that are inter-related.

  1. The correct action hook to use to enqueue scripts is wp_enqueue_scripts
  2. To print scripts in the footer via wp_enqueue_script(), set the $footer parameter to true
  3. Your add_action( $hook, $callback ) calls should not be wrapped in anything; let them execute directly from functions.php
  4. You should put your is_admin() conditional checks inside your callback
  5. You shouldn't deregister core-bundled scripts from a Theme, for any reason. Even if your purpose is script concatenation, that's Plugin territory.
  6. If you must deregister jquery, then wp_enqueue_scripts is too late. Split your deregister/register code into a callback hooked into init.
  7. Calling some other script "jquery" is also probably not a good practice. Your better bet would simply be to dequeue jQuery, and then load your custom script.
  8. Be sure to put a low priority on your callback, so you override Plugins
  9. Use get_template_directory() rather than TEMPLATEPATH

Putting it all together:

<?php
function wpse55924_enqueue_scripts() {
    if ( ! is_admin() ) {

        // Dequeue jQuery
        wp_dequeue_script( 'jquery' );

        // Register/enqueue a custom script, that includes jQuery
        wp_register_script( 'mythemescripts', get_template_directory_uri() . '/scripts.mythemescripts.js', false, false,true );
        wp_enqueue_script( 'mythemescripts' ); 
    }
}
add_action( 'wp_enqueue_scripts', 'wpse55924_enqueue_scripts', 99 );

But again: this is really not the best approach. Your better bet is simply to remove plugin add_action() callbacks that deregister core jQuery - or use Plugins that don't do something so reckless as replacing core-bundled jQuery.

share|improve this answer
    
The OP is combining the WP-distributed version of jQuery with some other scripts programatically so that only one HTTP request is made by his theme to load all the JS files. So the custom scripts does contain jQuery and won't break anything if loaded this way. Overwriting the registered 'jquery' handle is necessary to prevent loading jQuery twice - once in the combined JS file and again by any plugins attempting to enqueue jQuery on their own. –  EAMann Jun 20 '12 at 15:59
    
It is semantically and practically _doing_it_wrong() to call something that isn't just jQuery "jQuery". Also: jQuery itself can simply be dequeued in order to ensure that it isn't loaded twice. The wp_dequeue_script() call just needs to happen with a sufficient priority to ensure that nothing enqueues it afterward. –  Chip Bennett Jun 20 '12 at 16:09
    
Hi Chip, I'm testing your example, but in this case, Jquery is showing up twice. Does this mean the plugin I'm using to test is not loading jquery properly? If so, can you address that in your example? –  N2Mystic Jun 20 '12 at 16:19
    
What Plugins are you using? My guess is that a Plugin is hooking into wp_head or wp_print_scripts to output jquery, or is enqueuing its own custom version. –  Chip Bennett Jun 20 '12 at 16:31
    
I'm testing with a random plugin that has a jquery dependency that breaks the example. It loads it with wp_enqueue_script('jquery') wrapped inside add_action('wp_print_scripts') –  N2Mystic Jun 20 '12 at 16:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.