Menu - MRDezigner/Api-WordPress GitHub Wiki
Nosso menu poderá ter quantos níveis o usuário quiser (apesar de não recomendado) ele irá exibir todos os submenus categorizados na forma em que foram registrados na área administrativa (wp-admin) do WordPress.
functions.php
Só para lembrar, nosso menu já está registrado em nosso functions.php
, veja:
Configurações do tema
function tutsup_setup() {
// Ativa o feed
add_theme_support( 'automatic-feed-links' );
// Ativa imagens destacadas
add_theme_support( 'post-thumbnails' );
// Ativa posts-formats
add_theme_support( 'post-formats', array( 'audio', 'aside', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video' ) );
// Adiciona tamanhos de imagens customizados
add_image_size( 'tutsup-small', 430, 286, true );
add_image_size( 'tutsup-large', 1140, 1140, false );
add_image_size( 'tutsup-thumbnails', 200, 133, true );
// Registra um menu
register_nav_menus( array(
'header' => 'Header',
) );
}
add_action( 'after_setup_theme', 'tutsup_setup' );
Veja as linhas marcadas acima. Nosso menu se chamará “header“, você pode modificar esse nome se quiser.
Acredite se quiser, mas você não vai precisar digitar nada em HTML. Simplesmente abra nosso arquivo header.php e adicione o seguinte ao final:
<?php
$header_menu_args = array(
'theme_location' => 'header',
'menu' => '',
'container' => 'nav',
'container_class' => 'main-menu clearfix',
'container_id' => '',
'menu_class' => '',
'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' => ''
);
wp_nav_menu( $header_menu_args );
?>
Pronto, agora seu menu já deve estar aparecendo sem nenhum estilo. O único serviço que teremos é em nosso CSS, então vamos para o arquivo css/main-style.css.
Observação: É necessário que você configure o menu na área administrativa do WordPress e selecione “header” como local.
###CSS do nosso menu###
Todo menu WordPress pode ter submenus de vários níveis diferentes, o que indica que o usuário pode optar por adicionar submenu dentro de submenu.
Para não privarmos o usuário de ter a possibilidade de criar o menu da maneira que preferir, vamos exibir todos os submenus categorizados nos mesmos níveis em que foram incluídos na wp-admin.
Para isso, teremos que utilizar alguns truques de CSS, veja:
###Menu principal###
#####Container do menu#####
.main-menu {
background: #1e88e5;
}
.main-menu a {
color: #fff;
text-transform: uppercase;
font-weight: 700;
font-size: 12px;
letter-spacing: 0.02em;
}
.main-menu a:hover {
background: #4f9ee3;
}
/* Container dos links do menu - Espaço de 30px para acompanhar o layout */
.main-menu > ul {
margin: 0 30px;
}
#####Mantém os sub-menus nas posições corretas#####
.main-menu li {
position: relative;
}
.main-menu > ul > li {
float: left;
}
.main-menu > ul > li > a {
display: block;
padding: 10px;
}
.main-menu > ul > .menu-item-has-children > a {
padding: 10px 30px 10px 10px;
}
#####Adiciona uma seta para baixo nos itens que tem sub-menu#####
.main-menu > ul > .menu-item-has-children > a:after{
display: block;
content: ' ';
border: 5px solid transparent;
border-top-color: #fff;
right: 10px;
top: 50%;
margin-top: -2px;
height: 5px;
width: 5px;
position: absolute;
z-index: 9998;
}
#####Mantém os sub-menus mais abaixo nas posições corretas#####
.menu-item-has-children {
position: relative;
}
.menu-item-has-children .sub-menu {
position: absolute;
background: #ddd;
min-width: 200px;
display: none;
z-index: 9999;
}
.menu-item-has-children .sub-menu li {
border-bottom: 2px solid #ccc;
}
.menu-item-has-children .sub-menu a {
display: block;
padding: 10px;
color: #555;
}
/* Sub-menus dentro de sub-menus sempre aparecem ao lado direito */
.sub-menu .sub-menu {
position: absolute;
min-width: 200px;
left: 100%;
top: -0;
}
#####Não precisamos de javascript para mostra os sub-menus#####
.menu-item-has-children:hover >.sub-menu {
display: block;
}
.menu-item-has-children:hover >.sub-menu a:hover {
background: #eee;
}
A partir daqui, seu menu deverá estar mais ou menos assim:
Caso queira baixar o tema que criamos no ponto que paramos nesse tutorial, segue o link:
https://www.todoespacoonline.com/w/tuts/2014/09/tutsup-tema-basico-1-7.zip
Fonte: https://www.todoespacoonline.com/w/2014/09/menu-em-temas-wordpress/
Add funcionalidades ao Menu
###Como add class ao link em wp_nav_menu
###
function add_menuclass($ulclass) {
return preg_replace('/<a /', '<a class="list-group-item"', $ulclass);
}
add_filter('wp_nav_menu','add_menuclass');
###Remover class em wp_nav_menu
###
function remove_css_id_filter($var) {
return is_array($var) ? array_intersect($var, array('current-menu-item')) : '';
}
add_filter( 'page_css_class', 'remove_css_id_filter', 100, 1);
add_filter( 'nav_menu_item_id', 'remove_css_id_filter', 100, 1);
add_filter( 'nav_menu_css_class', 'remove_css_id_filter', 100, 1);
Outra maneira de Saída limpa para wp_nav_menu ()
<?php
class MV_Cleaner_Walker_Nav_Menu extends Walker {
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"sub-menu\">\n";
}
function end_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}
function start_el(&$output, $item, $depth, $args) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes = in_array( 'current-menu-item', $classes ) ? array( 'current-menu-item' ) : array();
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = strlen( trim( $class_names ) ) > 0 ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', '', $item, $args );
$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names .'>';
$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
function end_el(&$output, $item, $depth) {
$output .= "</li>\n";
}
}
?>
Em seguida, certifique-se de especificar o novo Walker personalizado ao chamar wp_nav_menu()
.
<?php
wp_nav_menu( array( 'walker' => new MV_Cleaner_Walker_Nav_Menu() ) );
?>
Exemplo:
<ul id="menu-main" class="menu">
<li><a href="a#">About</a></li>
<li><a href="#">Featured</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">Blog</a></li>
</ul>
Você pode usar estes opcionalmente para adicionar classes e id's.
function mv_custom_menu_classes( $c )
{
$c[] = 'test';
return $c;
}
add_filter( 'nav_menu_css_class', 'mv_custom_menu_classes' );
Produziria:
<ul id="menu-main" class="menu">
<li class="test"><a href="#">Home</a></li>
</ul>
###Usando Boostrap###
Este é o código que estou usando, é um walker nav personalizado para o BootStrap, mas você poderia facilmente adaptá-lo ao seu próprio code. Dessa maneira, você poderia copiar & colar meu code do nav e ao certo mudar esta linha:
`$class_names .= ' dropdown';``
para
$class_names .= ' sub-menu';
Espero que isto ajude.
/**
* Custom Bootstrap Nav Walker
*/
class macho_bootstrap_walker extends Walker_Nav_Menu
{
/**
* @see Walker::start_lvl()
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of page. Used for padding.
*/
public function start_lvl(&$output, $depth = 0, $args = array())
{
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul role=\"menu\" class=\" dropdown-menu\">\n";
}
/**
* @see Walker::start_el()
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param int $current_page Menu item ID.
* @param object $args
*/
public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
{
$indent = ($depth) ? str_repeat("\t", $depth) : '';
/**
* Dividers, Headers or Disabled
* =============================
* Determine whether the item is a Divider, Header, Disabled or regular
* menu item. To prevent errors we use the strcasecmp() function to so a
* comparison that is not case sensitive. The strcasecmp() function returns
* a 0 if the strings are equal.
*/
if (strcasecmp($item->attr_title, 'divider') == 0 && $depth === 1) {
$output .= $indent . '<li role="presentation" class="divider">';
} else if (strcasecmp($item->title, 'divider') == 0 && $depth === 1) {
$output .= $indent . '<li role="presentation" class="divider">';
} else if (strcasecmp($item->attr_title, 'dropdown-header') == 0 && $depth === 1) {
$output .= $indent . '<li role="presentation" class="dropdown-header">' . esc_attr($item->title);
} else if (strcasecmp($item->attr_title, 'disabled') == 0) {
$output .= $indent . '<li role="presentation" class="disabled"><a href="#">' . esc_attr($item->title) . '</a>';
} else {
$class_names = $value = '';
$classes = empty($item->classes) ? array() : (array)$item->classes;
$classes[] = 'menu-item-' . $item->ID;
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
if ($args->has_children)
$class_names .= ' dropdown';
if (in_array('current-menu-item', $classes))
$class_names .= ' active';
$class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
$id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args);
$id = $id ? ' id="' . esc_attr($id) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names . '>';
$atts = array();
$atts['title'] = !empty($item->title) ? $item->title : '';
$atts['target'] = !empty($item->target) ? $item->target : '';
$atts['rel'] = !empty($item->xfn) ? $item->xfn : '';
$atts['custom'] = !empty($item->custom) ? $item->custom : '';
// If item has_children add atts to a.
if ($args->has_children && $depth === 0) {
$atts['href'] = '#';
$atts['data-toggle'] = 'dropdown';
$atts['class'] = 'dropdown-toggle';
$atts['aria-haspopup'] = 'true';
} else {
$atts['href'] = !empty($item->url) ? $item->url : '';
}
$atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args);
$attributes = '';
foreach ($atts as $attr => $value) {
if (!empty($value)) {
$value = ('href' === $attr) ? esc_url($value) : esc_attr($value);
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
$item_output = $args->before;
/*
* Glyphicons
* ===========
* Since the the menu item is NOT a Divider or Header we check the see
* if there is a value in the attr_title property. If the attr_title
* property is NOT null we apply it as the class name for the glyphicon.
*/
if (!empty($item->attr_title))
$item_output .= '<a' . $attributes . '><span class="glyphicon ' . esc_attr($item->attr_title) . '"></span> ';
else
$item_output .= '<a' . $attributes . '>';
$item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
$item_output .= ($args->has_children && 0 === $depth) ? ' <span class="caret"></span></a>' : '</a>';
$item_output .= $args->after;
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
}
/**
* Traverse elements to create list from elements.
*
* Display one element if the element doesn't have any children otherwise,
* display the element and its children. Will only traverse up to the max
* depth and no ignore elements under that depth.
*
* This method shouldn't be called directly, use the walk() method instead.
*
* @see Walker::start_el()
* @since 2.5.0
*
* @param object $element Data object
* @param array $children_elements List of elements to continue traversing.
* @param int $max_depth Max depth to traverse.
* @param int $depth Depth of current element.
* @param array $args
* @param string $output Passed by reference. Used to append additional content.
* @return null Null on failure with no changes to parameters.
*/
public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output)
{
if (!$element)
return;
$id_field = $this->db_fields['id'];
// Display this element.
if (is_object($args[0]))
$args[0]->has_children = !empty($children_elements[$element->$id_field]);
parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
/**
* Menu Fallback
* =============
* If this function is assigned to the wp_nav_menu's fallback_cb variable
* and a manu has not been assigned to the theme location in the WordPress
* menu manager the function with display nothing to a non-logged in user,
* and will add a link to the WordPress menu manager if logged in as an admin.
*
* @param array $args passed from the wp_nav_menu function.
*
*/
public static function fallback($args)
{
if (current_user_can('manage_options')) {
extract($args);
$fb_output = null;
if ($container) {
$fb_output = '<' . $container;
if ($container_id)
$fb_output .= ' id="' . $container_id . '"';
if ($container_class)
$fb_output .= ' class="' . $container_class . '"';
$fb_output .= '>';
}
$fb_output .= '<ul';
if ($menu_id)
$fb_output .= ' id="' . $menu_id . '"';
if ($menu_class)
$fb_output .= ' class="' . $menu_class . '"';
$fb_output .= '>';
$fb_output .= '<li><a href="' . admin_url('nav-menus.php') . '">Add a menu</a></li>';
$fb_output .= '</ul>';
if ($container)
$fb_output .= '</' . $container . '>';
echo $fb_output;
}
}
}
Alterar a classe do submenu padrão do WP
function change_submenu_class($menu) {
$menu = preg_replace('/ class="sub-menu"/','/ class="myclass" /',$menu);
return $menu;
}
add_filter('wp_nav_menu','change_submenu_class');