Auto-Nav Template with Unique CSS Classes

Permalink 4 users found helpful
I've seen a lot of people looking for something like this, where the auto nav applies a unique CSS class to each LI item in the nav so you can assign a unique background image to each individual nav item.

Here is a working model to use if anyone is interested. Just place this in your blocks/autonav/templates directory. I named mine custom_nav.php

All I did was call the $_c->getCollectionID() method to add it to each navigation item and I moved the nav-selected class into an ID. Otherwise, this is exactly the same as the existing auto-nav.

Enjoy!

<?php 
   defined('C5_EXECUTE') or die("Access Denied.");
   $aBlocks = $controller->generateNav();
   $c = Page::getCurrentPage();
   echo("<ul class=\"nav-header\">");
   $nh = Loader::helper('navigation');
   $isFirst = true;
   foreach($aBlocks as $ni) {
      $_c = $ni->getCollectionObject();
      if (!$_c->getCollectionAttributeValue('exclude_nav')) {
         $target = $ni->getTarget();
         if ($target != '') {
            $target = 'target="' . $target . '"';
         }
         if ($ni->isActive($c) || strpos($c->getCollectionPath(), $_c->getCollectionPath()) === 0) {

leinteractive
 
TimDix replied on at Permalink Reply
TimDix
I've done something similar on a number of sites, however I will say that I'm confused why you chose to break compatibility by moving nav-selected to an ID?

Honestly, the way I'd recommend doing this, and all future code is to modify this:


if ($c->getCollectionID() == $_c->getCollectionID()) { 
            echo('<li class="nav-selected nav-path-selected"><a class="nav-selected nav-path-selected" ' . $target . ' href="' . $pageLink . '">' . $ni->getName() . '</a>');
         } elseif ( in_array($_c->getCollectionID(),$selectedPathCIDs) ) { 
            echo('<li class="nav-path-selected"><a class="nav-path-selected" href="' . $pageLink . '" ' . $target . '>' . $ni->getName() . '</a>');
         } else {
            echo('<li><a href="' . $pageLink . '" ' . $target . ' >' . $ni->getName() . '</a>');
         }


And turn it into this:
$navclass = array();
$navclass[] = 'nav-item-'.$_c->getCollectionID();
if ($c->getCollectionID() == $_c->getCollectionID()) {
   $navclass[] = 'nav-path-selected';
   $navclass[] = 'nav-selected';
} else if ( in_array($_c->getCollectionID(),$selectedPathCIDs) ) { 
   $navclass[] = 'nav-path-selected';
} 
echo('<li class="'.explode(' ', $navclass).'"><a class="'.explode(' ', $navclass).'" href="' . $pageLink . '" ' . $target . ' >' . $ni->getName() . '</a>');


//Disclaimer: I wrote the above code while posting, so it might have errors.
TimDix replied on at Permalink Reply
TimDix
Come to think of it, this should be in core.
jordanlev replied on at Permalink Reply
jordanlev
Raverix, are you on the github? I agree that this should be in core -- the autonav template is the most-often-customized, and cleaning it up would be a great help especially for non-coders who need to get in there.
(Great suggestion by the way, nice and clean and easily extendable)
TimDix replied on at Permalink Reply
TimDix
I am now, been meaning to check out git for a while, guess this was as good a time as any. I made the changes, and in fact some more, but I'm having trouble getting the current head of C5 to install on my server... once I figure that out I'll try to submit the patch.

This will now add the following classes:

nav-selected - no change
nav-path-selected - no change
nav-first - Applied to the first li in the list, marginal uses
nav-item-{cid}

It'll now also check for a new attribute if you have it defined, 'nav_item_class', so if you wanted to give your your class a name better than nav-item-94, you can do nav-item-contact-popup or whatever.

<?
   defined('C5_EXECUTE') or die("Access Denied.");
   $aBlocks = $controller->generateNav();
   $c = Page::getCurrentPage();
   $containsPages = false;
   $firstNavLi = true;
   $nh = Loader::helper('navigation');
   //this will create an array of parent cIDs 
   $inspectC=$c;
   $selectedPathCIDs=array( $inspectC->getCollectionID() );
   $parentCIDnotZero=true;   
   while($parentCIDnotZero){
      $cParentID=$inspectC->cParentID;
      if(!intval($cParentID)){
         $parentCIDnotZero=false;
TimDix replied on at Permalink Reply
TimDix
Come to think of it... this whole nested levels and comparing this level to that level in the view seems kind of clunky... shouldn't the data be delivered in a form which indicates the hierachy? Perhaps something such as:
$pages = array(
   1 => array('obj'=> PageObject,
                'children' => array (5=> array('obj'=> PageObject)),
   7 => array('obj'=> PageObject),
   13 => array ('obj'=> PageObject,
                'children' => array (17=> array('obj'=> PageObject))
);


Perhaps for backwards compatibility, we could create:
$aBlocks = $controller->generateNavHierarchy();
leinteractive replied on at Permalink Reply
leinteractive
Yea, I didn't think about the ID thing until just now when I realized that I have a parent and a child nave item both with the ID of "nav-selected" which isn't very good for validation!

I like your approach better...seems to make the most sense.
leinteractive replied on at Permalink Reply
leinteractive
This is the error I got when testing the code you provided. Not really sure how to fix it:

Warning: in_array() [function.in-array]: Wrong datatype for second argument in /blocks/autonav/templates/custom_menu_compatible.php on line 48
TimDix replied on at Permalink Reply
TimDix
That means that $selectedPathCIDS is not an array, which it should defined in the stock view.php
leinteractive replied on at Permalink Reply
leinteractive
So...how do I fix it?
jordanlev replied on at Permalink Reply
jordanlev
It means you must have accidentally changed something else in the template, or perhaps you completely overwrote the view.php file with just Raverix's code (instead of only replacing that one chunk of code he pointed out)?
If that's not the case, or if you can't figure it out, please post your template file here (ZIP it up if the forum software prevents you from uploading php files).
TimDix replied on at Permalink Reply
TimDix
Reference the above code for the complete solution.
leinteractive replied on at Permalink Reply
leinteractive
I guess I'm not really sure what I'm looking at. Here is my full custom_nav.php file located in my blocks/autonav/templates folder.

This code throws the error I mentioned above.

Reading through these posts, I'd be interested to see an autonav block that 1.) Outputs nested lists and 2.) assigns a unique CSS class to each nav LI item.

Anyways...here's what I have that doesn't work:

<?php 
   defined('C5_EXECUTE') or die("Access Denied.");
   $aBlocks = $controller->generateNav();
   $c = Page::getCurrentPage();
   echo("<ul class=\"nav-header\">");
   $nh = Loader::helper('navigation');
   $isFirst = true;
   foreach($aBlocks as $ni) {
      $_c = $ni->getCollectionObject();
      if (!$_c->getCollectionAttributeValue('exclude_nav')) {
         $target = $ni->getTarget();
         if ($target != '') {
            $target = 'target="' . $target . '"';
         }
         if ($ni->isActive($c) || strpos($c->getCollectionPath(), $_c->getCollectionPath()) === 0) {
TimDix replied on at Permalink Best Answer Reply
TimDix
Your code only accounts for a <ul> one level deep, try replacing your entire file with this:

<?
   defined('C5_EXECUTE') or die("Access Denied.");
   $aBlocks = $controller->generateNav();
   $c = Page::getCurrentPage();
   $containsPages = false;
   $firstNavLi = true;
   $nh = Loader::helper('navigation');
   //this will create an array of parent cIDs 
   $inspectC=$c;
   $selectedPathCIDs=array( $inspectC->getCollectionID() );
   $parentCIDnotZero=true;   
   while($parentCIDnotZero){
      $cParentID=$inspectC->cParentID;
      if(!intval($cParentID)){
         $parentCIDnotZero=false;
leinteractive replied on at Permalink Reply
leinteractive
Thanks, Raverix.

This is the error I get when i do that:

Parse error: syntax error, unexpected T_ARRAY in /blocks/autonav/templates/custom_menu_compatible.php on line 69
TimDix replied on at Permalink Reply
TimDix
Somehow an '=' went missing, I've updated the above. Oh, and if it works, let me know where I can see the output... I still haven't even run the code :)
leinteractive replied on at Permalink Reply
leinteractive
Raverix, that worked PERFECT!

THIS is how the autonav block should work right out of the box.

Here is the working output. I just transitioned this site to C5 from Joomla.

http://ribapalooza.com
tallacman replied on at Permalink Reply
tallacman
Looks very handy from a builders point of view. How about a package in the marketplace?
mikefatty replied on at Permalink Reply
mikefatty
yeah we need a free addon menu on the marketplace ;-)
TimDix replied on at Permalink Reply
TimDix
I'm trying to do you one better by getting this into core.
uswebdesigner replied on at Permalink Reply
uswebdesigner
I created a file called custom_nav.php and put this code into it, nothing else. I added that file to MYSITE/blocks/autonav/templates folder. I then went into edit mode and changed the template in use for my main nav. I did not get the same result as leinteractive got when I go to his site - with custom classes for the nav li tags.

Am I missing something?

Thanks,

Result is here: http://designsbytierney.com/levin-c5/facilities-and-services/...
jordanlev replied on at Permalink Reply
jordanlev
Hello autonav-interested people. I have created a drastically-simplified autonav template that is *much* easier to work with than the built-in one:

https://raw.github.com/jordanlev/c5_clean_block_templates/master/aut...
(Save that file to YOURSITE/blocks/autonav/view.php).

It contains a ton of features from all over the forums and is very easy to customize as well. It even includes this "add a class for every item" feature, although it's disabled by default so you'll have to uncomment it (scroll down to the "DESIGNERS: CUSTOMIZE CSS CLASSES HERE..." section for that).

And I've also put up some other cleaned-up templates for the Form and Page List block, in case you're interested in those as well:
https://github.com/jordanlev/c5_clean_block_templates/...

-Jordan
vincedelaking replied on at Permalink Reply
vincedelaking
Briljant! just what I need!
uswebdesigner replied on at Permalink Reply
uswebdesigner
jordanlev - I added the view.php script above and saw no change. I was expecting to see custom class names added to each nav li tag that I could then style. I did not see that.

Was that supposed to be part of the script you mentioned above, the first of the two added in your post above?

thanks,
aghouseh replied on at Permalink Reply
aghouseh
Take a look at the actual code. There's an extremely well-documented section commented out where it prepares the nav classes array. You can enable many pre-set checks or put your own in there as well.
uswebdesigner replied on at Permalink Reply
uswebdesigner
Thanks. I did look through it but must have missed that. I thought that part was automatic and the commented out parts were the extra options stated at the top.

Will look again.
jordanlev replied on at Permalink Reply
jordanlev
Here's a blog post I wrote that explains how to customize this template in more detail:
http://c5blog.jordanlev.com/blog/2011/12/customizing-the-autonav-te...