My CMS‘s admin area has a lot of customisable features, so the navigation needs to be flexible.
Recently, the number of features grew to the point that I needed to implement a hierarchical menu structure, instead of the simple linear one that I had been using.
The script that I use (magicmenu – visible in action here) is an unobtrusive JavaScript which takes an list-tree of links, and converts it dynamically into drop-down menus.
The difficulty is in defining the tree, yet letting your validation scripts do this flexibly. Up until this point, I had drawn out the links immediately upon validating that the user had access to the link, but this is very difficult to do in a hierarchical manner
For example, consider this simple list:
Let’s say you have a user who does not have rights to edit user accounts in any way. In that case, a linear method would draw the Users tree root, but it would not have any leaf nodes:
Ideally, the Users root should not appear. By building the tree in an array beforehand, we can avoid that. Here is a bit of code that builds the above in an array format:
function addMenuItem(&$arr,$file,$nav){
if(ereg('>',$nav)){
$bits=explode(' > ',$nav);
if(!isset($arr[$bits[0]]))$arr[$bits[0]]=array();
addMenuItem($arr[$bits[0]],$file,str_replace($bits[0].' > ','',$nav));
}else{
$arr[$nav]=$file;
}
}
$arrayMenu=array();
addMenuItem($menuArray,'pages.php','Pages');
addMenuItem($menuArray,'user-accounts.php','Users > user accounts');
addMenuItem($menuArray,'user-groups.php','Users > user groups');
addMenuItem($menuArray,'user-admins.php','Users > admins');
addMenuItem($menuArray,'help.php','Help');
With the above, you do not need to pre-create the Users root – just tell the function you want to create the sub-node, and it will do it for you.
To draw that out, you need one more function, and a line of code:
function drawMenu($menuArray){
$c='';
foreach($menuArray as $name=>$item){
$c.='<li>';
if(is_array($item)){
$c.='<a href="#">'.htmlspecialchars($name).'</a>';
$c.='<ul>'.drawMenu($item).'</ul>';
}else{
$c.='<a href="'.$item.'">'.htmlspecialchars($name).'</a>';
}
$c.='</li>';
}
return $c;
}
echo '<ul class="magicmenutop">'.drawMenu($menuArray).'</ul>';
This code will build a compact tree-list with just the bits that are required.
Comments