Is this a bad implementation of wp_enqueue_script for conditional usage?

Conditionally Including scripts whether js or css in xhtml document head…has been a generally tricky affair, especially if you want to enqueue something, based on a shortcode or custom meta field or a widget.

If you know that you need your script for sure,you would just do what the WordPress Codex suggest by using wp_enqueue_script with following hooks,

* init
* template_redirect
* admin_print_scripts

But sometimes you require a more nuance inclusion of a script or stylesheet. Script inclusions based on shortcodes for example. The issue with shortcodes is that you couldn’t really tell if a shortcode has been used, unless you apply strpos() on the content. The reason for this is because, the ‘init’ + ‘template_redirect’ + ‘admin_print_scripts’ hooks fire before the WP_Query object is set, i believe. So it can get tricky for conditionally including scripts for shortcodes and other triggers.

To circumvent this, you can use strpos() with ‘the_posts’ hook, which gets fired before wp_head. But one of the drawbacks is that its an extra pass at the data.

Discussed at http://beerpla.net/2010/01/13/wordpress-plugin-development-how-to-include-css-and-javascript-conditionally-and-only-when-needed-by-the-posts/

Additionally, i havn’t seen examples of this enqueue scripts with this hook being able inject js or css in the head of the document

Scribu suggest, using a flag variable, and sending it to the footer, http://scribu.net/wordpress/optimal-script-loading.html …but that’s not feasible for css style sheets that should be included in the head portion of the document

I’ve been pondering the best compromise,and wanted to know your thoughts.
basically, my hook of choice is wp_head, because i have access to the WP_Query object, in case i need to search for the shortcode, or use a conditional tag, or even widget usage detection. If i know that i need to inject css or js, then i can just recall the wp_print_scripts() function, after figuring out if the page needs my js or css.

Here is a framework for script inclusion on WP 3.1…i’ve used it successfully for js inclusion. Havn’t tried it for CSS yet, but i suspect it will work the same.

add_action("wp_head","add_conditional_scripts", 20);
function add_conditional_scripts() {
   global $posts, $wp_scripts;

    foreach ($posts as $post) { 
        if ( condition_gets_met == true ) : 
            wp_enqueue_script( "scripthandle" , get_home_url().'/js/scriptfilename.js, array('jcycle'), '1.0', true);   // This will add to the $wp_scripts variable
        endif;
    }

   wp_print_scripts(); // This uses the $wp_script object, will print, out the newly enqueue script
}

Note that the *condition_gets_met is a stand in for strpos check or a conditional tag, or custom_meta_field check.

Any feed back or criticisms of doing it this way would be great.

3 Answers
3

To circumvent this, you can use strpos() with the_posts hook, which gets fired before wp_head. But one of the drawbacks is that its an extra pass at the data.

You’re essentially doing the same inside the callback you’re hooking onto wp_head, i don’t see the difference.. (please clarify if you think otherwise)..

Whether you hook onto the_posts or wp_head you’re still iterating over the same array data, ie. $posts..

I personally don’t see the issue with setting a flag inside the the_posts hook and if there’s a concern that the hook may get called multiple times, simply check for the flag at the start of the callback and return if it’s already set(ensuring only one iteration over that array).

I’m actually using this approach in a plugin i’m waiting to release, and i also realised the method Scribu posted about doesn’t really work when you’re using CSS, which can’t go in the foot. Scribu mentioned possibly injecting CSS into the head with JS, but i personally find that somewhat hacky(my personal opinion).

I have a function hooked onto the_posts which goes like this..

public function on_the_posts( $posts ) {

    if( empty( $posts ) || $this->has_tabs )
        return $posts;

    // trimmed code not relevant to the example

    foreach( $posts as $post ) {
        if( !stripos( $post->post_content, '[end_tabset]' ) )
            continue;
        $this->has_tabs = true;
    }

    return $posts;
}

How would this be any different inside a callback on wp_head, i’m still going to need to iterate over $posts aren’t i?

Is this a bad implementation of wp_enqueue_script for conditional usage?

No, i don’t think so personally.

Leave a Comment