1

I am trying to load JS files in my theme's to footer.All my custom JS files are being added to WordPress using wp_enqueue_script, but i am unable to find any way which will help me to load them in footer.

one possible way is to

remove_action('wp_head', 'wp_print_scripts');
remove_action('wp_head', 'wp_print_head_scripts', 9);
add_action('wp_footer', 'wp_print_scripts', 5);
add_action('wp_footer', 'wp_enqueue_scripts', 5);

but that means , I need to list down all possible JS files being used in plugins and than remove those from header and add them to footer, but that seems a bit strange to me as I need to take care what new plugin i have added or removed.

Is there any other alternate where i can let Wordpress load those JS files (including Plugin's) in footer section.

Since I can add/ remove plugin, so i am not sure how to handle it.

8
  • What do you mean by I need to list down all possible JS files being used in plugins and than remove those from header and add them to footer. Did you test the code snippet?
    – birgire
    Commented Nov 17, 2013 at 10:30
  • @birgire: By that i mean, I need to see what all JS files are being used and loaded by plugins. I have limited knowledge about WordPress so might be missing something Commented Nov 17, 2013 at 10:33
  • 1
    do you want to load all javascript files in the footer, both from plugins and the theme? The above code snippet should do it all for you, but maybe I'm misunderstanding the question ;-)
    – birgire
    Commented Nov 17, 2013 at 10:35
  • @birgire:Yes that is true I want to load all JS in footer, only issue i can see with Jquery core but will be able to handle that. Commented Nov 17, 2013 at 10:39
  • 1
    While not impossible some scripts are supposed to be in header (async loaders and analytics, etc). I would never recommend to do this blindly in bulk for all scripts.
    – Rarst
    Commented Nov 17, 2013 at 16:33

3 Answers 3

2

Check out this tutorial by kaiser and go step by step:

Every time I register a script and add jquery as dependency, it gets added to the <head> in the finally rendered HTML page. As this blocks page rendering time – the included script might modify the DOM – I want to add it to the end of the page to prevent this behavior. This will make Google happy and positively influence my page rank as page loading time should decrease.

class RegisterScripts
{
    public function __construct()
    {
        add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
    }

    public function scripts()
    {
        wp_enqueue_script(
            'requirejs',
            get_stylesheet_directory_uri().'/assets/scripts/vendor/requirejs/require.js',
            array( 'jquery' ),
            filemtime( plugin_dir_path( __FILE__ ).'assets/scripts/vendor/requirejs/require.js' ),
            true
        );
    }
}

So what does core do then? Actually it’s quite easy. The WP_Scripts class is an extension for the class WP_Dependencies. And when you make a call to wp_enqueue/register_script(), it just uses the add_data() method from there.

$wp_scripts->add( $handle, $src, $deps, $ver );
if ( $in_footer )
    $wp_scripts->add_data( $handle, 'group', 1 );

As you can see, it adds “data” with the script name as a first argument and sets some group to 1. This just tells the class where to put the the script data in the global array. Then, when looping through the array, WP just checks the current hook and prints either the default part or, in case of the end of the page, the wp_footer hook, all scripts that have a group equal and/or higher than 1. That’s it.

Now to the part where we quickly fix that:

// Move jQuery to the footer
global $wp_scripts;
$wp_scripts->add_data( 'jquery', 'group', 1 );

Of course you can do that with every other script as well. A (maybe incomplete) list of default scripts can be found in Codex. If you want to have the real list, you’ll have to dump $GLOBALS['wp_scripts'] and look through the array. In case you want to wrap all this up in a standalone plugin, you of course can do. I recommend using a mu-plugin.

/* Plugin Name: jQuery to the footer! */
add_action( 'wp_enqueue_scripts', 'wcmScriptToFooter', 9999 );
function wcmScriptToFooter()
{
    global $wp_scripts;
    $wp_scripts->add_data( 'jquery', 'group', 1 );
}

Keep in mind that there might be plugin or theme scripts doing things wrong(!) and this solution might break. Normally this would happen if the custom scripts are loaded into the header or if the whole WP Dependency API is bypassed and the script hard coded. Conclusion: Test before you add that mini plugin to an already live page. If it doesn’t work, inspect where and how the script loading works. Then fix that and try to load those blocking scripts to the footer as well. Google will love you.

If you want to go further, here’s a related recommendation. If you want to create JavaScript classes, take a look at JavaScript++.

2

Not sure why @RockerMaruf answer got downvoted. That is the best way to do this.

The example you have in your question can be used like this below (as seen in roots/soil plugin), but as @Rarst suggested it will break some things (like html5shiv) meant to be loaded in the header.

function all_js_to_footer() {
  remove_action('wp_head', 'wp_print_scripts');
  remove_action('wp_head', 'wp_print_head_scripts', 9);
  remove_action('wp_head', 'wp_enqueue_scripts', 1);
}
add_action('wp_enqueue_scripts', 'all_js_to_footer');

If you know what the script is that needs to be loaded in the head you could just dequeue it and add it using wp_head... or have a fallback/check, maybe something like this:

add_action( 'wp_head', 'wp_theme_check_html5shiv', 1 );
function wp_theme_check_html5shiv() {
    if ( !has_filter( 'wp_head', 'wp_enqueue_scripts' ) && !wp_script_is( 'html5shiv', 'done' ) ) {
        add_action('wp_head', 'wp_theme_echo_html5shiv');
        wp_dequeue_script('html5shiv');
    }
}
function wp_theme_echo_html5shiv() {
    echo '<!--[if (gt IE 5)&(lt IE 9)]> <script>window.html5={shivCSS:!1};</script> <script src="https://cdn.jsdelivr.net/html5shiv/3.7.3/html5shiv.min.js"></script> <![endif]-->' . "\n";
}

While the above fallback seems to work, it's pretty ugly and ridiculous.

So using the @kaiser method is the best approach, although here's a slightly modified approach ( thanks to a [discussion] with Theme Review Team's Ulrich Pogson on Github(https://github.com/roots/soil/issues/33#issuecomment-173838447) ) using new wordpress functions and not accessing globals directly.

Best Known Approach as of Jan 2016

function move_js_to_footer() {
    foreach( wp_scripts()->registered as $script ) {
        if ( 'html5' == $script->handle ) {
            wp_script_add_data( $script->handle, 'group', 0 );
        } else {
            wp_script_add_data( $script->handle, 'group', 1 );
        }
    }
}
add_action( 'wp_enqueue_scripts', 'move_js_to_footer', 99 );
0

From the Codex :

$in_footer (boolean) (optional) Normally, scripts are placed in of the HTML document. If this parameter is true, the script is placed before the end tag. This requires the theme to have the wp_footer() template tag in the appropriate place.

    Default: false

So if your script is myscript.js, I'd try something like

wp_enqueue_script('myscript', bloginfo('template_url').'/js/myScript.js'__FILE__), array(), 'version', true );
2
  • The OP seems to be wanting to force all scripts to the footer and not just scripts under his/her control.
    – s_ha_dum
    Commented Nov 17, 2013 at 16:22
  • Right. Then I'd use the plugins_loaded hook. Write a function that does the head removal / footer add (like the code the OP wrote, but inside a function) then use it in add_action( 'plugins_loaded', 'put_js_in_footer' );
    – AurelienT
    Commented Nov 17, 2013 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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