Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm running a function on pages where the shortcode [make-me-a-map] is used. It enqueues javascript to the page and makes a map. That part works fine (woot!) but I'm having trouble with adding the stylesheets to only those pages in a similar fashion.

functions.php (Current)

add_shortcode("make-me-a-map", "create_new_map");
add_action("wp_head", "style_my_new_map");

function create_new_map () {
    global $new_map_called_for;
    $map_called_for = true;

    wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
    wp_enqueue_script('make-a-new-map');
    }

function style_my_new_map() {
    global $new_map_called_for;
    if ($new_map_called_for == true) {
        $tDir = get_template_directory_uri();

        // Echo stylesheets because wp_register_style & wp_enqueue_style don't work atm
        // And add_action('wp_enqueue_script', 'style_my_new_maps') with those functions would add style to all pages
        // Not just the ones with [make-me-a-map] shortcode
        echo "<link rel='stylesheet' href='", $tDir, "/css/new-map.css' />", PHP_EOL;

        // Echo Javascript straight to page (couldn't do it with wp_enqueue_script) to let js code know the template directory
        echo '<script type="text/javascript">var templateDir = "', get_template_directory_uri(), '";</script>', PHP_EOL;
        $map_called_for = false;
    }
}

This doesn't seem to be working unfortunately. The styles are being added to all pages.

I didn't use wp_register_style & wp_enqueue_style because this bug is still adding <Link /> tags to the footer from those functions.

I could have used add_action("wp_enqueue_scripts", "style_my_new_map") instead of add_action('wp-head', "style_my_new_map") but as far as I can see and have checked, there's no difference? Still adds the stylesheets to all pages.

So my question is actually in two parts: :)

  1. Why is the current functions.php not working and adding styles to all pages? I'm not sure if it's the global call or the if statement...
  2. What's the best way for me to add the stylesheets to the header of only the pages that the above shortcode is used on, assuming I will not know the page ids, etc?

Thanks in advance! P

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

2 questions so 2 answers :)

Why is the current functions.php not working and adding styles to all pages? I'm not sure if it's the global call or the if statement...

It doesn't work because of the order in which these functions are called. Your shortcode callback is called during rendering post content (most probably the_content function call).

Both wp_enqueue_scripts and wp_head are called much earlier: wp_head somewhere in your themes header.php file and wp_enqueue_scripts during wp_head call.

What's the best way for me to add the stylesheets to the header of only the pages that the above shortcode is used on, assuming I will not know the page ids, etc?

I don't think there is such "best" way. It's not a good idea at all. Browsers cache CSS files. So if you have the same CSS on all pages, browser will get it only once. If there are many CSS files for different pages, browser will have to get all of them. So I wouldn't do it at all, and include these CSS styles in global css file.

Although if you have to include it only on pages that use this shortcode, then (2 solutions, the choice which is better is yours; I think 2nd one is nicer)...

  1. You can add these styles as inline styles. Just be careful to not include them many times. So output them with your shortcode and assure they will be printed only once.
  2. Since posts are already selected, when wp_head/wp_enqueue_scripts is called, you can add some function to this hook, loop through selected posts, check if they're containing your shortcode and enqueue your CSS if it's needed. (Of course it won't be very efficient).
share|improve this answer
1  
Yeah, #2 might be less efficient but definitely nicer than inline =) Got it working now, cheers! –  Padraic Aug 3 '13 at 8:46
add comment

Loading Scripts and Styles Dynamically Using Shortcode

Advantages

  • Does not search through all the posts every time the shortcode is called.
  • Able to add styles as well as scripts dynamically only when shortcode is on the page.
  • Does not use regexes since they tend to be slower than strstr() or strpos(). You could switch to regex if you need to accept args.
  • Reduces file calls

Explanation of Code

  1. Finds the shortcodes on page using the save_post hook only when the post is not a revision and matches the specified post_type.

  2. Saves the found post ids as an array using add_option() with autoload set to yes unless the entry is already present. Then it will use update_option().

  3. Uses hook wp_enqueue_scripts to call our add_scripts_and_styles() function.

  4. That function then calls get_option() to retrieve our array of page ids. If the current $page_id is in the $option_id_array then it adds the scripts and styles.

Please note: I converted the code from OOP Namespaced classes so I may have missed something. Let me know in the comments if I did.

Code Example: Finding Shortcode Occurences

function find_shortcode_occurences($shortcode, $post_type = 'page')
{
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );
    $query_result = new \WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

function save_option_shortcode_post_id_array( $post_id ) {
    if ( wp_is_post_revision( $post_id ) OR 'page' != get_post_type( $post_id )) {
        return;
    }
    $option_name = 'yourprefix-yourshortcode';
    $id_array = find_shortcode_occurences($option_name);
    if (false == add_option($option_name, $id_array, '', 'yes')) update_option($option_name, $id_array);
}

add_action('save_post', 'save_option_shortcode_id_array' );

Code Example: Shortcode Dynamically Include Scripts and Styles

function yourshortcode_add_scripts_and_styles() {
    $page_id = get_the_ID();
    $option_id_array = get_option('yourprefix-yourshortcode');
    if (in_array($page_id, $option_id_array)) {
        wp_enqueue_script( $handle, $src, $deps, $ver, $footer = true );
        wp_enqueue_style( $handle, $src , $deps);
    }
}

add_action('wp_enqueue_scripts', 'yourshortcode_add_scripts_and_styles');
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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