admin管理员组文章数量:1410737
I'm using a WordPress Menu to create a navigation structured like this:
- Home
- About
- Contact
- Sub Page
Using this code from kuroi's response here I'm able to add first-menu-item
and last-menu-item
classes to the list items above:
function add_first_and_last($output) {
$output = preg_replace('/class="menu-item/', 'class="first-menu-item menu-item', $output, 1);
$output = substr_replace($output, 'class="last-menu-item menu-item', strripos($output, 'class="menu-item'), strlen('class="menu-item'));
return $output;
}
add_filter('wp_nav_menu', 'add_first_and_last');
However the last-menu-item
class is being added to the Sub Page list item (because it's the last) rather than to the Contact list item.
Question: How can I make this function apply only to the top level items of a menu?
Thanks!
I'm using a WordPress Menu to create a navigation structured like this:
- Home
- About
- Contact
- Sub Page
Using this code from kuroi's response here I'm able to add first-menu-item
and last-menu-item
classes to the list items above:
function add_first_and_last($output) {
$output = preg_replace('/class="menu-item/', 'class="first-menu-item menu-item', $output, 1);
$output = substr_replace($output, 'class="last-menu-item menu-item', strripos($output, 'class="menu-item'), strlen('class="menu-item'));
return $output;
}
add_filter('wp_nav_menu', 'add_first_and_last');
However the last-menu-item
class is being added to the Sub Page list item (because it's the last) rather than to the Contact list item.
Question: How can I make this function apply only to the top level items of a menu?
Thanks!
Share Improve this question asked May 26, 2013 at 13:01 Alec RustAlec Rust 4161 gold badge7 silver badges20 bronze badges5 Answers
Reset to default 2I would lean very much towards a custom walker for this but I think I've managed to make it work using part of that code and some of my own.
function add_position_classes_wpse_100781($classes, $item, $args) {
static $fl;
if (0 == $item->menu_item_parent) {
$fl = (empty($fl)) ? 'first' : 'middle';
$classes[] = $fl.'-menu-item';
}
return $classes;
}
add_filter('nav_menu_css_class','add_position_classes_wpse_100781',1,3);
function replace_class_on_last_occurance_wpse_100781($output) {
$output = substr_replace(
$output,
'last-menu-item ',
strripos($output, 'middle-menu-item'),
strlen('middle-menu-item')
);
return $output;
}
add_filter('wp_nav_menu', 'replace_class_on_last_occurance_wpse_100781');
What I did was add first-menu-item
and middle-menu-item
to top level items only with the first filter on nav_menu_css_class
. Then with the second filter I replaced the last occurrence of middle-menu-item
with last-menu-item
.
It works for the few test cases I tried.
I have little fix on Bainternet code, because this code not work if last item has sub item
function wpb_first_and_last_menu_class($items) {
$items[1]->classes[] = 'first-menu-item'; // add first class
$cnt = count($items);
while($items[$cnt--]->post_parent != 0); // find last li item
$items[$cnt+1]->classes[] = 'last-menu-item'; // last item class
return $items;
}
add_filter('wp_nav_menu_objects', 'wpb_first_and_last_menu_class'); //filter to iterate each menu
something like this:
function add_first_and_last_classes_wpa100781($items) {
$items[1]->classes[] = 'first';
$items[count($items)]->classes[] = 'last';
return $items;
}
add_filter('wp_nav_menu_objects', 'add_first_and_last_classes_wpa100781');
I would recommend:
1) skip adding the first menu item class. That's extra php that you don't need. Using ul > li:first-child
will let you target the first menu item in either CSS or as a jQuery selector. :first-child
has great browser support (more than :last-child, so I would add a class for the last menu item).
2) Find the last top-level menu item and add a class to it. Drop this code into your theme's functions.php file and it will add a class to only the last top-level navigation item instead of the very last navigation item like many of the code snippets in the other answers here.
// Add a class to the last top-level menu item
function fancy_last_menu_item_class($items) {
// Create an empty array to hold the array ID's of top level menu items
$topLevelMenuItemIDs = array();
// Loop through all of the menu $items
for($i=0,$count=count($items);$i<$count;$i++){
// Check if the 'menu_item_parent' property is set to '0'
if($items[$i]->menu_item_parent == 0){
// This item has no parent menu items, so it's top-level.
// Add its array ID to the top level menu item IDs array.
$topLevelMenuItemIDs[] = $i;
}
}
// Count how many top level nav items were found, so you can target the last one
$topLevelMenuItemCount = count($topLevelMenuItemIDs);
// Add a class to the last top level navigation item.
$lastMenuItemClass = 'last-menu-item';
$items[$topLevelMenuItemIDs[--$topLevelMenuItemCount]]->classes[] = $lastMenuItemClass;
// Return the items with the altered last item
return $items;
}
// Hook the last menu item class to the wp_nav_menu_objects filter
add_filter('wp_nav_menu_objects', 'fancy_last_menu_item_class');
Very late to the party, but was looking for something that handled doing this for submenus and subsubmenus also, ended up coming up with this, writing it out long-hand to with comments to help get my head around it.
Basically rather than trying to loop backwards, it loops forwards and checks the next menu item parent.
add_filter('wp_nav_menu_objects', 'first_last_nav_menu_item_classes');
function first_last_nav_menu_item_classes($items) {
// --- loop items to add classes ---
$itemcount = count($items);
$lastmenuitems = $lastsubmenuitems = $lastsubsubmenuitems = array();
foreach ($items as $i => $item) {
// --- get menu item parent ---
$itemparent = $item->menu_item_parent;
// --- maybe get next item and parent ---
if (isset($nextitem)) {unset($nextitem);}
if (isset($items[($i+1)])) {
$nextitem = $items[($i+1)];
$nextparent = $nextitem->menu_item_parent;
}
if ($itemparent == 0) {
// --- clear for top level menu item ---
if (isset($parentmenu)) {unset($parentmenu);}
$foundsubmenu = $foundsubsubmenu = false;
// --- set first menu class and store current menu index ---
if ($i == 1) {$items[$i]->classes[] = 'first-menu-item';} else {$lastfoundmenu = $i;}
// --- check if next item is a submenu of this menu ---
if ( isset($nextitem) && ($nextparent == $item->ID) ) {$parentmenu = $item->ID;}
// --- store last found submenu and subsubmenu items ---
if (isset($lastfoundsubmenu)) {
$lastsubmenuitems[] = $lastfoundsubmenu;
unset($lastfoundsubmenu);
}
if (isset($lastfoundsubsubmenu)) {
$lastsubsubmenuitems[] = $lastfoundsubsubmenu;
unset($lastfoundsubsubmenu);
}
} elseif (isset($parentmenu)) {
// --- subsubmenu items ---
if ( isset($parentsubmenu) && ($itemparent == $parentsubmenu) ) {
// --- set first subsubmenu item class ---
if (!$foundsubsubmenu) {
$items[$i]->classes[] = 'first-subsubmenu-item';
$foundsubsubmenu = true;
}
// --- store last subsubmenu item ---
if ( !isset($nextitem) || ( isset($nextitem) && ($nextparent != $parentsubmenu) ) ) {
$items[$i]->classes[] = 'last-subsubmenu-item';
}
} elseif ($itemparent == $parentmenu) {
// --- submenu items ---
$foundsubsubmenu = false;
// --- add class for first submenu item ---
if (!$foundsubmenu) {
$items[$i]->classes[] = 'first-submenu-item';
$foundsubmenu = true;
}
// --- store last submenu item ---
if ( !isset($nextitem) || ( isset($nextitem) && ($nextparent != $parentmenu) ) ) {
$lastfoundsubmenu = $i;
}
// --- set parent submenu ---
if ( isset($nextitem) && ($nextparent == $item->ID) ) {$parentsubmenu = $item->ID;}
}
}
}
// --- if submenu or subsubmenu item is last item ---
if (isset($lastfoundsubmenu)) {$lastsubmenuitems[] = $lastfoundsubmenu;}
if (isset($lastfoundsubsubmenu)) {$lastsubsubmenuitems[] = $lastfoundsubsubmenu;}
// --- add classes to last found menu items ---
$items[$lastfoundmenu]->classes[] = 'last-menu-item';
if (count($lastsubmenuitems) > 0) {
foreach ($lastsubmenuitems as $index) {
$items[$index]->classes[] = 'last-submenu-item';
}
}
if (count($lastsubsubmenuitems) > 0) {
foreach ($lastsubsubmenuitems as $index) {
$items[$index]->classes[] = 'last-subsubmenu-item';
}
}
return $items;
}
Good inclusion to my theme, hope it helps someone looking.
本文标签: Adding first and last class to Menu on top level only
版权声明:本文标题:Adding first and last class to Menu on top level only 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744923085a2632417.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论