WordPress. Виджет «Дерево категорий»
Давайте создадим плагин, который будет добавлять еще один виджет «Дерево категорий» к тем, что доступны изначально, сразу после установки WordPress. Виджет категорий блога уже имеется в поставке, но наше дерево категорий будет изначально свернуто, т.е. будут показаны только категории верхнего уровня, а все потомки скрыты.
При клике по категории, у которой есть дочерние категории — будут показаны дочерние. Если у категории нет потомков — тогда будет просто переход на страницу категории. Практической ценности этот плагин не имеет, сделан исключительно с целью изучения WordPress.
Простой вариант
Итак, создаем директорию category-tree-widget
, а внутри нее — три файла: category-tree-widget.php
, category-tree-widget.js
и Category_Tree_Widget.php
.
<?php /* Plugin Name: Виджет «Дерево категорий» Plugin URI: https://tokmakov.msk.ru Description: Добавляет виджет категорий блога в виде дерева Version: 1.0 Author: Евгений Токмаков Author URI: https://tokmakov.msk.ru */ require 'Category_Tree_Widget.php'; /* * Регистрируем виджет «Дерево категорий» */ add_action( 'widgets_init', function () { register_widget('Category_Tree_Widget'); } ); /* * Подключаем js-файл, который будет изначально скрывать все дочерние * категории и показывать их по клику на родительской категории */ add_action( 'wp_enqueue_scripts', function () { wp_enqueue_script( 'category-tree-widget', // будет зарегистрирован под этим именем plugin_dir_url(__FILE__) . 'category-tree-widget.js', [ // должен быть подключен после jquery 'jquery', ], null, // версии нет, поэтому null true // подключаем перед закрывающим тегом body ); } );
<?php /** * Класс виджета, который позволяет вывести категории * блога в виде дерева */ class Category_Tree_Widget extends WP_Widget { /** * Cоздание виджета */ function __construct() { parent::__construct( 'category_tree_widget', 'Дерево категорий блога', // заголовок виджета ['description' => 'Иерархия категорий, дочерние категории можно свернуть или развернуть'] // описание ); } /** * Метод выводит каегории блога в общедоступной части сайта */ public function widget($args, $instance) { // к заголовку применяем фильтр $title = apply_filters('widget_title', $instance['title']); echo $args['before_widget']; // выводим заголовок виджета if ( ! empty($title)) { echo $args['before_title'] . $title . $args['after_title']; } // выводим дерево категорий echo '<ul id="category-tree-widget">', "\n"; wp_list_categories( apply_filters( 'widget_categories_args', ['title_li' => ''], $instance ) ); echo '</ul>', "\n"; echo $args['after_widget']; } /* * Форма настроек виджета в панели управления */ public function form($instance) { $title = ''; if (isset($instance['title'])) { $title = $instance['title']; } // заголовок виджета $id = $this->get_field_id('title'); $name = $this->get_field_name('title'); $value = esc_attr($title); ?> <p> <label for="<?= $id; ?>">Заголовок</label> <input type="text" class="widefat" id="<?= $id; ?>" name="<?= $name; ?>" value="<?= $value; ?>" /> </p> <?php } /* * Сохранение настроек виджета в панели управления */ public function update($new_instance, $old_instance) { $instance = array(); $instance['title'] = ! empty($new_instance['title']) ? strip_tags($new_instance['title']) : ''; return $instance; } }
jQuery(document).ready(function ($) { $('#category-tree-widget ul').hide(); $('#category-tree-widget li a').on('click', function (event) { /* * Если у этого элемента дерева есть дочерние узлы и они в данный момент * свернуты, то по ссылке переходить не надо, а надо их просто показать. */ var closed = $(this).next().is('ul') && !$(this).next().is(':visible') if (closed) { event.preventDefault(); $(this).next().slideDown('normal'); } }); });
После установки и активации плагина, виджет станет доступным в числе прочих и его можно будет разместить в сайдбаре. Этот виджет сформирует примерно такой html-код:
<ul id="category-tree-widget"> <li class="cat-item cat-item-123"><a href="...">Первая категория</a></li> <li class="cat-item cat-item-197 current-cat-parent current-cat-ancestor"><a href="...">Вторая категория</a> <ul class="children"> <li class="cat-item cat-item-206 current-cat"><a href="...">Дочерняя категория</a></li> </ul> </li> <li class="cat-item cat-item-196"><a href="...">Третья категория</a> <ul class="children"> <li class="cat-item cat-item-204"><a href="...">Дочерняя категория</a> <ul class="children"> <li class="cat-item cat-item-205"><a href="...">Дочерняя дочерней</a></li> </ul> </li> </ul> </li> <li class="cat-item cat-item-198"><a href="...">Четвертая категория</a></li> </ul>
Сложный вариант
У простого варианта есть существенный недостаток — ссылка служит и для перехода на страницу категории и для показа дочерних категорий. Поэтому добавим слева от ссылок иконки, при клике по которым будут показываться или скрываться дочерние категории.
<?php /* Plugin Name: Виджет «Дерево категорий» Plugin URI: https://tokmakov.msk.ru Description: Добавляет виджет категорий блога в виде дерева Version: 1.0 Author: Евгений Токмаков Author URI: https://tokmakov.msk.ru */ require 'Category_Tree_Widget.php'; /* * Регистрируем виджет «Дерево категорий» */ add_action( 'widgets_init', function () { register_widget('Category_Tree_Widget'); } ); /* * Подключаем css и js файлы виджета «Дерево категорий» */ add_action( 'wp_enqueue_scripts', function () { /* * Подключаем css-файл */ wp_enqueue_style( 'category-tree-widget', // будет зарегистрирован под этим именем plugin_dir_url(__FILE__) . 'category-tree-widget.css', [ // должен быть подключен после bootstrap 'current-theme-bootstrap', ] ); /* * Подключаем js-файл */ wp_enqueue_script( 'category-tree-widget', // будет зарегистрирован под этим именем plugin_dir_url(__FILE__) . 'category-tree-widget.js', [ // должен быть подключен после jquery 'jquery', ], null, // версии нет, поэтому null true // подключаем перед закрывающим тегом body ); } );
<?php /** * Класс виджета, который позволяет вывести категории * блога в виде дерева */ class Category_Tree_Widget extends WP_Widget { /** * Cоздание виджета */ function __construct() { parent::__construct( 'category_tree_widget', 'Дерево категорий блога', // заголовок виджета ['description' => 'Иерархия категорий, дочерние категории можно свернуть или развернуть'] // описание ); } /** * Метод выводит категории блога в общедоступной части сайта */ public function widget($args, $instance) { // к заголовку применяем фильтр $title = apply_filters('widget_title', $instance['title']); echo $args['before_widget']; // выводим заголовок виджета if ( ! empty($title)) { echo $args['before_title'] . $title . $args['after_title']; } // выводим дерево категорий $this->tree(0); echo $args['after_widget']; } /* * Форма настроек виджета в панели управления */ public function form($instance) { $title = ''; if (isset($instance['title'])) { $title = $instance['title']; } // заголовок виджета $id = $this->get_field_id('title'); $name = $this->get_field_name('title'); $value = esc_attr($title); ?> <p> <label for="<?= $id; ?>">Заголовок</label> <input type="text" class="widefat" id="<?= $id; ?>" name="<?= $name; ?>" value="<?= $value; ?>" /> </p> <?php } /* * Сохранение настроек виджета в панели управления */ public function update($new_instance, $old_instance) { $instance = array(); $instance['title'] = ! empty($new_instance['title']) ? strip_tags($new_instance['title']) : ''; return $instance; } /* * Выводит список категорий блога в виде вложенного списка */ private function tree($parent) { $categories = get_categories([ 'hide_empty' => true, 'parent' => $parent ]); if (!empty($categories)) { $icons = [ 'plus' => '<b class="glyphicon glyphicon-plus" aria-hidden="true"></b>', 'right' => '<i class="glyphicon glyphicon-triangle-right" aria-hidden="true"></i>', ]; ?> <ul<?= $parent ? '' : ' id="category-tree-widget"'; ?>> <?php foreach ($categories as $category): ?> <?php $icon = $icons['right']; if ($this->hasChildren($category->term_id)) { $icon = $icons['plus']; } $link = get_category_link($category->term_id); ?> <li><?= $icon; ?> <a href="<?= $link; ?>"><?= $category->name; ?></a> <?php $this->tree($category->term_id); ?> </li> <?php endforeach; ?> </ul> <?php } } /* * Возвращает true, если у категории блога есть дочерние категории */ private function hasChildren($id) { $categories = get_categories([ 'hide_empty' => true, 'parent' => $id ]); return !empty($categories); } }
jQuery(document).ready(function ($) { $('#category-tree-widget ul').hide(); $('#category-tree-widget li b').on('click', function () { var $icon = $(this); var closed = $icon.siblings('ul') && !$icon.siblings('ul') .is(':visible'); if (closed) { $icon.siblings('ul').slideDown('normal', function () { $icon.removeClass('glyphicon-plus').addClass('glyphicon-minus'); }); } else { $icon.siblings('ul').slideUp('normal', function () { $icon.removeClass('glyphicon-minus').addClass('glyphicon-plus'); }); } }); });
#category-tree-widget {
list-style: none;
padding-left: 0;
}
#category-tree-widget ul {
list-style: none;
padding-left: 25px;
}
#category-tree-widget .glyphicon {
color: #777;
border: 1px solid #777;
padding: 1px;
border-radius: 2px;
font-size: 10px;
margin-right: 5px;
}
#category-tree-widget .glyphicon-plus,
#category-tree-widget .glyphicon-minus {
cursor: pointer;
color: #337ab7;
border: 1px solid #337ab7;
}
- WordPress. Произвольные типы записей
- WordPress. Пользовательские таксономии
- WordPress. Что такое сайдбар
- WordPress. Фильтр записей по произвольным полям. Часть 3 из 3
- WordPress. Фильтр записей по произвольным полям. Часть 2 из 3
- WordPress. Фильтр записей по произвольным полям. Часть 1 из 3
- WordPress. Добавляем мета-теги. Часть 3 из 3
Поиск: Web-разработка • WordPress • Виджет • Иерархия • Навигация • Плагин