Ask your WordPress questions! Pay money and get answers fast! (more info)

conditional loading of css files if do_shortcode() is used WordPress

  • SOLVED

I am the developer of mapsmarker.com and with v3.2 I added conditional loading of my css files - meaning that they will only be loaded when my shortcode is used within content. I do this by the following function:

function lmm_frontend_enqueue_stylesheets() {
$lmm_options = get_option( 'leafletmapsmarker_options' );
global $wp_query;
$posts = $wp_query->posts;
$pattern = get_shortcode_regex();

$plugin_version = get_option('leafletmapsmarker_version');
global $wp_styles;
wp_register_style('leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css', array(), $plugin_version);
wp_register_style('leafletmapsmarker-ie-only', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.ie.css', array(), $plugin_version);

if (is_array($posts)) {
foreach ($posts as $post) {
if ( preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches ) && array_key_exists( 2, $matches ) && in_array( $lmm_options['shortcode'], $matches[2] ) ) {
wp_enqueue_style('leafletmapsmarker');
wp_enqueue_style('leafletmapsmarker-ie-only');
$wp_styles->add_data('leafletmapsmarker-ie-only', 'conditional', 'lt IE 9');
break;
}
}
}
}


Problem is, that this doesnt work if users embedded the shortcode (e.g. [mapsmarker marker="1"]) via do_shortcode() action directly within their template.

This is way I added a check within my shortcode-function (showmap.php) which displays an info if the css-files were not loaded:

global $wp_styles;
if ( (!wp_style_is( 'leafletmapsmarker', 'done' )) || (!wp_style_is( 'leafletmapsmarker-ie-only', 'done' )) ) {
echo "<div style='background:white;border:2px solid red;padding:5px;'><p><strong>Leaflet Maps Marker warning!</strong><br/>You must enqueue the plugin stylesheets manually if you want to show maps by calling do_shortcode() in your template files!</p>";
echo "<p>Please add the following code before your get_header() call inside your template, which is usually located in header.php:<br/><div style='background:#efefef;'>";
echo "\$plugin_version = get_option('leafletmapsmarker_version');<br/>global \$wp_styles;<br/>wp_enqueue_style( 'leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css', array(), \$plugin_version );<br/>wp_enqueue_style( 'leafletmapsmarker-ie-only', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.ie.css', array(), \$plugin_version );<br/>\$wp_styles->add_data('leafletmapsmarker-ie-only', 'conditional', 'lt IE 9');";
echo "</div></p></div>";
}


Unfortunately this is not very usable, especially if users dont have any programming experience.

I would like to enhance my code from above to also enqueue my css files (within </head>) if my shortcode is used within do_action().

What would be a solution here?

Answers (5)

2012-12-12

John Cotton answers:

Well this might help:

function my_template_include( $template ) {

$contents = file_get_contents($template);
if( strpos( $contents, '[mapsmarker' ) != false ) {
// do what you need to do....
}
}
add_action( 'template_include', 'my_template_include' );


That will get you the file for the current page and you can see if it contains your shortcode.

HOWEVER - what it doesn't do is check for included/required files. It would be possible to code for that, but it's not a straightforward task since such files could be pathed or named from variables or functions ( eg include_once( ABSPATH . '/' . $filename ) ) and I can't see how you could work that out without the PHP parser.

So if they used the shortcode in a content loop file for instance, the above code would fail.

But here's an idea (it's ugly but it's the best I've got right now!) - how about capturing whether a template ultimately uses the shortcode in the database? ie when your shortcode runs, update a setting that is an array of template names.

Then, examine that array in the wp_head action (or the code above) and output what you need.

Clearly, this would mean the code failing first time (since the template name wouldn't have been captured). But it will work after that. And most (!) sites have their page viewed by the developer at least once before going live.


Robert Harm comments:

thanks John - that was the right approach. I ended up with this working code:

Finally I also found a solution for conditional css loading which works for my plugin 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:

function prefix_template_check_shortcode( $template ) {
$searchterm = '[mapsmarker';
$files = array( $template, get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'header.php', get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'footer.php' );
foreach( $files as $file ) {
if( file_exists($file) ) {
$contents = file_get_contents($file);
if( strpos( $contents, $searchterm ) ) {
wp_enqueue_style('
leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css');
break;
}
}
}
return $template;
}
add_action('template_include','prefix_template_check_shortcode' );

2012-12-12

Arnav Joy answers:

please see these two articles

http://wordpress.stackexchange.com/questions/20854/conditionally-loading-javascript-css-for-shortcodes

http://kuttler.eu/post/shortcodes-include-css-and-js-only-on-the-correct-blog-pages/


Robert Harm comments:

Hi Arnav,
thanks for the links. Anyway I already found these approaches/blog posts, especially the one by Ian Dunn - I just need more practical example how to use that approaches with the code I posted above.
regards,
Robert

2012-12-12

Dbranes answers:

Hi, the Ian Dunn solution you mention, outlined here:

http://iandunn.name/conditionally-loading-javascript-and-css-in-wordpress-plugins/

is to let the theme developer put some extra code in their functions.php file to tell the plugin which pages (i.e. page slugs) to load the files on, where the theme and the plugin are communication via 'add_filter' hooks.

So is this a solution you might want to use, do handle the do_shortcode part?

Ian Dunn is using this here:
http://plugins.svn.wordpress.org/basic-google-maps-placemarks/tags/1.1.3/core.php


2012-12-12

phppoet answers:

try this
<?php
function lmm_frontend_enqueue_stylesheets() {

$lmm_options = get_option( 'leafletmapsmarker_options' );

global $wp_query;

$posts = $wp_query->posts;

$pattern = get_shortcode_regex();



$plugin_version = get_option('leafletmapsmarker_version');

global $wp_styles;

wp_register_style('leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css', array(), $plugin_version);

wp_register_style('leafletmapsmarker-ie-only', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.ie.css', array(), $plugin_version);



if (is_array($posts)) {

foreach ($posts as $post) {

if ( preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches ) && array_key_exists( 2, $matches ) && in_array( 'your-shortcode, $matches[2] ) ) {

wp_enqueue_style('leafletmapsmarker');

wp_enqueue_style('leafletmapsmarker-ie-only');

$wp_styles->add_data('leafletmapsmarker-ie-only', 'conditional', 'lt IE 9');

break;

}

}


}

add_action( 'wp', 'lmm_frontend_enqueue_stylesheets' ); //add this line


}



?>





global $wp_styles;

if ( (!wp_style_is( 'leafletmapsmarker', 'done' )) || (!wp_style_is( 'leafletmapsmarker-ie-only', 'done' )) ) {

echo "<div style='background:white;border:2px solid red;padding:5px;'><p>Leaflet Maps Marker warning!<br/>You must enqueue the plugin stylesheets manually if you want to show maps by calling do_shortcode() in your template files!</p>";

echo "<p>Please add the following code before your get_header() call inside your template, which is usually located in header.php:<br/><div style='background:#efefef;'>";

echo "\$plugin_version = get_option('leafletmapsmarker_version');<br/>global \$wp_styles;<br/>wp_enqueue_style( 'leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css', array(), \$plugin_version );<br/>wp_enqueue_style( 'leafletmapsmarker-ie-only', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.ie.css', array(), \$plugin_version );<br/>\$wp_styles->add_data('leafletmapsmarker-ie-only', 'conditional', 'lt IE 9');";

echo "</div></p></div>";

}


phppoet comments:

if didn't work try the wp_enqueue_scripts action to call wp register style function.

2012-12-12

jazbek answers:

One quick way that would handle both situations is to load the css via javascript in the function that displays your shortcode, i.e.:

function display_mapsmarker // change this to the name of your shortcode function
{
echo '
<script type="text/javascript">
var stylesheet = document.createElement("link");
stylesheet.type = "text/css";
stylesheet.rel = "stylesheet";
stylesheet.href = "'.$path_to_css.'";
document.getElementsByTagName("head")[0].appendChild(stylesheet);
</script>
';

// rest of your code here
}