I released a plugin that creates a shortcode and requires a JavaScript file and a CSS file to load on any page that contains that shortcode. I could just make the script/style load on all pages, but that’s not the best practice. I only want to load the files on pages that call the shortcode. I’ve found two methods of doing this, but both have problems.
Method 1 sets a flag to true inside the shortcode handler function, and then checks that value inside a wp_footer
callback. If it’s true, it uses wp_print_scripts()
to load the JavaScript. The problem with this is that it only works for JavaScript and not CSS, because CSS should be declared inside <head>
, which you can only do during an early hook like init
or wp_head
.
Method 2 fires early and “peeks ahead” to see if the shortcode exists in the current page content. I like this method much better than the first, but the problem with it it won’t detect if the template calls do_shortcode()
.
So, I’m leaning towards using the second method and then trying to detect if a template is assigned, and if so, parse it for the shortcode. Before I do that, though, I wanted to check if anyone knows of a better method.
Update: I’ve integrated the solution into my plugin. If anyone is curious to see it fleshed out in a live environment you can download it or browse it.
Update 2: As of WordPress 3.3, it’s now possible to call wp_enqueue_script()
directly inside a shortcode callback, and the JavaScript file will be called within the document’s footer. That’s technically possible for CSS files as well, but should be considered a bad practice because outputting CSS outside the <head>
tag violates W3C specs, can case FOUC, and may force the browser to re-render the page.
Based on my own experience, I’ve used a combination of method 1 & 2 – the architecture and footer scripts of 1, and the ‘look-ahead’ technique of 2.
For the look-ahead though, I use regex in place of
stripos
; personal preference, faster, and can check for ‘malformed’ shortcode;If you’re concerned about authors using
do_shortcode
manually, I would opt to instruct them touse an action callenqueue your pre-registered style manually.UPDATE: For the lazy author who never RTFM, output a message to highlight the error of their ways 😉
I’m late answering this question but since Ian started this thread on the wp-hackers list today it made me think it worth answering especially considering I’ve been planning to add such a feature to some plugins I’ve been working on.
An approach to consider is to check on the first page load to see if the shortcode is actually used and then save the shortcode usage status to a post meta key. Here’s how:
Step-by-Step How-To
$shortcode_used
flag to'no'
.$shortcode_used
flag to'yes'
.'the_content'
hook priority12
which is after WordPress has processed shortcodes and check post meta for a''
using the key"_has_{$shortcode_name}_shortcode"
. (A value of''
is returned when a post meta key doesn’t exist for the post ID.)'save_post'
hook to delete the post meta clearing the persistent flag for that post in case the user changes shortcode usage.'save_post'
hook usewp_remote_request()
to send a non-blocking HTTP GET to the post’s own permalink to trigger to first page load and the setting of the persistent flag.'wp_print_styles'
and check post meta for a value of'yes'
,'no'
or''
using the key"_has_{$shortcode_name}_shortcode"
. If the value is'no'
don’t serve the external. If the value is'yes'
or''
go ahead and serve the external.And that should do it. I’ve written and tested an example plugin to show how this all works.
Example Plugin Code
The plugin wakes up on a
[trigger-css]
shortcode which sets the<h2>
elements on the page to white-on-red so you can easily see it working. It assumes acss
subdirectory containingstyle.css
file with this CSS in it:And below is the code in a working plugin:
Example Screenshots
Here’s a series of screenshots
Basic Post Editor, No Content
Post Display, No Content
Basic Post Editor with
[trigger-css]
ShortcodePost Display with
[trigger-css]
ShortcodeNot Sure if it’s 100%
I believe the above should work in almost all cases but as I just wrote this code I can’t be 100% sure. If you can find situations where it doesn’t work I’d really like to know so I can fix the code in some plugins I just added this to. Thanks in advance.
Googling found me a potential answer. I say “potential” as in it looks good, should work, but I’m not 100% convinced it’s the best way to do it:
This should be able to check if the current post is using a shortcode and add a stylesheet to the
<head>
element appropriately. But I don’t think it will work for an index (i.e. multiple posts in the loop) page … It’s also from a 2-yr old blog post, so I’m not even sure it will work with WP 3.1.X.Using a combination of TheDeadMedic’s answer and the get_shortcode_regex() documentation (which actually didn’t find my shortcodes), I created a simple function used to enqueue scripts for multiple shortcodes. Since the wp_enqueue_script() in shortcodes only adds to the footer, this can be helpful as it can handle both header and footer scripts.
Finally I also found a solution for conditional css loading which works for my plugin http://www.mapsmarker.com and I´d like to share with you. It checks if my shortcode is used within the current template file and header/footer.php and if yes, enqueues the needed stylesheet in the header:
For my plugin I found that sometimes users have a theme builder that has shortcode stored in post meta data. Here is what I am using to detect whether my plugin shortcode is present in current post or post meta data:
For CSS files you can load them within your shortcode output:
Set a constant or something after this, like
MY_CSS_LOADED
(only include the CSS if the constant is not set).Both your methods are slower than going this way.
For JS files you can do the same if the script you’re loading is unique and doesn’t have any outside dependencies. If this is not the case load it inside the footer, but use the constant to determine if needs to be loaded or not…