Многоуровневое выпадающее меню категорий
Я использую WordPress в качестве CMS и хотел бы иметь возможность выбора категорий из нескольких выпадающих списков, т.е. <option>
.
Пример использования: первый выпадающий список будет содержать родительские категории. После выбора родительской категории появится второй выпадающий список с дочерними категориями. На Wordpress.org есть несколько плагинов, но все они либо не работают, либо устарели. Буду благодарен за любую помощь.
Не работающий плагин http://wordpress.org/extend/plugins/ajax-category-dropdown/
Код, который я использую с wordpress.org:
<form action="<?php bloginfo('url'); ?>/" method="get">
<?php
$select = wp_dropdown_categories('orderby=name&echo=0&depth=0&hierarchical=1&exclude=5,4');
$select = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $select);
echo $select;
?>
<noscript><input type="submit" value="Просмотр" /></noscript>
</form>
function parent_child_cat_select() { ?>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(document).ready(function() {
jQuery('#parent_cat').change(function(){
var parentCat=jQuery('#parent_cat').val();
// вызов ajax
jQuery.ajax({
url:"/wp-admin/admin-ajax.php",
type:'POST',
data:'action=category_select_action&parent_cat_ID=' + parentCat,
success:function(results)
{
jQuery("#sub_cat_div").html(results);
}
});
});
});
/* ]]> */
</script>
<form action="<?php bloginfo('url'); ?>/" method="get">
<div id="parent_cat_div"><?php wp_dropdown_categories("show_option_none=Выберите родительскую категорию&orderby=name&depth=1&hierarchical=1&id=parent_cat"); ?></div>
<div id="sub_cat_div"><select name="sub_cat_disabled" id="sub_cat_disabled" disabled="disabled"><option>Сначала выберите родительскую категорию!</option></select></div>
<div id="submit_div"><input type="submit" value="Просмотреть" /></div>
</form>
<?php }
function implement_ajax() {
$parent_cat_ID = $_POST['parent_cat_ID'];
if ( isset($parent_cat_ID) )
{
$has_children = get_categories("parent=$parent_cat_ID");
if ( $has_children ) {
wp_dropdown_categories("orderby=name&parent=$parent_cat_ID");
} else {
?><select name="sub_cat_disabled" id="sub_cat_disabled" disabled="disabled"><option>Нет дочерних категорий!</option></select><?php
}
die();
} // end if
}
add_action('wp_ajax_category_select_action', 'implement_ajax');
add_action('wp_ajax_nopriv_category_select_action', 'implement_ajax');//для пользователей, не вошедших в систему
//это необязательно, только если вы еще не используете jQuery
function load_jquery() {
wp_enqueue_script('jquery');
}
add_action('init', 'load_jquery');
Для отображения выпадающих меню используйте функцию parent_child_cat_select()
.
<?php parent_child_cat_select(); ?>

add_action('wp_ajax_category_select_action', 'implement_ajax');//для пользователей, не вошедших в систему. Должно быть add_action( 'wp_ajax_nopriv_category_select_action', 'implement_ajax' );

Спасибо! Однако я получаю сообщение, что нет дочерних категорий, хотя их несколько.

@Zach, у вас есть записи, назначенные этим дочерним категориям? Также учтите, что эта настройка будет отображать только строго связанные подкатегории.

@JohnnyPea Да, в каждой есть несколько пользовательских записей. Меня устраивает, что отображаются только строго связанные категории. Например, у категории Camera будут показаны все категории, к которым я отнес продукты. Я обновил запись, добавив скриншот раздела с моими категориями. Еще раз спасибо за помощь.

@Zach Вы используете плагин кеширования? Проверяли ли вы это в другом браузере? (попробуйте очистить кеш) Вы скопировали мой код как есть? (попробуйте скопировать код снова) У вас нет плагинов или функций темы, которые могут взаимодействовать с категориями или как-то их фильтровать? Можно попробовать деактивировать все плагины, переключиться на стандартную тему и проверить работу... У меня это работает без активных плагинов на стандартной теме TwentyTen.

<form action="<?php echo remove_query_arg(array('mycat_go', 'cat')); ?>" method="get">
<?php
// получаем выбранную категорию и выполняем начальные настройки
if (isset($_REQUEST['cat'])) $_REQUEST['mycat_go'] = $_REQUEST['cat'];
$selected = $_REQUEST['mycat_go'];
$selects = array();
$last = 0;
$top = false;
$i = 0;
// в основном, мы проходим от выбранной категории вверх через родителей
// пока не останется родительских категорий
while (!$top) {
// подготавливаем запрос для генерации поля со всеми дочерними категориями
// выбранной категории
$args = array(
'name' => 'mycat_'.$i,
'orderby' => 'name',
'echo' => 0,
'hierarchical' => 1,
'exclude' => '4,5',
'child_of' => $selected,
'depth' => 1,
'show_option_none' => '--выбрать--',
'hide_if_empty' => true,
);
if(!empty($last)) $args['selected'] = $last;
// подготавливаем следующую итерацию цикла или останавливаемся, если показываем дочерние элементы 0
if (!empty($selected)) {
$last = $selected;
$category = get_category($selected);
$selected = $category->parent;
} else {
$top = true;
}
// генерируем вывод и сохраняем в обратном порядке, так как мы идем снизу вверх
$select = wp_dropdown_categories($args);
$select = preg_replace("#<option([^>]*)>#", "<option$1 onclick=\"this.parentNode.name = 'mycat_go';return this.form.submit()\">", $select);
array_unshift($selects, $select);
$i++;
}
// выводим на экран
foreach ($selects as $select) {
echo $select;
}
?>
</form>
<form action="<?php remove_query_arg(array('mycat_go', 'cat')); ?>" method="get">
<input type="hidden" name="cat" value="<?php echo $_REQUEST['mycat_go']; ?>" />
<input type="submit" value="Перейти" />
</form>
Может потребоваться доработка, но должно работать.

лол, это было впечатляюще и полностью логично! Однако есть ошибка в строке 15 if(!empty($last) $args['selected'] = $last;
Не уверен, что её вызывает.

@Zach Shallbetter: Упс, это опечатка...пропущена закрывающая скобка. Исправил.

Я добавил это на страницу, и она вернула бесчисленное множество select-боксов. Также была огромная загрузка. Я подумал, что это может быть у меня, поэтому удалил несколько категорий и очистил весь остальной код из шаблона. Проблема не решилась.

@Zach Shallbetter: Похоже, условие цикла не срабатывает, и он продолжает выполняться бесконечно. Хорошо... я внес еще одно изменение, которое должно предотвратить бесконечный цикл, когда первоначальный выбор не сделан.

Кажется, отображается только один выпадающий список с дочерними значениями. Также при выборе элемента не выполняется никакое действие.

@Zach Shallbetter: Извините, мое первоначальное условие цикла было из другого подхода, и я не подумал об этом должным образом. Я снова внес изменения и добавил комментарии, надеюсь, теперь это работает лучше.

Приношу извинения за то, что заставил вас побегать. Результат, который я получаю, такой же, как был изначально, когда я использовал код из codex. Я добавляю информацию в категорию, и категория появляется в выпадающем списке. Я выбираю её, и она переносит меня на страницу. Я думаю, проблема может быть в том, что выпадающий список не показывает пустые категории.

Также неважно, есть ли у дочерней категории родитель - в выпадающем списке будет отображаться только дочерняя.

Я добавил 'hide_empty' => 0
в массив, и это позволило мне видеть все категории, включая пустые. Однако при выборе родительской категории не появляется второй селект — происходит переход сразу на страницу этой категории.

@Zach Shallbetter: Да, я об этом не подумал, конечно же так и будет, поскольку парсится параметр URL 'cat'. Я внес еще одно изменение, которое (надеюсь) должно это исправить... извини, что заставил тебя побегать. ;-)

Жаль, что здесь нельзя публиковать изображения, лол. Теперь при выборе элемента отображаются абсолютно все записи. Также не появляется второй селект, когда я добавляю 'hide_empty' => 0
, чтобы видеть родительские категории и выбрать одну из них. Второй селект я так и не увидел. Проблема с использованием 'hide_empty' => 0
в том, что отображаются все категории, а не только родительские (если это имеет смысл).

@Zach Shallbetter: Лол...ок, для разнообразия я наконец протестировал это локально, создал несколько категорий и так далее. Теперь... оно работает, вроде как. Есть несколько проблем. Не знаю, насколько хорошо оно работает с hide_empty
, но основы работают.

Всё ещё нет вторичного выбора. Может быть, что-то на моей стороне вызывает это?

Да, когда я выбираю категорию в списке, он переносит меня на полный список записей, относящихся к ней.

@Zach Shallbetter: Аргх, сегодня явно не мой день... что-то пошло не так при вставке кода обратно. Убедитесь, что это 2! отдельных формы (последняя часть отсутствовала).

Также учтите, что это скорее быстрый набросок для вдохновения. Это стоит сделать лучше, например, перезагружать только часть формы через AJAX вместо перезагрузки всей страницы, и когда есть только одна запись, она должна автоматически выбираться и т.д.

Если вы замените весь ваш фрагмент кода на весь фрагмент кода выше, он больше не должен перенаправлять на страницу категорий.

Боже, я просто не понимаю, что я делаю не так. Я создал совершенно базовую страницу. Добавляю точную копию кода выше. Когда я выбираю "models" из выпадающего списка (там 4 подкатегории), он сразу переходит на /?mycat_go=112 без показа второго выбора. Ещё раз спасибо за всю твою помощь, wyrfel.

Возможно, тут недопонимание... так и задумано, что страница перезагружается с этим параметром. Так это работает. Это не AJAX и не JS. Просто перезагружается страница с переданной выбранной категорией как параметром, а затем перерисовывается при загрузке страницы.

Ааа, кажется, я понял... должно быть, дело в параметре action
в формах... см. правку.
