Добавление div для обертки содержимого виджета после заголовка виджета

3 дек. 2012 г., 11:57:10
Просмотры: 21.7K
Голосов: 10

Я пытаюсь добавить div для содержимого виджета в моем динамическом сайдбаре.

Вот код регистрации:

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>',
    ));

Но этот код создает такую структуру:

<div class="sidebar-box">
    <div class="title">{ЗАГОЛОВОК ВИДЖЕТА}</div>
     {СОДЕРЖИМОЕ ВИДЖЕТА}
</div>

Вот что я пытаюсь получить:

<div class="sidebar-box">
    <div class="title">{ЗАГОЛОВОК ВИДЖЕТА}</div>
    <div class="content">
           {СОДЕРЖИМОЕ ВИДЖЕТА}
    </div> 
</div>

Как это можно сделать?

0
Все ответы на вопрос 7
4
19

В дополнение к ответу Toscho вот что вам нужно для надежного решения:

// если нет заголовка, добавляем обертку содержимого виджета перед виджетом
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;
}

Из ответа Toscho:

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">',
));

Что делает этот код:

  • проверяет настройки зарегистрированной боковой панели для виджетов, заканчивающихся на 2 закрывающих тега <div>
  • проверяет, есть ли заголовок
  • если нет, он изменяет вывод before_widget, чтобы показать открывающий div содержимого виджета

Вы можете использовать этот подход для изменения аргументов боковой панели другими способами на основе настроек экземпляра виджета.

3 дек. 2012 г. 14:54:49
Комментарии

У меня проблема: некоторые виджеты (например, стандартные виджеты WP) устанавливают заголовок по умолчанию, если оставить это поле пустым. Так что ваша функция добавляет div, потому что в этот момент в параметрах нет заголовка, но виджет добавляет его позже, и код получается испорченным. Вы знаете, как проверить наличие заголовка "изнутри" виджета? Спасибо

Cmorales Cmorales
25 янв. 2013 г. 03:36:34

Нет, без добавления проверки для каждого виджета в отдельности или какого-то ужасно сложного кода, который бы рендерил виджет в тихом режиме, а затем анализировал его на наличие заголовка... Подумаю над этим

sanchothefat sanchothefat
25 янв. 2013 г. 19:07:57

Может быть, использование этого хука http://codex.wordpress.org/Function_Reference/the_widget поможет? Его используют (по другой причине) в этой статье http://wp.smashingmagazine.com/2012/12/11/inserting-widgets-with-shortcodes/

Cmorales Cmorales
29 янв. 2013 г. 02:53:32

the_widget() не используется в функции dynamic_sidebar(), это способ вызова любого виджета с указанными вами параметрами. Это еще одно место для фильтрации, поэтому мое решение не охватывает этот случай. Удачи

sanchothefat sanchothefat
29 янв. 2013 г. 19:14:37
1

Мне понравилась идея обоих ответов @tosco и @sanchothefat - однако у меня возникли трудности с их комбинацией, потому что хотя empty( $settings[ 'title' ] действительно может вернуть true, сам виджет может выводить заголовок по умолчанию, если он не задан. Этот заголовок затем оборачивается в разметку before_title и after_title, и снова страница ломается. По крайней мере, так происходит с некоторыми стандартными виджетами.

Проще просто придерживаться стандартных параметров регистрации виджетов:

register_sidebar(array(
    'id' => 'sidebar1',
    'name' => __( 'Боковая панель 1', 'bonestheme' ),
    'description' => __( 'Первая (основная) боковая панель.', 'bonestheme' ),
    'before_widget' => '<div class="block">',
    'after_widget' => '</div>',
    'before_title' => '<div class="block-title">',
    'after_title' => '</div>',
));

а затем добавить фильтр, как предложил Marventus в своем ответе здесь:

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');
25 сент. 2013 г. 17:37:58
Комментарии

и это работает только для "Текстовых виджетов"

Prashant Pugalia Prashant Pugalia
15 дек. 2014 г. 16:23:18
3

Добавьте второй div к параметру title:

register_sidebar(array(
        'name' => "Sidebar1",
        'id' => 'home-sidebar-1',
        'before_widget' => '<div class="sidebar-box">',
        'after_widget' => '</div></div>', // Закрываем оба div-элемента
        'before_title' => '<div class="title">', // Открывающий div для заголовка
        'after_title' => '</div><div class="content">', // Закрываем title и открываем content
    ));
3 дек. 2012 г. 11:59:38
Комментарии

Это не сработает, если у виджета нет заголовка - хотя это можно исправить

sanchothefat sanchothefat
3 дек. 2012 г. 12:15:11

Да, это не работает, когда нет заголовка..

MBraiN MBraiN
3 дек. 2012 г. 14:06:38

Я добавил ответ с кодом для исправления проблемы с заголовками. Возможно, его стоит объединить с ответом Toscho, но у него и так эпическая репутация :)

sanchothefat sanchothefat
3 дек. 2012 г. 14:56:47
1

Вот что нужно сделать для достижения этого:

register_sidebar(array(
        'name' => "Боковая панель 1",
        'id' => 'home-sidebar-1',
        'before_widget' => '<div class="sidebar-box"><div class="content">',
        'after_widget' => '</div></div>',
        'before_title' => '</div><div class="title">',
        'after_title' => '</div><div class="content">',
    ))

Когда заголовок отсутствует, вы получите:

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

Когда есть заголовок, вы получите:

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

Чтобы убедиться, что первый пустой div с классом content не отображается в последнем случае, добавьте это в ваш CSS:

.sidebar-box .content:empty {display:none !important;}
14 нояб. 2015 г. 18:17:36
Комментарии

Очень умный способ, и он работает.

Mohammed Mohammed
21 янв. 2021 г. 20:38:43
1

Рассмотрев предыдущие ответы, я думаю, что исправил проблему, которую Cmorales обнаружил в ответе sanchothefat. Определите свой виджет следующим образом:

register_sidebar( array(
    'name' => 'Боковая панель',
    'id' => 'sidebar',
    'before_widget' => '<div class="panel panel-default %2$s" id="%1$s">',
    'after_widget' => '</div>',
    'before_title' => '',
    'after_title' => ''
) );

Важно, чтобы значения по умолчанию для before_title и after_title были удалены. После некоторых проб и ошибок я заметил, что первый фильтр, который показывал заголовок по умолчанию, был widget_title. Затем используйте фильтр widget_title следующим образом:

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;
}

По сути, <div class="panel-heading"><h3 class="panel-title"> — это мой before_title, а </h3></div> — мой after_title. Наконец, используйте dynamic_sidebar_params, чтобы добавить закрывающий div для нашей обёртки контента:

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

Это не самое элегантное решение, но оно работает.

3 апр. 2014 г. 21:52:22
Комментарии

Изначально был очень воодушевлён этим подходом, но столкнулся с проблемой в виджетах, использующих esc_html($title) (например, BuddyPress). В таком случае добавленный HTML отображается экранированным и не рендерится на фронтенде.

Ryan Ryan
25 авг. 2014 г. 05:53:35
0

Я немного изменил код, чтобы не нужно было трогать register_sidebar. Регистрируем сайдбар обычным способом:

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>',
));

А ниже представлен модифицированный код из решения Sanchothefat:

/**
 * Если заголовок не указан, добавляем обертку widget-content в before_widget
 * Если заголовок указан, добавляем обертку контента в before_widget
*/
add_filter('dynamic_sidebar_params', 'check_widget_template');
function check_widget_template($params){
    global $wp_registered_widgets;

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

    if (isset($params[0]['id']) && $params[0]['id'] == 'home-sidebar-1') {
        if (!isset($the_settings['title']) && empty($the_settings['title'])) {
            $params[0]['before_widget'] .= '<div class="widget-inner">';
            $params[0]['after_widget']  .= '</div>';
        } else {
            $params[0]['after_widget']  .= '</div>';
            $params[0]['after_title']   .= '<div class="widget-inner">';
        }
    }

    return $params;
}
23 мар. 2019 г. 01:15:39
0

Как упоминалось в комментариях, некоторые основные виджеты добавляют собственный заголовок, который затем дважды оборачивается в div с контентом. Чтобы удалить их, можно просто вернуть пустую строку. Единственный недостаток — необходимо вручную вводить все заголовки.

function remove_default_widget_title( $title, $instance = [], $id = '' ) {
    // Проверяем, установлен ли заголовок и является ли он пустой строкой
    if ( isset($instance['title']) && trim($instance['title']) == '' ) {
        return '';
    }
    return $title;
};
// Добавляем фильтр для изменения заголовка виджета
add_filter( 'widget_title', 'remove_default_widget_title', 10, 3 );

Поправьте меня, если я что-то упустил, но мне кажется, это довольно надежное решение.

14 февр. 2020 г. 17:18:03