• The site I’m working on is divided in four global sections, basically four parent menu items with different sub menus each. The requirement is that the “current” parent menu item with its sub menu should always be at the top (i. e. the first item). So, simply spoken: if I click parent item 2 or one of its children, parent should become parent item 1.

    At the same time, each global section has a slightly different style (e. g. different color scheme). So, for instance, whenever a page assigned to parent item 1 or its children is active, the text color should be green and whenever a page assigned to parent item 2 or its children is active, the text color should be blue etc.

    I’m going to tell you what I’ve currently done so far but if you think there is a simpler or smarter way to do it I’m certainly open for suggestions.
    So, the way I’ve currently set up the whole thing is that I’ve created categories for pages, and for each top-level category a new menu is registered:

    $main_categories = get_categories( array(
    	'orderby' => 'name',
    	'parent'  => 0
    ));
    foreach($main_categories as $key => $cat):
    	register_nav_menu('nav_'.$key, 'Menu for '.$cat->name);
    endforeach;
    

    This way each category gets its own user-editable sub menu. And the template code to output the menu in header.php looks like this at the moment:

    <ul>
    <?php
    $main_categories = get_categories( array(
    	'orderby' => 'name',
    	'parent'  => 0,
    	'hide_empty' => false
    ));
    $nav_locations = get_nav_menu_locations(); // retrieve all existing nav menu locations
    // loop through main categories and create menu if assigned in admin
    foreach($main_categories as $key => $cat):
    	if(isset($nav_locations['nav_'.$key])): // if array item for menu exists
    		$menu_id = $nav_locations['nav_'.$key]; // ID of the menu assigned in the current iteration
    		$items = wp_get_nav_menu_items($menu_id); // get all menu items of current iteration’s menu
    ?>
    <!-- begin parent list item -->
    <li class="<?= $cat->slug ?>">
    	<a<?php if($items) { ?> href="<?= $items[0]->url; ?>"<?php } ?>><?= $cat->name ?></a>
    	<span><?= $cat->description ?></span>
    <?php
    		if($items): // if child items exist
    ?>
    		<ul>
    <?php
    			foreach($items as $item): // loop over child menu items
    				if($item->menu_item_parent): // output all child menu items
    ?>
    			<li><a href="<?= $item->url ?>"><?= $item->title ?></a></li>
    <?php
    				endif;
    			endforeach;
    ?>
    		</ul>
    </li>
    <?php
    		endif;
    	endif;
    endforeach;
    ?>
    </ul>
    

    This works good so far. But the challenge is now to re-order the category array (parent items) according to the “current” status of the child menu items, i.e. if one of the child items is a “current page” the parent should be first in the category array.

    Does that make sense to you? What are the options here? And really, if you think that there is a better approach than my current one, please don’t hesitate to tell me about it. I’d be very grateful for any inspiration you can give me. And let me know if you need any additional info.

Viewing 6 replies - 1 through 6 (of 6 total)
  • @10010110

    Not that I have used it, but isn’t this default behaviour from Multisite ?
    https://wisdmlabs.com/blog/set-default-theme-logo-menu-subsites-wordpress-multisite/

    Thread Starter VIPStephan

    (@10010110)

    Thanks for your reply. Yeah, I’ve thought about a multisite set-up but even though it might look like it to the visitor, it’s not actually multiple sites. The thing is that the same types of content could be present in multiple areas. I don’t think multiple separate sites are appropriate here.

    Moderator bcworkz

    (@bcworkz)

    Using separate menus to accomplish this is OK, but it makes maintaining the menus into the future more difficult because the same change needs to be applied to every menu. OTOH it makes completely bespoke menus for each condition possible.

    You can use the ‘wp_nav_menu_items’ filter to dynamically rearrange menu items before they are concatenated into a string and output. This way future changes can be done in one place, but how items get rearranged could be so specific that the code needs to be altered should the menu items be changed. What you already have might be better if that’s the case.

    Ideally the rearrangement code is generic enough so that editing the menu would not require code modification.

    Thread Starter VIPStephan

    (@10010110)

    Thanks bcworkz, but I’m not quite sure what you’re suggesting me right now.

    So, to reiterate: my global parent menu is created from post categories, the sub menus are actual wp_nav_menu()s managed by the user. What I want is the parent menu items to be reordered depending on the currently active sub menu item. Is this possible at all? And if yes, how (with my current setup, or a different approach)?

    Edit: What makes this even harder, I suppose, is the fact that menu items aren’t necessarily associated with pages but can be post archives etc. How is the “current menu item” situation handled there?

    Moderator bcworkz

    (@bcworkz)

    The current menu item classes are determined by matching up the requested page with the various menu items. When there is a match, appropriate classes are added through the function _wp_menu_item_classes_by_context() which is called from wp_nav_menu().

    I gave you the wrong filter name previously, apologies. The correct one is “wp_nav_menu_objects”. As the name implies, your filter callback is passed an ordered array of menu item objects. If your callback code returns rearranged items from the array, the menu output will be likewise rearranged.

    Thread Starter VIPStephan

    (@10010110)

    Hmmm, sorry, I’m kind of stuck with this, and I have a feeling that I’ve hit a dead end. Perhaps I’m overcomplicating things but I’m out of ideas.

    So, to recapitulate: Basically I have four top-level links, let’s call them

    
    - blue
    - red
    - green
    - yellow

    for the background color each should have for the purpose of this example. Each of these top-level links can and will have second and third-level children:

    
    - blue
    -- blue child A
    -- blue child B
    --- blue sub child 1b
    --- blue sub child 2b
    --- blue sub child 3b
    -- blue child C
    
    - red
    -- red child A
    --- red sub child 1a
    -- red child B
    --- red sub child 1b
    --- red sub child 2b
    
    - green
    -- green child A
    -- green child B
    
    - yellow
    -- yellow child A
    --- yellow sub child 1a
    --- yellow sub child 2a
    -- yellow child B
    -- yellow child C

    If any of the top-level links or any of their children are clicked, the pages should change color accordingly. The first issue with this is that sub items aren’t necessarily just pages, they could as well be category/post type archives.

    I know that the change of color could be done with a body class but how does the system know which item is the active one if a category archive link is clicked? This is the first issue. The second issue is to bring the active top-level item to the front of the list, i. e. if, for instance, “red sub child 1b” is clicked, the entire red section should become the first in the list of links.

    Would anyone please help me get on the right track? I’ll be forever grateful.

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Change order of menu items depending on current active page/item’ is closed to new replies.