Обновлено: 27 марта 2017, 15:57
 Marabar

Реализация меню-"аккордеона" в MODX revolution

Раскрывающееся меню в MODX revolution — «Аккордеон» мы реализуем с помощью движка jQuery и сниппета wayfinder. Если у вас ещё не установлен движок jQuery, то перейдите по ссылке и скачайте последнюю версию у разработчика. На сегодняшний день — jQuery 1.8.3. Поместите скачанный файл в /assets/js/jquery/. В чанке со служебной информацией, обычно это чанк [[$head]], между тегами <> пропишем путь до файла:
<script type="text/javascript" src="assets/js/jquery/jquery-1.8.3.js"></script>
Ваш файл может иметь другую версию, если зто так — меняем на свою. И ещё, если вы используете вложенные урлы, вам скорее всего нужен будет слэш перед <>. Подготовка закончена, переходим к созданию меню-аккордеона.

В том месте, где у вас будет меню помещаем конструкцию не кэшируемого вызова сниппета wayfinder:
[[wayfinder? &startId=`0` &excludeDocs=`1` &level=`2`]]
Разберём параметры:
  • &startId=`0` — Отправная точка, в данном случае корень сайта,
  • &excludeDocs=`1` — ID документа, который исключаем из меню. У меня главная страница.
  • &level=`2` — Глубина для построения меню, т.е. будут отображаться ресурсы 1 и 2 вложенности.

Пример данного вызова можно посмотреть здесь.

Как видно из примера, я вывел в меню основные разделы, блога и их подкатегории. У этих подкатегорий могут быть свои подкатегории — 3 вложенность, которые остались скрыты.
Теперь, чтобы наш аккордеон оживился, нам нужно прописать классы в вызове wayfindera и убрать ненужные, которые подставляет сниппет, поработать со стилями CSS. И самое главное скрипт управления меню — accordion-menu.js.
jQuery.fn.initMenu = function() {
    return this.each(function(){
        var theMenu = $(this).get(0);
        $('.acitem', this).hide();
        $('li.expand > .acitem', this).show();
        $('li.expand > .acitem', this).prev().addClass('active');
        $('li a', this).click(
            function(e) {
                e.stopImmediatePropagation();
                var theElement = $(this).next();
                var parent = this.parentNode.parentNode;
                if($(parent).hasClass('noaccordion')) {
                    if(theElement[0] === undefined) {
                        window.location.href = this.href;
                    }
                    $(theElement).slideToggle('normal', function() {
                        if ($(this).is(':visible')) {
                            $(this).prev().addClass('active');
                        }
                        else {
                            $(this).prev().removeClass('active');
                        }
                    });
                    return false;
                }
                else {
                    if(theElement.hasClass('acitem') && theElement.is(':visible')) {
                        if($(parent).hasClass('collapsible')) {
                            $('.acitem:visible', parent).first().slideUp('normal',
                            function() {
                                $(this).prev().removeClass('active');
                            }
                        );
                        return false;
                    }
                    return false;
                }
                if(theElement.hasClass('acitem') && !theElement.is(':visible')) {
                    $('.acitem:visible', parent).first().slideUp('normal', function() { 
                        $(this).prev().removeClass('active');   
                    });
                    theElement.slideDown('normal', function() {
                        $(this).prev().addClass('active');
                    });
                    return false;
                }
            }
        }
    );
});
};
$(document).ready(function() {$('.menu').initMenu();});
Скопируйте этот скрипт accordion-menu.js и поместите его в /assets/js/jquery/, сохранять лучше через какой нибудь текстовый редактор. Иначе могут прописаться лишние теги. В чанке [[$head]] указываем путь до файла:
<script type="text/javascript" src="assets/js/jquery/accordion-menu.js"></script>
Если разобрать скрипт, то мы увидим что используются четыре основных класса (в нашем случае, на самом деле их больше) — menu, collapsibleacitem и active, другие классы расcматривать не будем. Этих классов и будем придерживаться, такие классы как: first, last и active, которые нам любезно подставляет wayfinder мы уберём. Здесь они не нужны. Класс active будет подставлять скрипт. Ниже предоставлен исходный код меню при нынешнем вызове сниппета. Все пункты беру со своего сайта, все ссылки будут активны.
<ul>                          <!-- Меню - внешний шаблон -->
    <li class="first">                                <!-- Элемент списка -->
        <a title="Статьи" href="stati/">Статьи</a>
            <ul>                                      <!-- Субменю - внутренний шаблон -->
                <li class="first">
                    <a title="Сниппеты MODx evolution" href="snippetyi_modx_evolution/">Сниппеты MODx evolution</a>
                </li>
            </ul>
    </li>
    <li class="active"><a title="Блог" href="blog/">Блог</a>
        <ul>                                          <!-- Ещё один Субменю -->
            <li class="first">
                <a title="MODx evolution" href="modx_evolution/">MODx-evo</a>
            </li>
            <li class="active">
                <a title="MODX revolution" href="modx_revolution/">MODX revo</a>
            </li>
            <li>
                <a title="Локальный сервер" href="lokalnyij_server/">Локальный сервер</a>
            </li>
            <li class="last">
                <a title="TV в MODX" href="tv_v_modx/">TV в MODX</a>
            </li>
        </ul>
    </li>
        <li class="last">
            <a title="Портфолио" href="portfolio/">Портфолио</a>
        </li>
</ul>
Как видите, class=«first» — присваивается первому элементу списка, а wayfinder в своём вызове использует список, class=«last» — последнему элементу списка, class=«active» — активному элементу списка. Чтобы исключить эти классы давайте дополним наш вызов:
[[Wayfinder?
    &startId=`0`
    &excludeDocs=`1`
    &level=`2`
    &firstClass=`0`
    &lastClass=`0`
    &hereClass=`0`
]]
Думаю что всё понятно, разбирать не будем. Далее.

Наш скрипт подставляет в основной блок (назовём его внешний шаблон) <
    > два classa — menu и collapsible. В активный блок субменю (внутренний шаблон) — class=«acitem». Активным считается тогда, когда внутренний шаблон раскрыт и доступны элементы списка. Добавим их в наш вызов:
[[Wayfinder?
    &startId=`0`
    &excludeDocs=`1`
    &level=`2`
    &firstClass=`0`
    &lastClass=`0`
    &hereClass=`0`
    &outerClass=`menu collapsible`
    &innerClass=`acitem`
]]
Разберём добавленные параметры:
  • &outerClass=`menu collapsible` — Присвоили классы внешнему шаблону, это class=«menu» — отвечает за общий стиль и открытие дочерних ресурсов, и class=«collapsible» — отвечает за закрытие дочерних ресурсов.
  • &innerClass=`acitem` — Присвоили класс внутреннему шаблону — субменю, class=«acitem» — отвечает за стиль активного субменю.
Ну что же, вот мы и оживили наше меню.

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

Придаём стиль нашему меню-аккордеону.


Сразу предупреждаю, я буду придерживаться своего сайта. Под свой сайт, свой стиль каждый подберёт сам.
ul.menu, ul.menu ul {
    width:300px;                              /*ширина меню */
    list-style-type:none;                     /* убираем маркеры */
    margin: 0;                                /* внешний отступ */
    padding: 0;                               /* внутренний отступ */
}
ul.menu a {
    display: block;                           /* блочный элемент */
    text-decoration: none;                    /* убираем подчёркивание */
    text-align: left;                         /* расположение текст слева */
    font-size:14px;                           /* размер шрифта */
}
    ul.menu li {
    margin-top: 1px;                          /* отступ от верхнего края */
}
ul.menu li a, ul.menu ul.menu li a {
    padding: 0.5em;
    border-radius: 5px;                       /* закругляем углы в IE до 9 версии не поддерживается */
    -moz-border-radius: 5px;                  /* Firefox-су привет) */
    -webkit-border-radius: 5px;               /* хром, сафари */
    color: #d7d7d7;                           /* цвет шрифта */
    border: solid 1px #333;                   /* стили рамки */
    background: #333;                         /* цвет фона */
/* Используем градиент, поддерживается всеми современными браузерами, IE - только от 9+ */
    background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#000));
    background: -moz-linear-gradient(top, #666, #000);
    background-image: -o-linear-gradient(top,rgb(102,102,102),rgb(0,0,0)); /* Опера */
}
 /* градиент при наведении */
ul.menu li a:hover, ul.menu ul.menu li a:hover {
    background: #000;
    background: -webkit-gradient(linear, left top, left bottom, from(#444), to(#000));
    background: -moz-linear-gradient(top, #444, #000);
    background-image: -o-linear-gradient(top,rgb(68,68,68),rgb(0,0,0));
    }
  /* стили субменю */
ul.menu li ul li a, ul.menu ul.menu li ul li a {
    background: #ccc;
    color: #000;
    padding-left: 20px;
}
 /* стили субменю при наведении */
ul.menu li ul li a:hover, ul.menu ul.menu li ul li a:hover {
    background: #aaa;
    padding-left: 15px;                       /* отступ слева */
}
ul.menu ul.menu li a:hover {
    border-left: 0;
    padding-left: 0.5em;
} 
 /* градиент активных пунктов меню */
ul.menu a.active, ul.menu ul.menu li a.active, ul.menu a.active:hover, ul.menu ul.menu li a.active:hover {
    text-decoration: none;
    color:#000;                                  
    border: solid 1px #000;
    background: #B8F2F5;
    background: -webkit-gradient(linear, left top, left bottom, from(#B8F2F5), to(#46afb5));
    background: -moz-linear-gradient(top, #B8F2F5, #46afb5);
    background-image: -o-linear-gradient(top, #B8F2F5, #46afb5);
}
Вообщем градиент будет отображаться во всех современных браузерах кроме IE-8 и более старых версиях. Посмотреть результат можно здесь. О чём ещё хотелось сказать, в стилях мы применили class=«menu». Значение довольно таки распространённое. Если оно у вас уже занято, то в файле accordion-menu.js, в самой нижней строчке 
$(document).ready(function() {$('.menu').initMenu();});
меняем параметр $(.menu) на своё, только не забываем и в сниппете изменить. На этом всё.

зы. Самое главное забыл). Поздравляю всех с наступившим Новым годом! Всего самого наилучшего, радости веселья и всякого такого)) С Новым Годом!

UPD: Чтобы избавиться от эффекта «хлопанья» при загрузке страницы, необходимо для субменю добавить стиль display: none;, например:
ul.menu .acitem {
    display: none;
}
   Marabar Инструкции 0    2 0
Marabar 21 сентября 2018, 00:32
Login в MODX revolution 25
Marabar 17 мая 2018, 12:22
Выводим облако тегов в MODX revo 17
medortex 14 июля 2017, 16:26
Меню Аккордеон в MODX revo 54
Madao 16 мая 2017, 18:28
msMiniCartDynamic 3
Семён 05 мая 2017, 23:30
Создание ресурсов из фронтенда 41
Филитович Владимир 26 февраля 2017, 22:25
Apache 2.2.22, установка и настройка 41
valery 30 ноября 2016, 15:51
phpMyAdmin 3.5.1, установка и настройка 3