Пользовательский Nav Walker: структура HTML для подменю
У меня настроен Custom Nav Walker, и он правильно работает с основными пунктами меню, отображая их так, как я хочу.
Однако тот же HTML применяется к элементам sub-menu
, что не соответствует моим требованиям.
Я хочу, чтобы sub-menu
имел следующую структуру:
<ul>
<li>
<h2 class="dropdown-text">Блог 1</h2>
</li>
<li>
<h2 class="dropdown-text">Блог 2</h2>
</li>
<li>
<h2 class="dropdown-text">Блог 3</h2>
</li>
<li>
<h2 class="dropdown-text">Блог 4</h2>
</li>
</ul>
Вот HTML структура для полной навигации:
<div class="postit-surround">
<a href="#">
<div class="postit">
<div class="pin">
<img src="<?php echo get_template_directory_uri(); ?>/assets/drawing-pin.png" alt="Кнопка" title="Кнопка">
</div>
<div class="postit-title">
<h1 class="nav-title-text">Продукты</h1>
</div>
<div class="corner-peel">
<img src="<?php echo get_template_directory_uri(); ?>/assets/corner-flick-cyan.png" alt="Уголок" title="Уголок">
</div>
</div>
</a>
<div class="navigation-dropdown">
<ul>
<li>
<h2 class="dropdown-text">Продукт 1</h2>
</li>
<li>
<h2 class="dropdown-text">Продукт 2</h2>
</li>
<li>
<h2 class="dropdown-text">Продукт 3</h2>
</li>
<li>
<h2 class="dropdown-text">Продукт 4</h2>
</li>
<li>
<h2 class="dropdown-text">Продукт 5</h2>
</li>
</ul>
</div>
</div>
Вот вызов wp_nav_menu:
<div class="navigation-container">
<?php
$walker = new my_nav_walker;
wp_nav_menu( array( 'theme_location' => 'header-menu', 'menu' => 'ul', 'menu_class' => 'navigation', 'menu_id' => '', 'walker' => $walker ) );
?>
</div>
Вот структура моего Custom Walker HTML: (ПРИМЕЧАНИЕ: Я новичок в этом, так что код может быть неоптимальным...)
class my_nav_walker extends Walker {
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$direct = get_template_directory_uri();
$item_output = $args->before;
$item_output .= '<div class="postit-surround">';
$item_output .= '<a'. $attributes .'>';
/** Этот фильтр описан в wp-includes/post-template.php */
$item_output .= '<div class="postit">
<div class="pin">';
$item_output .= '<img src="' . $direct . '/assets/drawing-pin.png" alt="Кнопка" title="Кнопка">
</div>
<div class="postit-title">
<h1 class="nav-title-text">';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '</h1>
</div>
<div class="corner-peel">
<img src="' . $direct . '/assets/corner-flick-green.png" alt="Уголок" title="Уголок">
</div>
</div>';
$item_output .= '</a>';
$item_output .= '</div>';
$item_output .= $args->after;
}
} // Walker_Nav_Menu
Вот CSS, если нужно: Ссылка на PasteBin
Я не уверен, правильно ли я создаю структуру для получения отдельного стиля, который мне нужен.
Что вы посоветуете?
Есть ли альтернативы?
Конструктивная критика кода? (Не будьте слишком строги! :P)
РЕДАКТИРОВАНИЕ -----:
Я провел дополнительные исследования, чтобы понять PHP код, и теперь понимаю, где начинается определение начала и конца подменю (с помощью start_lvl и end_lvl), но все еще не понимаю, как разделить код для родительских элементов навигации и их соответствующих подменю.
Вот чего я хочу добиться в отображении навигации: http://jsfiddle.net/TPD5L/
Решение: Скопируйте и вставьте приведенный ниже код в вашу функцию. Затем в шаблоне используйте
my_nav_menu($menu_location);
// Поместите это в ваши функции
class MY_Menu_Walker_Ext extends Walker {
var $tree_type = array('post_type', 'taxonomy', 'custom');
var $db_fields = array('parent' => 'menu_item_parent', 'id' => 'db_id');
function start_el(&$output, $object, $depth = 0, $args = array(), $current_object_id = 0) {
$output .="<li><h2 class='dropdown-text'>{$object->title}</h2>";
}
function end_el(&$output, $object, $depth = 0, $args = array()) {
$output.='</li>';
}
}
class my_custom_menu {
public $menu;
public $menuItems;
public $parents;
public $walker;
public function __construct($menu_location) {
$this->setMenu($menu_location);
$this->getMenuItems();
$this->getParents();
$this->walker = new MY_Menu_Walker_Ext();
}
public function drawMenu() {
}
public function setMenu($menu_location) {
$this->menu = $this->getMenuByLocation($menu_location);
}
protected function getMenuByLocation($menu_location) {
$locations = get_nav_menu_locations();
$menu = null;
if ($locations && isset($locations[$menu_location])) {
$menu = wp_get_nav_menu_object($locations[$menu_location]);
}
return $menu;
}
public function get() {
}
public function getMenuItems() {
if ($this->menuItems)
return $this->menuItems;
$this->menuItems = wp_get_nav_menu_items($this->menu);
return $this->menuItems;
}
public function getParents() {
if ($this->parents)
return $this->parents;
$parents = array();
foreach ($this->menuItems as $item) {
if ($item->menu_item_parent == 0) {
array_push($parents, $item);
}
}
$this->parents = $parents;
return $this->parents;
}
public function getChild($parent_id) {
$childs = array();
foreach ($this->menuItems as $item) {
if ($parent_id == $item->menu_item_parent) {
$item->menu_item_parent = 0;
array_push($childs, $item);
foreach ($this->menuItems as $item1) {
if ($item->ID == $item1->menu_item_parent) {
array_push($childs, $item1);
}
}
}
}
return $childs;
}
public function draw() {
echo "<div class='postit-surround'>";
foreach ($this->parents as $item) {
$this->displayParentHTML($item->title);
$this->drawChildren($this->getChild($item->ID));
}
echo "</div>";
}
public function displayParentHTML($title) {
?>
<a href="#">
<div class="postit">
<div class="pin">
<img src="<?php echo get_template_directory_uri(); ?>/assets/drawing-pin.png" alt="Кнопка" title="Кнопка меню">
</div>
<div class="postit-title">
<h1 class="nav-title-text"><?php echo $title ?></h1>
</div>
<div class="corner-peel">
<img src="<?php echo get_template_directory_uri(); ?>/assets/corner-flick-cyan.png" alt="Загнутый уголок" title="Элемент дизайна">
</div>
</div>
</a>
<?php
}
public function drawChildren($children) {
$defaults = array('menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'depth' => 0, 'walker' => '', 'theme_location' => '');
$args = array(
'theme_location' => 'header-menu',
'container' => 'div',
'container_class' => 'navigation-dropdown',
'items_wrap' => '<ul >%3$s</ul>',
'depth' => 0,
);
$args = wp_parse_args($args, $defaults);
echo "<div class='navigation-dropdown'><ul>";
echo $this->walker->walk($children, 2, $args);
echo "</ul></div>";
}
}
function my_nav_menu($name = null) {
$myMenu = new my_custom_menu($name);
$myMenu->draw();
}

Спасибо, это работает само по себе, но мне сложно понять, как интегрировать это с моим Walker верхнего уровня, чтобы получить общую структуру, указанную в вопросе?

Замените ваш класс my_nav_walker на этот. И в шаблоне, где вы хотите отобразить навигационное меню, скопируйте и вставьте код из второго раздела. Примечание: вывод будет включать также контейнер div

Я не уверен, что вы правильно поняли, что я имею в виду по поводу навигации (я был очень неясен в своем вопросе, извините за это). Посмотрите этот пример: http://jsfiddle.net/TPD5L/

Хорошо, HTML-код для части 'postit' должен быть включен в шаблон. <div для postit><код postit></> Здесь вызываем меню навигации </div>

Вы НЕ должны пытаться получить весь HTML из wp_nav_menu. Используйте wp_nav_menu только для части 'меню'. Остальное должно быть включено в код шаблона, понимаете?

Так вместо использования wp_nav_menu для получения элементов меню верхнего уровня, просто используйте его для получения дочерних элементов?

давайте продолжим обсуждение в чате
