Estou tentando criar um mega menu walker. Infelizmente, os caminhantes escapam completamente do meu conhecimento de codificação. Eu realmente poderia usar alguma ajuda para fazê-lo funcionar. Aqui estão os recursos que eu preciso:
- Enrole o segundo nível
<ul>
em<section>
. [COMPLETO] - Quando um usuário define a classe "break" em um
<li>
no segundo nível<ul>
, faça com que ele<li>
comece um novo<ul>
. Se for o primeiro<li>
da lista, não faça nada para impedir a formação de listas não ordenadas vazias. [COMPLETO] - Quando um usuário define a classe "widget" em um
<li>
no primeiro nível que possui um sub<ul>
, anexe um widget ao final dele<ul>
. [COMPLETO] - Adicione classe
mega-menu-columns-#
aos<li>
elementos de primeiro nível que contêm caixas suspensas com várias colunas e / ou um widget. O # representa o número de<ul>
elementos, +1 para o widget, se existir. [COMPLETO]
Eu tenho um pouco de código para fazer parte disso, mas não tudo. Existem seções recortadas abaixo:
Envolva o segundo nível <ul>
em <section>
:
function start_lvl(&$output, $depth = 0, $args = array()) {
if ($depth == 0) {
$output .= "<section>";
}
$output .= "<ul class=\"sub-menu\">";
}
function end_lvl(&$output, $depth = 0, $args = array()) {
$output .= "</ul>";
if ($depth == 0) {
$output .= "</section>\n";
}
}
Gere o HTML do widget:
ob_start();
dynamic_sidebar("Navigation Callout");
$widget = ob_get_contents();
ob_end_clean();
O HTML de saída seria:
<ul>
<li id="menu-item-1" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1 mega-menu-columns-2">
<a href="http://www.example.com/about/">
About Us
</a>
<section>
<ul class="sub-menu">
<li id="menu-item-2" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2">
<a href="http://www.example.com/about/company-profile/">
Company Profile
</a>
</li>
<li id="menu-item-3" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-3">
<a href="http://www.example.com/about/leadership-team/">
Leadership Team
</a>
</li>
<li id="menu-item-4" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4">
<a href="http://www.example.com/about/professional-affiliations/">
Professional Affiliations
</a>
</li>
</ul>
<ul class="sub-menu">
<li id="menu-item-5" class="break menu-item menu-item-type-post_type menu-item-object-page menu-item-5">
<a href="http://www.example.com/about/clients/">
Clients
</a>
</li>
<li id="menu-item-6" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-6">
<a href="http://www.example.com/about/partnerships/">
Partnerships
</a>
</li>
</ul>
</section>
</li>
<li id="menu-item-7" class="widget menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-7 mega-menu-columns-3">
<a href="http://www.example.com/services/">
Services
</a>
<section>
<ul class="sub-menu">
<li id="menu-item-8" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-8">
<a href="http://www.example.com/services/civil-engineering/">
Civil Engineering
</a>
</li>
<li id="menu-item-9" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-9">
<a href="http://www.example.com/services/land-planning/">
Land Planning
</a>
</li>
<li id="menu-item-10" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10">
<a href="http://www.example.com/services/surveying/">
Surveying
</a>
</li>
</ul>
<ul class="sub-menu">
<li id="menu-item-11" class="break menu-item menu-item-type-post_type menu-item-object-page menu-item-11">
<a href="http://www.example.com/services/information-technology/">
Information Technology
</a>
</li>
<li id="menu-item-12" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-12">
<a href="http://www.example.com/services/subsurface-utility-engineering/">
Subsurface Utility Engineering
</a>
</li>
</ul>
<aside>
<h6>Widget Title</h6>
<p>Maecenas quis semper arcu. Quisque consequat risus nisi. Sed venenatis urna porta eros malesuada euismod. Nulla sollicitudin fringilla posuere. Nulla et tellus eu nisi sodales convallis non vel tellus.</p>
</aside>
</section>
</li>
<li id="menu-item-13" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-15">
<a href="http://www.example.com/contact/">
Contact Us
</a>
</li>
</ul>
ATUALIZAÇÃO: Meus contadores estão me dando dor. Eles estão contando apenas após a geração do submenu, o que não me ajuda. Veja esta captura de tela para entender o que quero dizer:
Os números principais estão sendo apresentados start_el
. Os números inferiores estão sendo apresentados end_el
. Como você pode ver, os números principais não estão contando os meus .breaks
como deveriam. Eles contam a classe de widget porque esses estão sendo contados $depth = 0
. Alguém por favor me salve dessa horribilidade!
// mega menu walker
/*
ONE REMAINING BUG:
- Need to add class to LI containing mega-menu-columns-#
*/
class megaMenuWalker extends Walker_Nav_Menu {
private $column_limit = 3; /* needs to be set for each site */
private $show_widget = false;
private $column_count = 0;
static $li_count = 0;
function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
$classes = empty($item->classes) ? array() : (array) $item->classes;
$item_id = $item->ID;
if ($depth == 0) self::$li_count = 0;
if ($depth == 0 && in_array("widget", $classes)) {
$this->show_widget = true;
$this->column_count++;
}
if ($depth == 1 && self::$li_count == 1) {
$this->column_count++;
}
if ($depth == 1 && in_array("break", $classes) && self::$li_count != 1 && $this->column_count < $this->column_limit) {
$output .= "</ul><ul class=\"sub-menu\">";
$this->column_count++;
}
if ($depth == 0 && $this->column_count > 0) {
$mega_menu_class = " mega-menu-columns-" . $this->column_count;
}
$class_names = join(" ", apply_filters("nav_menu_css_class", array_filter($classes), $item));
$class_names = " class=\"" . esc_attr($class_names . $mega_menu_class) . "\"";
$output .= sprintf(
"<li id=\"menu-item-%s\"%s><a href=\"%s\">%s</a>",
$item_id,
$class_names,
$item->url,
$item->title
);
self::$li_count++;
}
function start_lvl(&$output, $depth = 0, $args = array()) {
if ($depth == 0) {
$output .= "<section>";
}
$output .= "<ul class=\"sub-menu\">";
}
function end_lvl(&$output, $depth = 0, $args = array()) {
$output .= "</ul>";
if ($depth == 0) {
if ($this->show_widget) {
ob_start();
dynamic_sidebar("Navigation Callout");
$widget = ob_get_contents();
ob_end_clean();
$output .= $widget;
$this->show_widget = false;
}
$output .= "</section>";
}
}
function end_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
if ($depth == 0 && $this->column_count > 0) {
/* needs to be added to opening level 0 li */
$column_count_class = " mega-menu-columns-" . $this->column_count;
$output .= $column_count_class;
/* end */
$this->column_count = 0;
}
$output .= "</li>";
}
}
ATUALIZAÇÃO 2: Aqui está um exemplo de saída com comentários descrevendo como a mega-menu-columns-
classe deve contar as coisas:
<ul>
<!-- +1 because this has a class of "widget" -->
<li id="menu-item-1" class="widget menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1 mega-menu-columns-3">
<a href="http://www.example.com/about/">
About Us
</a>
<!-- +1 because a drop down exists -->
<!-- gets added by my walker -->
<section>
<!-- end gets added by my walker -->
<ul class="sub-menu">
<!-- +0 because this "break" is the first child -->
<li id="menu-item-2" class="break menu-item menu-item-type-post_type menu-item-object-page menu-item-2">
<a href="http://www.example.com/about/company-profile/">
Company Profile
</a>
<ul>
<!-- +0 because this "break" is in level 2 -->
<li id="menu-item-3" class="break menu-item menu-item-type-post_type menu-item-object-page menu-item-3">
<a href="http://www.example.com/about/our-team/">
Our Team
</a>
</li>
</ul>
</li>
<li id="menu-item-4" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4">
<a href="http://www.example.com/about/leadership-team/">
Leadership Team
</a>
</li>
<li id="menu-item-5" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-5">
<a href="http://www.example.com/about/professional-affiliations/">
Professional Affiliations
</a>
</li>
<!-- gets added by my walker -->
</ul>
<ul class="sub-menu">
<!-- end gets added by my walker -->
<!-- +1 because this "break" is in level 1 and not the first child -->
<li id="menu-item-6" class="break menu-item menu-item-type-post_type menu-item-object-page menu-item-6">
<a href="http://www.example.com/about/clients/">
Clients
</a>
</li>
<li id="menu-item-7" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7">
<a href="http://www.example.com/about/partnerships/">
Partnerships
</a>
</li>
</ul>
<!-- gets added by my walker for .widget -->
<section>
<header>
<h1>Widget Title</h1>
</header>
<p>This is a widget. It was hard to make appear!</p>
</section>
<!-- end gets added by my walker for .widget -->
<!-- gets added by my walker -->
</section>
<!-- end gets added by my walker -->
</li>
</ul>
UPDATE: Aqui estão minhas Walker e funções finais. Isso faz exatamente o que eu queria. Obrigado pela ajuda!
// mega menu walker
class megaMenuWalker extends Walker_Nav_Menu {
private $column_limit = 3;
private $show_widget = false;
private $column_count = 0;
static $li_count = 0;
function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
$classes = empty($item->classes) ? array() : (array) $item->classes;
$item_id = $item->ID;
if ($depth == 0) {
self::$li_count = 0;
}
if ($depth == 0 && in_array("widget", $classes)) {
$this->show_widget = true;
$this->column_count++;
}
if ($depth == 1 && self::$li_count == 1) {
$this->column_count++;
}
if ($depth == 1 && in_array("break", $classes) && self::$li_count != 1 && $this->column_count < $this->column_limit) {
$output .= "</ul><ul class=\"sub-menu\">";
$this->column_count++;
}
$class_names = join(" ", apply_filters("nav_menu_css_class", array_filter($classes), $item)); // set up the classes array to be added as classes to each li
$class_names = " class=\"" . esc_attr($class_names) . "\"";
$output .= sprintf(
"<li id=\"menu-item-%s\"%s><a href=\"%s\">%s</a>",
$item_id,
$class_names,
$item->url,
$item->title
);
self::$li_count++;
}
function start_lvl(&$output, $depth = 0, $args = array()) {
if ($depth == 0) {
$output .= "<section>";
}
$output .= "<ul class=\"sub-menu\">";
}
function end_lvl(&$output, $depth = 0, $args = array()) {
$output .= "</ul>";
if ($depth == 0) {
if ($this->show_widget) {
ob_start();
dynamic_sidebar("Navigation Callout");
$widget = ob_get_contents();
ob_end_clean();
$output .= $widget;
$this->show_widget = false;
}
$output .= "</section>";
}
}
function end_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
if ($depth == 0 && $this->column_count > 0) {
$this->column_count = 0;
}
$output .= "</li>";
}
}
// add mega-menu-columns-# classes
function add_column_number($items, $args) {
static $column_limit = 3;
static $post_id = 0;
static $x_key = 0;
static $column_count = 0;
static $li_count = 0;
$tmp = array();
foreach($items as $key => $item) {
if (0 == $item->menu_item_parent) {
$x_key = $key;
$post_id = $item->ID;
$column_count = 0;
$li_count = 0;
if (in_array("widget", $item->classes, 1)) {
$column_count++;
}
}
if ($post_id == $item->menu_item_parent) {
$li_count++;
if ($column_count < $column_limit && $li_count == 1) {
$column_count++;
}
if (in_array("break", $item->classes, 1) && $li_count > 1 && $column_count < $column_limit) {
$column_count++;
}
$tmp[$x_key] = $column_count;
}
}
foreach($tmp as $key => $value) {
$items[$key]->classes[] = sprintf("mega-menu-columns-%d", $value);
}
unset($tmp);
return $items;
};
// add the column classes
add_filter("wp_nav_menu_args", function($args) {
if ($args["walker"] instanceof megaMenuWalker) {
add_filter("wp_nav_menu_objects", "add_column_number");
}
return $args;
});
// stop the column classes function
add_filter("wp_nav_menu", function( $nav_menu ) {
remove_filter("wp_nav_menu_objects", "add_column_number");
return $nav_menu;
});
Warning: Missing argument 2 for add_column_number()
Você encontrou esse problema?function add_column_number($items, $args) {
parafunction add_column_number($items) {
remover o$args
e funciona bem para mim com essa mudança, bem estranho! Obrigado por compartilhar o seu código, embora seja apenas o que eu precisava por um longo tempoRespostas:
Se eu entendi a configuração do problema corretamente, você pode tentar fazer a contagem de classes de quebra e widget dentro do
wp_nav_menu_objects
filtro.Aqui está um exemplo atualizado, ele foi expandido devido à parte extra de depuração:
Com sua árvore de menus atual, recebo essas informações de depuração:
Se você deseja verificar se o objeto walker é da
megaMenuWalker
classe, pode usar:ao invés de
Eu espero que isso ajude.
fonte
<li>
elementos filhos diretos , não ao atual<li>
. Ele precisa verificar se é um filho direto, e não o primeiro filho que também tem a classebreak
.break
. Na verdade, ele precisa contar se os filhos diretos têm a classe debreak
, não ela própria, e excluir o primeiro filholi
da criançaul
, se isso faz sentido.<li>
itens raiz estejam em profundidade0
e, em seguida, conto as classes de quebra / widget dos subitens<li>
em profundidade1
. Eu acho que eu deveria começar o$x_cols
em1
vez de0
, já quen
breaks dán+1
colunas.