Jump to content

Main navigation class for parent items


SamC
 Share

Recommended Posts

I'm having a little difficulty implementing a parent class on my two menus. Structure like so:

Home
 - Link 1
 -- Link 1.1
 -- Link 1.2
 - Link 2
 -- Link 2.1
 -- Link 2.2
 - Link 3

The main menu displays the top level items, if the top level items has children, they are displayed in the sub-menu. I have a function like this:

/**
 * Render navigation from array of pages
 *
 * @param PageArray $items
 * @param $menuClassName
 * @return string
 *
 */
function renderMenu($items, $menuClassName) {

    $str = '';

    foreach ($items as $item) {

    if ($item->showInMenu == true) {

            $menuText = $item->get('menuLinkTitle|title');

            if ($item->id == wire('page')->id) {

                $str .= "<li class=\"current\">";
            }
            else {
                $str .= '<li>';
            } 

            $str .= "<a href=\"$item->url\">$menuText</a></li>";
        }
    }

    // if output was generated above, wrap it in a <ul>
    if ($str) {
        $str = "<ul class=\"$menuClassName\">$str</ul>";
    }

    return $str;
}

All pages are routed through main, so in main.php, I have this to render the two menus.

<!-- main navigation -->
    <nav>
        <?php
            $arr = $home->and($home->children);
            echo renderMenu($arr, 'main-menu');
        ?>
    </nav>

    <!-- sub navigation -->
    <nav>
        <?php
            $className = 'sub-menu';

            // if current page is not home
            if (!($page->id == 1)) {
                // if current page has children
                if ($page->numChildren > 0) {
                    echo renderMenu($page->children, $className);
                }
                // if on a child page, still show sub-menu
                if (count($page->parents) > 1) {
                    echo renderMenu($page->parent->children, $className);
                }
            }
        ?>
    </nav>

What I want to do, is when, for example, on 'Link 1.1' or 'Link 1.2' page, a parent class is added on Link 1. This only affects the top menu.

I was thinking along the lines of, if on 'Link 1.1' page, the current pages' rootParent (Link 1) would have the same id as the id of one of the items (its parent) of the array passed in to the function, if that makes any sense at all. Like:

// this is passed in
$arr = $home->and($home->children);
echo renderMenu($arr, 'main-menu');

// in renderMenu()
// add parent class
if ($item->id == wire('page')->rootParent->id) {
    $str .= "<li class=\"current-parent\">";
}
// add current class
if ($item->id == wire('page')->id) {
      $str .= "<li class=\"current\">";
}
else {
    $str .= '<li>';
} 

No luck so far though, and not sure where this would fit into my function. The furthest I got was getting a 'parent-page' class onto the main menu, but then the homepage was also 'parent-class' when on 'Link 1', 'Link 2' etc.. because they all share home as parent page. In another attempt, a link item would end up with 'current' and 'current-parent' at the same time.

Not sure whether (a) this should be a nested if/else, or maybe a if/elseif/else or (b) if I've even used the correct selectors to get the parent page. Logic fail basically.

Any help would be most appreciated. Thanks.

Link to comment
Share on other sites

10 hours ago, Robin S said:

Not a proper answer to your issue, but have you had a look at MarkupSimpleNavigation? It will take care of your current/parent classes, plus a lot more (if you want it).

I've read about this, but I would only want to use a module once I know how to do this manually. It would save time of course, but now I've learnt about '$a->has('selector')'.

2 hours ago, szabesz said:

@SamC Hi,

You might find the solution in this thread:

Especially @gebeer's solution might be the one you are looking for, if I'm not mistaken.

Spot on! Thanks to you and @gebeer. Complete function works now as follows (with parent page class added):

/**
 * Render navigation from array of pages
 *
 * @param PageArray $items
 * @param $menuClassName
 * @return string
 *
 */
function renderMenu($items, $menuClassName) {

    // if we were given a single Page rather than a group of them, we'll pretend they
    // gave us a group of them (a group/array of 1)
    if($items instanceof Page) {
        $items = array($items);
    }

    $str = '';

    foreach ($items as $item) {
    
    // checkbox on page template, fieldname 'showInMenu'
    if ($item->showInMenu == true) {

            $menuText = $item->get('menuLinkTitle|title');

            if ($item->id == wire('page')->id) {
                $str .= "<li class=\"current\">";
            }
            elseif (wire('page')->parents->has($item) && !($item->id == 1)) {
                  $str .= "<li class=\"current-parent\">";
            }
            else {
                $str .= '<li>';
            } 

            $str .= "<a href=\"$item->url\">$menuText</a></li>";
        }
    }

    // if output was generated above, wrap it in a <ul>
    if ($str) {
        $str = "<ul class=\"$menuClassName\">$str</ul>";
    }

    return $str;
}

 

  • Like 2
Link to comment
Share on other sites

Needed to add a bit more in order not to have the homepage constantly having a 'current-parent' class regardless of which page you're on:

// _func.php
elseif (wire('page')->parents->has($item) && !($item->id == 1)) {
    $str .= "<li class=\"current-parent\">";
}
      
// crude testing in main.css
.current a {
    color: red;
}

.current-parent a {
    color: yellow;
}      

Works great :)

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...