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 trying to add a div to a widget's content in my dynamic sidebar.

Here is the register code;

register_sidebar(array(
        'name' => "Sidebar1",
        'id' => 'home-sidebar-1',
        'before_widget' => '<div class="sidebar-box">',
        'after_widget' => '</div>',
        'before_title' => '<div class="title">',
        'after_title' => '</div>',
    ));

But this code causes like this;

<div class="sidebar-box">
    <div class="title">{WIDGET TITLE}</div>
     {WIDGET CONTENT}
</div>

Here is what I am trying to do;

<div class="sidebar-box">
    <div class="title">{WIDGET TITLE}</div>
    <div class="content">
           {WIDGET CONTENT}
    </div> 
</div>

How it can be done?

share|improve this question

4 Answers 4

up vote 6 down vote accepted

In addition to Toscho's answer here's what you need for a robust solution:

// if no title then add widget content wrapper to before widget
add_filter( 'dynamic_sidebar_params', 'check_sidebar_params' );
function check_sidebar_params( $params ) {
    global $wp_registered_widgets;

    $settings_getter = $wp_registered_widgets[ $params[0]['widget_id'] ]['callback'][0];
    $settings = $settings_getter->get_settings();
    $settings = $settings[ $params[1]['number'] ];

    if ( $params[0][ 'after_widget' ] == '</div></div>' && isset( $settings[ 'title' ] ) && empty( $settings[ 'title' ] ) )
        $params[0][ 'before_widget' ] .= '<div class="content">';

    return $params;
}

From Toscho's answer:

register_sidebar(array(
    'name' => "Sidebar1",
    'id' => 'home-sidebar-1',
    'before_widget' => '<div class="sidebar-box">',
    'after_widget' => '</div></div>',
    'before_title' => '<div class="title">',
    'after_title' => '</div><div class="content">',
));

What this does is:

  • checks the settings for the registered sidebar for widgets ending in 2 closing <div>s
  • checks if there's no title
  • if not, it modifies the before_widget output to show the opening widget content div

You could use this approach to change the sidebar arguments in other ways to based on the widget instance's settings.

share|improve this answer
    
I have a problem with that: some widgets (like WP default ones, for example) set a default title if you leave that blank. So your function adds the div because there isn't a title in the params at that point, but the widget adds it afterwards and the code is messed up. Do you know how to check for the title from "within" the widget? Thanks –  Cmorales Jan 25 '13 at 1:36
    
Not without adding a widget by widget check or some horrendously complex code to render the widget silently then parse it for a title... Will have a think –  sanchothefat Jan 25 '13 at 17:07
    
Maybe hooking to this codex.wordpress.org/Function_Reference/the_widget would help? They use it (for other reason) in this article wp.smashingmagazine.com/2012/12/11/… –  Cmorales Jan 29 '13 at 0:53
1  
the_widget() isn't used in the dynamic_sidebar() function, it's a means of calling any widget with options you specify in place. It's another place to filter though so my solution doesn't cover that eventuality. Cheers –  sanchothefat Jan 29 '13 at 17:14

I liked the idea of both @tosco and @sanchothefat answers - however I have struggled with that combination because whilst empty( $settings[ 'title' ] might indeed return true the widget itself might output a default title if none is set. This title is then wrapped in the before_title and after_title markup and again the page breaks. That's the case with some of the default widgets anyway.

Easier to just stick to standard widget registration parameters;

register_sidebar(array(
    'id' => 'sidebar1',
    'name' => __( 'Sidebar 1', 'bonestheme' ),
    'description' => __( 'The first (primary) sidebar.', 'bonestheme' ),
    'before_widget' => '<div class="block">',
    'after_widget' => '</div>',
    'before_title' => '<div class="block-title">',
    'after_title' => '</div>',
));

and then add a filter action as per Marventus' answer here;

http://wordpress.org/support/topic/add-html-wrapper-around-widget-content

function widget_content_wrap($content) {
    $content = '<div class="block-content">'.$content.'</div>';
    return $content;
}
add_filter('widget_text', 'widget_content_wrap');
share|improve this answer

Add the second div to the title parameter:

register_sidebar(array(
        'name' => "Sidebar1",
        'id' => 'home-sidebar-1',
        'before_widget' => '<div class="sidebar-box">',
        'after_widget' => '</div></div>',
        'before_title' => '<div class="title">',
        'after_title' => '</div><div class="content">',
    ));
share|improve this answer
    
That fails if there's no widget title - it can be done though –  sanchothefat Dec 3 '12 at 10:15
    
Yes it fails when there is no title.. –  MBraiN Dec 3 '12 at 12:06
    
I've added an answer with some code to fix the titles problem. Should probably be merged with Toscho's really but he has epic rep already :) –  sanchothefat Dec 3 '12 at 12:56

After looking at the previous answers, I think I fixed the problem Cmorales identified with sanchothefat's answer. Define your widget as follows:

register_sidebar( array(
    'name' => 'Sidebar',
    'id' => 'sidebar',
    'before_widget' => '<div class="panel panel-default %2$s" id="%1$s">',
    'after_widget' => '</div>',
    'before_title' => '',
    'after_title' => ''
) );

It's important that the before_title and after_title defaults are removed. After some trial and error I noted that the first filter that showed a default title was widget_title. Then use the widget_title filter like so:

function widget_title( $title ) {
    if ( $title )
        $title = '<div class="panel-heading"><h3 class="panel-title">' . $title . '</h3></div>';
    $title .= '<div class="panel-body">';
    return $title;
}

Basically, <div class="panel-heading"><h3 class="panel-title"> is my before_title and </h3></div> is my after_title. Finally, use dynamic_sidebar_params to prepend a closing div for our content wrap:

function dynamic_sidebar_params( $params ) {
    $params[0]['after_widget'] = '</div>' . $params[0]['after_widget'];
    return $params;
}

It isn't pretty, but it works.

share|improve this answer

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.