4

I've created some shortcodes and for some of these, I need to load particular scripts on demand.

I've included by default in my function.php file

vendor.js
myscript.js

When i load the shortcode, i need to include a separate script between the two above (meaning that myscript.js requires the new script to be included before it to work).

I've created the shortcode like this:

function callbackService()
{
    ob_start();    
    get_template_part('hg_custom_shortcodes/callback');
    return ob_get_clean();   
}
add_shortcode('callbackService', 'callbackService');

the template is loading an angular app.

I then tried to load my script (the one that needs to be included only when the shortcode is loaded) by changing the snippet above to this:

function callbackService()
{
    ob_start();    
    wp_enqueue_script('angular-bundle', get_template_directory_uri() . '/scripts/angular-bundle.js', array(), false, true);
    get_template_part('hg_custom_shortcodes/callback');
    return ob_get_clean();   
}
add_shortcode('callbackService', 'callbackServhowever

The script is included, hovewer i think it's included after myscript.js and the whole shortcode (angular app) is not working as "Angular is not defined".

How can i tell the enqueue to load the script after? I know that usually i would change the add_action() priority, but in this particular case there's no add_action involved and i don't know what else to try.

Any suggestions? thanks

  • Can you work with the dependancies parameter? (currently array() in your code) – kero Oct 20 '18 at 12:24
  • Hi, i did try using this already with no luck – Nick Oct 21 '18 at 16:08
5

wp_enqueue_script is not going to work in a shortcode, this is because of the loading order.

You could use wp_register_script and then you could wp_enqueue_script in you shortcode function like this example:

// Front-end
function front_end_scripts() {
    wp_register_script( 'example-js', '//example.com/shared-web/js/example.js', array(), null, true );
}
add_action( 'wp_enqueue_scripts', 'front_end_scripts' );

Then you use this in your shortcode:

function example_shortcode() {

   wp_enqueue_script( 'example-js' );
   return; // dont forget to return something

}
add_shortcode( 'example-shortcode', 'example_shortcode' );

Furthermore, you could use has_shortcode to check if a shortcode is loaded:

function custom_shortcode_scripts() {
global $post;
if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'custom-shortcode') ) {
    wp_enqueue_script( 'custom-script');
}
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
  • I did try with register first and then enqueu but with no luck. I wasn't aware of the has_shortcode. I'll try to use this and see if that helps. Thanks for now – Nick Oct 21 '18 at 16:09
  • @Nick You're welcome :) Glad it worked. – Remzi Cavdar Oct 21 '18 at 16:30
  • 1
    This answer is mostly incorrect. wp_enqueue_script works fine on its own in a Shortcode, you don't have to register the script first. Script registration is a convenience feature, note that wp_enqueue_script accepts all the same arguments as wp_register_script. In either case, WordPress can't time travel and load order is exactly the same, late enqueue works because the script is output by the wp_footer() function. – Milo Oct 22 '18 at 15:36
  • @Milo It didn't work for me. I have developed a theme and two plugins. Try for yourself. Maybe I did something wrong, but I doubt it. – Remzi Cavdar Oct 22 '18 at 18:06
  • Tested and confirmed that registration is not necessary. – Milo Oct 23 '18 at 15:03
2

Would has_shortcode help you solve your problem?

On the codex there's an example,

Enqueue some script when some post uses some shortcode

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'custom-shortcode') ) {
        wp_enqueue_script( 'custom-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
0

We can indeed conditionally load CSS and JS files via shortcode without using any overly elaborate functions:

First, let's assume we registered all of our CSS/JS files previously (perhaps when wp_enqueue_scripts ran)

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Next, lets examine our shortcode function:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Simple. Done. Ergo: we can "conditionally load" css/js files, (only when [shortcode] runs).

Let's consider the following ideology:

  • We want to load certain CSS/JS files (but only when shortcode is triggered)
  • Maybe we do not want those files to load on every page, or at all if the shortcode is not used on a page/post. (light weight)
  • We can accomplish this by making sure WP registers ALL of the css/js files prior to calling the shortcode and prior to the enqueue.
  • IE: Maybe during my prep_css_and_js() function I load ALL .css/.js files that are in certain folders...

Now that WP see's them as registered scripts, we can indeed call them, conditionally, based on a verity of situations, including but not limited to my_shortcode_func()

Benefits: (no MySQL, no advanced functions and no filters needed)

  • this is "WP orthodix", elegant, fast loading, easy and simple
  • allows compilers/minifiers to detect such scripts
  • uses the WP functions (wp_register_style/wp_register_script)
  • compatible with more themes/plugins that might want to de-register those scripts for a verity of reasons.
  • will not trigger multiple times
  • very little processing or code is involved

References:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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