[h]Rationale[/h]
Initially I posted this in another thread about a very similar topic, however in order to keep the discussion focused on the code block posted in that thread I moved my version over to here.
Reasons for creating this variation are,
One: UL is ambigous, LI is the real focus.
Class names on the UL element seem pointless to me, i consider all <ul> to be of submenu types anyway. what we were really interested in to begin with was if a UL element was nested or not... this can be easily verified with :
Second reason for this is that since I stack relevant classname descriptors on the common items (LI) we can target individual UL via the LI.className :
Two : Positional classNames
I wanted to be able to apply attributes to the first, last, odd and even items of a submenu :
Three : Obsessive Compulsive Disorder
separation of the individual aspects of the menu creation function into three main parts provides easy modification to those aspects. In addition to using string format replacement method it becomes clear what the output of a particular step will be, allowing developers to quickly modify the output of a "step" without modifying logic.
Four : Tree Walking
lastly, if and when getSimple starts supporting a page tree deeper than 2 levels, this setup will continue to walk down the tree.
[h]Setup[/h]
You need :
$themedir$/functions.php
$themedir$/includes/navigation.php
$themedir$/css/navigation.css
This is an example of my css I use. Attributes would vary, however I would still be using the same selectors.
$themedir$/js/navigation.js
$themeDir$/template.php
Inside the <head> ;
Inside the <body> (somewhere);
Initially I posted this in another thread about a very similar topic, however in order to keep the discussion focused on the code block posted in that thread I moved my version over to here.
Reasons for creating this variation are,
One: UL is ambigous, LI is the real focus.
Class names on the UL element seem pointless to me, i consider all <ul> to be of submenu types anyway. what we were really interested in to begin with was if a UL element was nested or not... this can be easily verified with :
Code:
.navigation li > ul { something something something ... complete }
Code:
.navigation .current > ul { something something something ... complete }
.navigation .odd > ul { something something something ... complete }
.navigation .menu-item-45 > ul { something something something ... complete }
Two : Positional classNames
I wanted to be able to apply attributes to the first, last, odd and even items of a submenu :
Code:
.navigation .odd > a{ border-right:.1em solid #ccc; }
.navigation .even > a{ border-left:.1em solid #fff; }
.navigation .first > a{ border-left:none; }
.navigation .last > a{ border-right:none; }
Three : Obsessive Compulsive Disorder
separation of the individual aspects of the menu creation function into three main parts provides easy modification to those aspects. In addition to using string format replacement method it becomes clear what the output of a particular step will be, allowing developers to quickly modify the output of a "step" without modifying logic.
Four : Tree Walking
lastly, if and when getSimple starts supporting a page tree deeper than 2 levels, this setup will continue to walk down the tree.
[h]Setup[/h]
You need :
$themedir$/functions.php
Code:
<?php include("./includes/navigation.php"); ?>
$themedir$/includes/navigation.php
Code:
<?php
function template_zebra_row($array, $index,$total){
array_push($array, ( $index%2 > 0)? "odd":"even");
if( $index == 1 ){ array_push($array,"first"); }
if( $index == $total ){ array_push($array,"last"); }
return $array;
}
function template_menu_item_is_active($array, $test){
if($test) array_push($array, 'current');
return $array;
}
function template_tiered_menu(&$menu=false, &$id=false, &menuOnly=true){
$template = "<ul>%s</ul>";
$output = "";
$id = "";//($id==false)? "" : $id;
$menuOnly = "Y";//($menuOnly==false)? "N" :$menuOnly;
$data = simplexml_load_string(menu_data("",true));
if(!$menu){
$menu = $data->xpath('//*[menuStatus="'.$menuOnly.'"][parent="'.$id.'"]');
}
if(!empty($menu)){
$menu_count = count($menu);
$step = 1;
foreach ($menu as $link) {
$class = array();
if ($link->slug=='') $link->slug = "index";
$submenu = $data->xpath('//*[menuStatus="Y"][parent="'.$link->slug.'/"]');
$class = template_menu_item_is_active(template_zebra_row($class, $step, $menu_count), "$link->slug" == return_page_slug());
array_push($class,"menu-item-id-$step");
$output .= template_tiered_menu_item($link,join($class, " "),$submenu);
$step++;
}
}
return sprintf($template, $output);
}
function template_tiered_menu_item($link,$class,$submenu){
$template = '<li class="%s"><div class="inner">%s</div></li>';
if(strpos($class,"current")<=0){
if(!$THEME_NONACTIVE_SUBMENUS){ $submenu = array(); }
}
return sprintf($template, $class, template_tiered_menu_link($link,$submenu) );
}
function template_tiered_menu_link($link,$submenu){
$template = '<a href="%s" title="%s"><span>%s</span></a>%s';
$title = ($link->menu!="")?$link->menu:$link->title;
return sprintf($template, $link->url, $title, $title,(count($submenu)>0)?template_tiered_menu($submenu):"");
}
?>
$themedir$/css/navigation.css
This is an example of my css I use. Attributes would vary, however I would still be using the same selectors.
Code:
.site-header .navigation{
margin:0;
padding:0 1px;
height:6em;
}
.site-header .navigation > div.inner{
margin:0 ;
padding:.5em 0;
display:inline;
float:left;
}
.navigation ul{
margin:0;
padding:0 .5em;
list-style:none;
display:inline;
float:left;
}
.navigation li{
display:inline;
float:left;
list-style:none;
margin:0;
padding:0;
background-repeat:repeat-x;
background-color:#ccc;
background-position:0em -2em;
background-image:url("../images/small-transparent-vertical-gradient-reversed.png");
}
.navigation li > div.inner{
margin:0;
padding:0;
display:inline;
float:left;
}
.navigation ul ul{
display:none;
}
.navigation a{
display:inline;
float:left;
padding:0.2em 0;
margin:0em 0em;
}
.navigation li a span{
display:inline;
float:left;
padding:0.3em 2em;
margin:.2em 0em;
color:#333;
}
.navigation a:hover{
background-position:0em -6em;
}
.navigation .odd > div.inner{
}
.navigation .first > .inner > a span,
.navigation .first > .inner > a,
.navigation .first{
-moz-border-radius:none;
-webkit-border-radius:none;
-moz-border-radius-bottomleft:.3em;
-moz-border-radius-topleft:.3em;
-webkit-border-top-left-radius:.3em;
-webkit-border-bottom-left-radius:.3em;
}
.navigation .last a span,
.navigation .last a,
.navigation .last{
-moz-border-radius:none;
-webkit-border-radius:none;
-moz-border-radius-bottomright:.3em;
-moz-border-radius-topright:.3em;
-webkit-border-top-right-radius:.3em;
-webkit-border-bottom-right-radius:.3em;
}
.navigation .last > div.inner{
}
.navigation .current > a{
}
.navigation .current > a:hover{
}
.navigation li ul li{
padding:.2em 0em;
}
.navigation li ul a{
display:inline;
float:left;
padding:0;
margin:0;
}
.navigation li ul a:hover{
}
.navigation li ul a{
background-repeat:repeat-x;
background-color:#ddd;
background-position:0em -1em;
background-image:url("../images/small-transparent-vertical-gradient-reversed.png");
}
$themedir$/js/navigation.js
Code:
(function($) {
$.fn.handleSubMenu = function(settings) {
var config = {
childItems : 0
}
if (settings) $.extend(config, settings);
/*
* _isActive
* Is the element marked as the active menu item ?
* or does it have any descendant items marked as the current menu item?
*/
function isActive(elm,action){
var name = elm.find("a:eq(0)").text()
var activeParents = elm.parents(".current, .active")
var activeChildren = elm.find(".current, .active")
var thisIsActive = elm.hasClass("active") || elm.hasClass("current")
var parentIsMaster = elm.parents().eq(1).filter(".inner").length>0
if( activeChildren.length>0 ){
output = true;
}else if( activeParents.length>0 ){
output = true;
}else if(thisIsActive){
output = true;
}else{
output = false;
}
if(parentIsMaster){}
return output
}
var open = function(elm){
/*
if this item contains a submenu, show it.
*/
$(elm).find("ul").css("display","inline")
}
var close = function(elm){
if(!isActive($(elm),"close") ){
/*
if the current elem (an LI) has LI descendants
and none of those are marked with the ".current" className,
hide the UL containing them
*/
$(elm).find("ul").css("display","none")
}
}
/*
* Hover Logic
* Deal with it.
*/
$(this).hover(function(){ open($(this))},function(){ close($(this))})
/*
* Activated Menu Items
* Keep them open.
*/
if( isActive($(this),"initialisation") ){
$(this).parent().css("display","inline")
}else{
if(!$(this).parents().eq(1).filter(".inner").length > 0){
// not sure about this yet.
// $(this).css("display","none");
}
}
}
})(jQuery);
$(function(){
$(".primary-navigation li").each(function(){
$(this).handleSubMenu()
})
})
$themeDir$/template.php
Inside the <head> ;
Code:
<script type="text/javascript" src="<?php print get_theme_url();?>/js/jquery/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="<?php print get_theme_url();?>/js/navigation.js"></script>
Inside the <body> (somewhere);
Code:
<div class="row navigation">
<div class="inner">
<?php print template_tiered_menu(); ?>
</div>
</div>
Fear is mindkiller, the little death that obliterates.