For the next version of my plugin www.mapsmarker.com I would like to output the plugin´s css and js-files only
if the shortcode [mapsmarker ...] is used. For posts/and pages I already found this working code:
function lmm_detect_shortcode()
{
global $post;
$pattern = get_shortcode_regex();
preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches );
if( is_array( $matches ) && array_key_exists( 2, $matches ) && in_array( 'mapsmarker', $matches[2] ) )
{
echo 'shortcode is used';
}
}
add_action( 'wp', 'lmm_detect_shortcode' );
Problem is, that the maps can also be embedded in widgets (by shortcode) or template file directly by using the function do_shortcode()
(http://www.mapsmarker.com/docs/how-to-add-maps-to-your-site-using-template-tags/) and the code above
does not check, if this is true - resulting in the map not being displayed.
As a workaround I could add an option in the plugin settings if the js/css-files should only be added when the
shortcode is added to a post or page and add the description, to disable this setting if a map is added
to widgets via shortcode or to template files via do_shortcode().
As this is not a quite usable solution (which would result in some support requests in the long run), I am looking
for a solution, where I can turn this feature on by default and don´t have to add an option to the settings, because
the code also checks if a shortcode is added in widgets or via do_shortcode() in one of the template files, like this:
....
if( ( is_array( $matches ) && array_key_exists( 2, $matches ) && in_array( 'mapsmarker', $matches[2] ) ) || ( CHECK IF SHORTCODE USED IN WIDGETS == TRUE ) || ( CHECK IF SHORTCODE USED IN TEMPLATE FILES == TRUE ) )
{
echo 'shortcode is used';
}
.....
My first approach to this problem was to check global variables and see if somehow I could filter out this added code, e.g. by
$wp_filter (array) - a multi-dimensional array of all functions that have been added to filters/hooks.
Unfortunately I didnt find a solution yet. Any help is appreciated!
Denzel Chia answers:
Hi,
There is no need to check for shortcode in content, sidebar, or do_shortcode in template, in order to output javascript and css file link, once only in footer.
In WordPress 3.3, wp_enqueue_script and wp_enqueue_style works in mid page. So it works in shortcode function. And wp_enqueue_script and wp_enqueue_style are smart enough to produce only one javascript or css file link, irregardless of how many times it is called within the web page.
So please carry out the following test.
1) Create two files namely test.js and test.css and save them in root folder of theme
2) Place the following codes in functions.php of theme.
function my_scripts_method(){
wp_register_style('test-css',
get_template_directory_uri() . '/test.css',
$deps='',
'1.0' );
wp_register_script('test-js',
get_template_directory_uri() . '/test.js',
$deps='',
'1.0' );
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
function test_enqueue_shortcode(){
wp_enqueue_style('test-css');
wp_enqueue_script('test-js');
return "testing enqueue";
}
add_shortcode('test_enqueue','test_enqueue_shortcode');
3) use the shortcode [test_enqueue] in many instances in content, or sidebar, or do_shortcode
4) view html source and you will see there is only one test.css and test.js loaded in footer.
Hope this answers your question!
Thanks!
Denzel
Robert Seyfriedsberger comments:
thanks - but duplicate js/css arent the problem as I am already using wp_enqueue(). I want to check post/page content AND widet
content AND template files if they include the shortcode from my plugin and only include js/css files from plugin if a shortcode was
found in one of the 3 locations
Denzel Chia comments:
Hi,
That's exactly what I meant.
If you do not use the shortcode in my example, in content, or sidebar or template, NO javascript or CSS from your theme (in my example) or plugin will be included (loaded) into footer of web page!
Javascript or CSS will only be "loaded" into your theme, if the shortcode is found in one of the 3 locations that you mentioned.
If you cannot understand my codes, please at least try out my steps, so that you can understand how it works.
Thanks!
Denzel
Denzel Chia comments:
Hi,
I will explain again.
Look at my codes carefully.
I register the javascript and css in wp_enqueue_scripts hook (not function)
In shortcode function, I use wp_enqueue_script and wp_enqueue_style to load them in footer of theme. They do not load the "old" way.
If you do not use the shortcode in content or sidebar or template, you do not execute the wp_enqueue_style and wp_enqueue_scripts at all, and nothing will be loaded in footer!
So, what's the need to check for shortcode being used? if user doesn't use it anywhere, no script gets loaded.
Thanks!
Denzel
Robert Seyfriedsberger comments:
oh - than I didnt understand your code when I first read it - thanks for the hint! I will try if this solution works for my plugin
Robert Seyfriedsberger comments:
Hi,
I just checked your code - in general it seems to work, the only problem is, that I can enqueue the js+css-files in <head>, causing the maps not to show up.
I tried to include the parameter for footer=false, but it didnt work.
Any hint is appreciated!
add_action('wp_enqueue_scripts', array(&$this, 'lmm_frontend_register_scripts'),3);
....
function lmm_frontend_register_scripts() {
wp_register_script( 'leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.js', $deps='', NULL, FALSE ); (--> last false for not attaching to footer)
...
shortcode-function:
...
wp_enqueue_script( 'leafletmapsmarker' );
--> js always gets embedded in footer :-(
John Cotton answers:
How about doing it the other way around?
This assumes that your css and js can go in the footer....
Always queue both files and then have some code that runs early on the the_content filter which - if it doesn't string match the shortcode - it dequeues the files.
Robert Seyfriedsberger comments:
that doesnt solve the problem. the_content doesnt check if the shortcode got added in a widget or in a template file via do_shortcode()
John Cotton comments:
Fair enough, then you need to use have a global flag that is set in the actual shortcode itself (so it only gets set if the shortcode is run).
Have the_content filter run very late and then dequeue if the flag if not set.
John Cotton comments:
I've just checked and the wp_print_footer_scripts function runs at a priority of 20 in wp_footer, so you could also run a high priority test in that rather than the_content as a way of guaranteeing to be after all content is done.