0

Image to describe issue better

enter image description here

My boss is looking for a navigational link set up in the nav bar which is not a page itself, but instead displays 3 separate parent pages in the dropdown (www.website.com/turkey, /greece, /italy). He wishes to retain url structure for the new site to avoid excessive redirects and this issue is proving problematic for me to try and tackle on my own.

The Auto Nav itself uses php to generate the nav bar based on site structure so the only way to incorporate this without any php editing is to make the link a page (instead of just a blank link as my boss would like), but then it breaks the url file structure he wants to follow.

I think this would have to be addressed in php but i'm not that well versed in it myself so would really appreciate some guidance!

Apologies if this is a little unclear, if more clarity is needed please let me know!

<?php  defined('C5_EXECUTE') or die(_("Access Denied."));

$navItems = $controller->getNavItems();

/**
 * The $navItems variable is an array of objects, each representing a nav menu item.
 * It is a "flattened" one-dimensional list of all nav items -- it is not hierarchical.
 * However, a nested nav menu can be constructed from this "flat" array by
 * looking at various properties of each item to determine its place in the hierarchy
 * (see below, for example $navItem->level, $navItem->subDepth, $navItem->hasSubmenu, etc.)
 *
 * Items in the array are ordered with the first top-level item first, followed by its sub-items, etc.
 *
 * Each nav item object contains the following information:
 *  $navItem->url        : URL to the page
 *  $navItem->name       : page title (already escaped for html output)
 *  $navItem->target     : link target (e.g. "_self" or "_blank")
 *  $navItem->level      : number of levels deep the current menu item is from the top (top-level nav items are 1, their sub-items are 2, etc.)
 *  $navItem->subDepth   : number of levels deep the current menu item is *compared to the next item in the list* (useful for determining how many <ul>'s to close in a nested list)
 *  $navItem->hasSubmenu : true/false -- if this item has one or more sub-items (sometimes useful for CSS styling)
 *  $navItem->isFirst    : true/false -- if this is the first nav item *in its level* (for example, the first sub-item of a top-level item is TRUE)
 *  $navItem->isLast     : true/false -- if this is the last nav item *in its level* (for example, the last sub-item of a top-level item is TRUE)
 *  $navItem->isCurrent  : true/false -- if this nav item represents the page currently being viewed
 *  $navItem->inPath     : true/false -- if this nav item represents a parent page of the page currently being viewed (also true for the page currently being viewed)
 *  $navItem->attrClass  : Value of the 'nav_item_class' custom page attribute (if it exists and is set)
 *  $navItem->isHome     : true/false -- if this nav item represents the home page
 *  $navItem->cID        : collection id of the page this nav item represents
 *  $navItem->cObj       : collection object of the page this nav item represents (use this if you need to access page properties and attributes that aren't already available in the $navItem object)
 */


/** For extra functionality, you can add the following page attributes to your site (via Dashboard > Pages & Themes > Attributes):
 *
 * 1) Handle: exclude_nav
 *    (This is the "Exclude From Nav" attribute that comes pre-installed with concrete5, so you do not need to add it yourself.)
 *    Functionality: If a page has this checked, it will not be included in the nav menu (and neither will its children / sub-pages).
 *
 * 2) Handle: exclude_subpages_from_nav
 *    Type: Checkbox
 *    Functionality: If a page has this checked, all of that pages children (sub-pages) will be excluded from the nav menu (but the page itself will be included).
 *
 * 3) Handle: replace_link_with_first_in_nav
 *    Type: Checkbox
 *    Functionality: If a page has this checked, clicking on it in the nav menu will go to its first child (sub-page) instead.
 *
 * 4) Handle: nav_item_class
 *    Type: Text
 *    Functionality: Whatever is entered into this textbox will be outputted as an additional CSS class for that page's nav item (NOTE: you must un-comment the "$ni->attrClass" code block in the CSS section below for this to work).
 */


/*** STEP 1 of 2: Determine all CSS classes (only 2 are enabled by default, but you can un-comment other ones or add your own) ***/
foreach ($navItems as $ni) {
    $classes = array();

    if ($ni->isCurrent) {
        //class for the page currently being viewed
        $classes[] = 'nav-selected';
    }

    if ($ni->inPath) {
        //class for parent items of the page currently being viewed
        $classes[] = 'nav-path-selected';
    }

    /*
    if ($ni->isFirst) {
        //class for the first item in each menu section (first top-level item, and first item of each dropdown sub-menu)
        $classes[] = 'nav-first';
    }
    */

    /*
    if ($ni->isLast) {
        //class for the last item in each menu section (last top-level item, and last item of each dropdown sub-menu)
        $classes[] = 'nav-last';
    }
    */


    if ($ni->hasSubmenu) {
        //class for items that have dropdown sub-menus
        $classes[] = 'parent';
    }


    /*
    if (!empty($ni->attrClass)) {
        //class that can be set by end-user via the 'nav_item_class' custom page attribute
        $classes[] = $ni->attrClass;
    }
    */

    /*
    if ($ni->isHome) {
        //home page
        $classes[] = 'nav-home';
    }
    */

    /*
    //unique class for every single menu item
    $classes[] = 'nav-item-' . $ni->cID;
    */

    //Put all classes together into one space-separated string
    $ni->classes = implode(" ", $classes);
}


//*** Step 2 of 2: Output menu HTML ***/
echo '<div id="menu">';
echo '<ul class="nav menu">'; //opens the top-level menu

foreach ($navItems as $ni) {

    echo '<li class="' . $ni->classes . '">'; //opens a nav item

    echo '<a href="' . $ni->url . '" target="' . $ni->target . '" class="' . $ni->classes . '">' . $ni->name . '</a>';

    if ($ni->hasSubmenu) {
        echo '<ul>'; //opens a dropdown sub-menu
    } else {
        echo '</li>'; //closes a nav item
        echo str_repeat('</ul></li>', $ni->subDepth); //closes dropdown sub-menu(s) and their top-level nav item(s)
    }
}

echo '</ul>'; //closes the top-level menu
echo '</div>'; //closes the top-level menu-container
Nikos M.
  • 8,033
  • 4
  • 36
  • 43
Ziggles
  • 101
  • 1
  • 9
  • 1
    i'm not sure i understand where the problem is exactly? maybe you should edit the question. what does this mean "*but instead displays 3 separate parent pages in the dropdown (www.website.com/turkey, /greece, /italy)*"? – Nikos M. Apr 22 '15 at 09:53
  • Thanks for getting back to me. Sorry, I added a picture to better explain at the top of the page. The dropdown populates based on the sitemap. The sitemap is Home > Destinations > Turkey .etc at the moment, it needs to change to Home > Tukey .etc while keeping destinations in the auto nav bar – Ziggles Apr 22 '15 at 12:48
  • If it is non-essential and the items can be reached by other means as well, then I’d probably just use JavaScript to add those links to the navigation client-side. – CBroe Apr 22 '15 at 13:01
  • Thanks CBroe, can you offer up any advice as to how I would handle doing this in JS? I am mostly a HTML user so I'm not all that keyed up on JavaScript. I know some basics but something like this I feel requires a bit more experience! :P – Ziggles Apr 22 '15 at 13:22

1 Answers1

0

i would recommend to just add a special configuration to ammend the links of the auto nav menu like the following:

$navItems = $controller->getNavItems();

$special_config = array(
  "www.website.com/turkey" /* url */=> array( "level" => 2 ),
  "www.website.com/greece" /* url */=> array( "level" => 2 )
  // .. rest special config here
);

foreach ($navItems as &$navItem)
{
    if ( isset($special_config[$navItem->url]) )
    {
          foreach ($special_config[$navItem->url] as $k=>$v)
          {
              // adjust navItem params as needed here by key=>value
               $navItem->{$k} = $v;
          }
    }
}

// rest code follows
// ...

You can even make a function ammend_nav_menu like this:

function ammend_nav_menu($special_config, &$navItems)
{
    foreach ($navItems as &$navItem)
    {
        if ( isset($special_config[$navItem->url]) )
        {
              foreach ($special_config[$navItem->url] as $k=>$v)
              {
                  // adjust navItem params as needed here by key=>value
                   $navItem->{$k} = $v;
              }
        }
    }
}

and use as such:

$navItems = $controller->getNavItems();
ammend_nav_menu(array(
  "www.website.com/turkey" /* url */=> array( "level" => 2 ),
  "www.website.com/greece" /* url */=> array( "level" => 2 )
  // .. rest special config here
), $navItems);

The special configuration that ammends the menus can even be in a seprate php file and loaded / updated as needed

Nikos M.
  • 8,033
  • 4
  • 36
  • 43
  • Thanks for the advice and code, much appreciated although I must admit I am unsure of how I would go about applying this in relation to the php code for the nav. I have tried both methods how I thought it should go and I am not seeing a change yet but I am more than likely overseeing something – Ziggles Apr 22 '15 at 14:05
  • @Nexus1234, the solution uses a special configuration for certain links to put them under another level (e.g destinations) while by the new sitemap they should be under the top level (this is your problem). In the example solution i used `level` to become **2**, but since i do not know all parameters of the links and how they are related you will probably use another configuration, if needed – Nikos M. Apr 23 '15 at 03:45
  • @Nexus1234, you can even add a dummy menu ("destinations") and extra data in the ammended `navItems` so in your main loop you can construct the needed menu hierarchy for these links (i.e be under dummy menu "destinations") – Nikos M. Apr 23 '15 at 03:50
  • @Nexus1234, however instad of changing the main code to take care of these special cases (and thus complicatiing the rest code), a better csolution is to use a special configuration (which can change as needed) and use it to add/change any menu items – Nikos M. Apr 23 '15 at 03:52