Фикс Bootstrap 3 Navigation dropdown submenu и реализация в Zend Framework 2 и Smarty

В новом (относительно) 3 отсутствует возможность по умолчанию для выпадающего меню в навигациии задавать уровень вложенности более чем 2. Т.е. невозможно построить навигацию с бесконечным выпадающим меню используя возможности Bootstrap 3 по умолчанию. Для добавления такой нужной возможности существует следующее решение.

На stackoverflow предложено отличное рабочее решение. Оно будет браться за основу, почти без изменений. Это добавление некоторого css и js кода, который расширяет или переопределяет стандартное поведение навигации bootstrap.

Я обычно добавляю этот код в файлы bootstrap-fix.css и bootstrap-fix.js и подключаю сразу после бутстраповских файлов.
Вот необходимый код, который надо добавить в css.

А вот код для js файла.

Верстка для данного фикса предполагается следующая.

Как должно быть понятно из кода – на каждый дополнительный уровень вложенности создается тег <li> с классом
-submenu. Для автоматической генерации такой верстки из какого-то набора (массива) ссылок меню придется воспользоваться рекурсией. Т.к. на каждой итерации при построении верстки надо будет проверть – есть ли у текущего родительского элемента дети? От этого зависит будет ли открыт новый тег для подменю.

Далее я приведу пример реализации на основе 2 хелпера (). И второй пример будет с использованием шаблонизатора и его встроенной возможности создавать ф-ии.

Пример реализации на Zend Framework 2

В Zend обычно существует базовый шаблон layout. В нем для рендеринга навигации вызывается хелпер navigation() c указанием partial шаблона меню. Кстати через navigation() можно построить breadcrumbs() – хлебные крошки (код шаблона стандартный из мануала).

Предварительно подключены css и js файлы в head. Сам же bootstrap-fix.js подключен в шаблоне меню.

Пример верстки layout.phtml.

Как можно понять из кода – контроллеры при выполнении заполняют переменную content, а нас интересует сейчас файл top_menu.phtml.
Вот его содержимое:

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

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

Пример реализации на Smarty

Для того, чтобы сделать такое же меню используя Smarty надо воспользоваться встроенной возможностью создания функций прямо внутри шаблона. Выглядит это несколько проще, по сравнению с Zend. Код файла bootstrap.tpl:

Тут отличие в том, что структура передается как чистый массив, где элементы тоже массивы, а не объекты. Так же видно, что путь в js файлу в переменной. Этот шаблон может быть просто отрендерен средствами Smarty и выведен в нужном месте.
Я использую этот шаблон в моем модуле для seyfer/kohana-dynamic-structure