Многоуровневое выпадающее меню категорий

27 февр. 2011 г., 06:19:16
Просмотры: 15.1K
Голосов: 3

Я использую 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>
0
Все ответы на вопрос 2
7
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(); ?>
23 апр. 2011 г. 21:42:18
Комментарии

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

Cristian Cristian
24 апр. 2011 г. 19:32:10

@Wild Phoenix да, ты прав. Я исправил это в своем посте.

Ján Bočínec Ján Bočínec
24 апр. 2011 г. 19:36:06

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

Zach Shallbetter Zach Shallbetter
25 апр. 2011 г. 21:54:04

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

Ján Bočínec Ján Bočínec
26 апр. 2011 г. 01:08:59

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

Zach Shallbetter Zach Shallbetter
26 апр. 2011 г. 01:13:36

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

Ján Bočínec Ján Bočínec
26 апр. 2011 г. 02:01:03

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

Zach Shallbetter Zach Shallbetter
26 апр. 2011 г. 02:22:10
Показать остальные 2 комментариев
22
<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>

Может потребоваться доработка, но должно работать.

27 февр. 2011 г. 23:56:39
Комментарии

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 18:43:56

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

wyrfel wyrfel
28 февр. 2011 г. 19:23:08

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 20:15:29

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

wyrfel wyrfel
28 февр. 2011 г. 20:18:41

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 20:33:46

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

wyrfel wyrfel
28 февр. 2011 г. 20:35:55

@Zach Shallbetter: Проблема с JS должна быть теперь тоже решена.

wyrfel wyrfel
28 февр. 2011 г. 20:54:54

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 21:16:52

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 21:20:32

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 21:27:09

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

wyrfel wyrfel
28 февр. 2011 г. 21:30:04

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 21:39:38

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

wyrfel wyrfel
28 февр. 2011 г. 22:10:18

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 23:32:09

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

Zach Shallbetter Zach Shallbetter
28 февр. 2011 г. 23:41:46

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

wyrfel wyrfel
1 мар. 2011 г. 00:17:49

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

wyrfel wyrfel
1 мар. 2011 г. 00:20:10

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

wyrfel wyrfel
1 мар. 2011 г. 00:22:04

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

Zach Shallbetter Zach Shallbetter
1 мар. 2011 г. 18:13:12

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

wyrfel wyrfel
1 мар. 2011 г. 21:05:35

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

wyrfel wyrfel
1 мар. 2011 г. 21:07:00

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

Zach Shallbetter Zach Shallbetter
3 мар. 2011 г. 00:03:03
Показать остальные 17 комментариев