1

I need to display images and other content in the sidebar depending on a page. Pages are added dynamically and information that need to appear in the sidebar is different for each page. So I can't predict what will go where. So the idea was is to have a page's content as usual (with all the neccessary shortcodes) and then at the end of page content have a shortcode with all the info that needs to appear in the sidebar for that page.


Original question: displaying shortcodes selectively (suppress in the main content and instead display in a sidebar)

I was wondering if it's possible to display shortcodes "selectively".

For example, a specific shortcode, let's call it [sc], is specified within a page content. Now, when displaying that page's content I would like to suppress that specific [sc] shortcode, but instead display it from the sidebar for that page. Content of a page will have other shortcodes. I only want to do selectively display the specific [sc] shortcode and process others as usual - i.e. other shortcodes will be processed within the page's content.

Is that possible to do? And how?

1
  • I rewrote your question using your new explanation. It's an interesting approach to solve this problem! There are other ways to do it (custom metadata), but this is probably the easiest to implement.
    – Jan Fabry
    Commented Apr 6, 2011 at 14:19

5 Answers 5

0

A shortcode handler doesn't have to return anything, it can just modify a global variable that you later read in your sidebar widget. If your sidebar is displayed after your post content (most likely if it's a right sidebar), you can do this without any problem. If your sidebar is displayed before the post content it is more complicated: you have to start output buffering when your widget is called, wait until the rest of the page is displayed, and then do something with the shortcode content and flush the output buffer.

A simple "proof of concept" that displays the shortcode content not in the post but in the footer:

$wpse13925_shortcode_content = array();

add_shortcode( '13925', 'wpse13925_shortcode' );
function wpse13925_shortcode( $shortcode_attr, $shortcode_content )
{
    $GLOBALS['wpse13925_shortcode_content'][] = $shortcode_content;
    return '';
}

add_action( 'wp_footer', 'wpse13925_footer' );
function wpse13925_footer()
{
    var_dump( $GLOBALS['wpse13925_shortcode_content'] );
}
1
  • Thanks a lot Jan, helped me a lot! I don't have widgets, but simple template files and right hand-side sidebar. So all worked well. Thanks a lot! :)
    – dashaluna
    Commented Apr 6, 2011 at 14:08
1

I have based my solution on Jan Fabry's answer. I don't have widgets, but simple template files.

So, what I did is the following:

  1. Specified all the info that needs to appear in the sidebar within a page's content itself wrapped in [sidebar_content] shortcode.

  2. Specified the following function in the functions.php. This expands all the content of [sidebar_content], but doesn't display anything, but instead saves it in the global variable.

    global $sidebar_content;
    add_shortcode("sidebar_content", "my_sidebar_content");
    function my_sidebar_content($atts, $content = null){
        global $sidebar_content;
        if( !empty($content) ){
            $sidebar_content = do_shortcode($content);
        }
        return "";
    }
    
  3. In the sidebar.php. I have the following code:

    global $sidebar_content;
    if( isset($sidebar_content) && !empty($sidebar_content) ){
      echo $sidebar_content;
    }
    
1
  • I fixed your code formatting: you need four extra spaces because you are in a list. So the first four spaces are to add an extra line to the same list item, and the next four to start your code block. Trial and error can be a good teacher :-)
    – Jan Fabry
    Commented Apr 6, 2011 at 14:14
0

You can use conditional tags and do_shortcode. http://codex.wordpress.org/Function_Reference/do_shortcode
http://codex.wordpress.org/Conditional_Tags

A simple example for a single page with an ID of 12.

if is_single(12){
do_shortcode('[shortcode]');
}

If instead you wrote this shortcode yourself, you can create a function to give it a display parameter, like [shortcode('page=5, 6, 7', 'category', 'exclude=posts', 'whatever')]

2
  • Sorry I still not sure how I can do what I need. I want to display a specific [sc] shortcode within the sidebar (sidebar template) and suppress it when outputing the page's content where it's specified. Hope that makes sense.
    – dashaluna
    Commented Apr 4, 2011 at 20:54
  • Unless you give specific code in your question, you're not going to get a specific answer back.
    – Wyck
    Commented Apr 4, 2011 at 22:56
0

You could do it based on a custom field, for example create a custom field named sc_no_show and give it the value of true. then in your shortcode function do something like this:

function what_ever(){
    global $post;
    $no_show = get_post_meta($post->ID,'sc_no_show',true);
    if ($no_show)
        return '';
    //add your normal shortcode stuff here
}

Now on every page or post you have a custom fields named sc_no_show with the value of true it wont show/

0

You could use a few well placed actions to look ahead for your shortcode, if it's found set a flag and run additional actions to first strip the content of that shortcode, then a secondary one to execute that shortcode in the sidebar. Alongside all that create a simple action of your own inside the sidebar file and hook onto that when you need to print out the shortcode.

Not following? Don't blame you, i'm not always good at explaining ideas, so here's an example in code form..

First, inside your sidebar where you want the shortcode content appear, add something like..

<?php do_action( 'special_shortcode_content' ); ?>

We now have an action we can hook onto when a flag gets set.

Next we need to scan the posts, before the loop occurs, check for the existance of a particular shortcode, i'll use [sc] as per your example and we can do that by hooking onto the_posts. Rather than using a global, i prefer to just wrap the code into a class, and define a class variable inside the class to act as the flag.

class Page_Shortcode_to_Sidebar {
    private $has_shortcode = false;
    public function __construct() {
        if( is_admin() )
            return;

        add_action( 'the_posts', array( $this, 'check_for_shortcode' ) );
        add_filter( 'the_content', array( $this, 'remove_shortcode' ), 1 ); 
    }
    public function check_for_shortcode( $posts ) {
        if( empty( $posts ) )
            return $posts;

        if( !is_page() )
            return $posts;

        foreach( $posts as $post ) {
            if( !stripos( $post->post_content, '[sc]' ) )
                continue;
            $this->has_shortcode = true;
        }
        return $posts;
    }
    public function remove_shortcode( $content ) {

        if( !$this->has_shortcode )
            return $content;

        $content = str_replace( '[sc]', '', $content );
        add_action( 'special_shortcode_content', array( $this, 'do_shortcode' ) );

        return $content;
    }
    public function do_shortcode() {
        ?>
        <li><?php do_shortcode('[sc]'); ?></li>
        <?php
    }
}

$Page_Shortcode_to_Sidebar = new Page_Shortcode_to_Sidebar;

So basically what happens is this..

  1. The callback on the_posts checks each post for the shortcode, if found sets the flag.
  2. The callback on the_content executes later, and checks if the flag is set.
  3. If the flag is set, the shortcode is remove from the content and adds an action onto our custom sidebar action.
  4. It returns the content, minus the specific shortcode.
  5. The sidebar action occurs, and the shortcode content is produced.

If you're referring to your own shortcode that you created, and it's use in this way..

[sc]something[/sc]

..then you'll need something smarter to strip the shortcode contents from the post content.

If it's not used like that, then what i've provided above should do the job just fine.

Hope that helps.. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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