PDA

View Full Version : PHP Flexible contextual navigation



digitalmatt
September 25th, 2009, 05:00 PM
Hello all,

I've been struggling with this for a week and cannot seem to figure out how to do it (or find the answer I've been looking for).

So I'm trying to build a flexible contextual navigation menu that can accept at least 2 tiers (nav and subnav).

Essentially, I want to build a semantic html navigation list:



<ul id="nav">
<li>Item One</li>
<li>Item Two</li>
<li>
Item Three
<ul>
<li>Item Three Sub 1</li>
<li>Item Three Sub 2</li>
</ul>
</li>
<li>Item Four</li>
</li>
Item Five
<ul>
<li>Item Five Sub 1</li>
<li>Item Five Sub 2</li>
</ul>
</li>
</ul>

Note: I've got this menu setup so that if you are not in a directory, when you rollover an item, if it has a submenu, it will display. But I also want to be able to display the submenu if you're on a page that's a child of that particular directory.

Here's how I'm building it in PHP:



$tierOne['Item One'] = "/itemone.php";
$tierOne['Item Two'] = "/itemtwo.php";
$tierOne['Item Three'] = "/itemthree/index.php";
$tierOne['Item Four'] = "/itemfour.php";
$tierOne['Item Five'] = "/itemfive/index.php";

$tierTwo['Item Three']['Item Three Sub 1'] = "/itemthree/sub1.php";
$tierTwo['Item Three']['Item Three Sub 2'] = "/itemthree/sub2.php";

$tierTwo['Item Five']['Item Three Sub 1'] = "/itemfive/sub1.php";
$tierTwo['Item Five']['Item Three Sub 2'] = "/itemfive/sub2.php";

$htmlMenu = '<ul>'; // start the tier one nav

foreach($tierOne as $key => $value) {
if($_SERVER['PHP_SELF'] == $value) { //if the current page url is equal to the url of the array index value, then give the list item a class of 'activePage' (for styling, etc)
$activeClass = ' class="activePage"';
}
else {
$activeClass = "";
}
$htmlMenu .= "<li><a href=\"$value\">$key2</a>"
if(isset($key[$tierTwo])) { // if a tier one item has sub array
$htmlMenu .= "<ul>"; // start the tier two nav (here's where my problem is. how can i figure out which active directory i'm in so i can give the subnav ul a class of 'active' so i can make that subnav display whenever i'm in a directory that has pages??
foreach($tierTwo as $key2 => $value2) {
$htmlMenu .= "<li><a href=\"$value2\">$key2</a></li>"
}
$htmlMenu .= "</ul></li>" // end the tier two nav and close off the tier one item
}
else {
$htmlMenu .= "</li>"; // otherwise close the tier one item
}
}

$htmlMenu .= "</ul>"; // end the tier one nav




Might not be the most elegant solution. But I'm getting closer. So the bottom line is. I want the navigation to be contextual -- that is to know which page and directory its in so it can give ONLY second tier <ul> a class (so that i can keep it displayed).

Any ideas? Thanks!

digitalmatt
September 28th, 2009, 12:23 PM
*gentle bump*

Anyone? :(

simplistik
September 28th, 2009, 11:16 PM
try:


<?php
$nav = array();

// Tier 1
$nav['Item One'][0] = '/itemone.php';
$nav['Item Two'][0] = '/itemtwo.php';
$nav['Item Three'][0] = '/itemthree/index.php';
$nav['Item Four'][0] = '/itemfour.php';
$nav['Item Five'][0] = '/itemfive/index.php';

// Tier 2
$nav['Item Three'][1] = array('Item Three Sub 1' => '/itemthree/sub1.php', 'Item Three Sub 2' => '/itemthree/sub2.php');
$nav['Item Five'][1] = array('Item Three Sub 1' => '/itemfive/sub1.php', 'Item Three Sub 2' => '/itemfive/sub2.php');
?>


then your formatting might look something like:


<ul>
<?php while (list($key, $value) = each($nav)) : ?>
<li>
<a href="<?php echo $value[0]; ?>"><?php echo $key ?></a>
<?php if ( is_array($value[1]) ) : // check for Tier 2 ?>
<ul>
<?php while (list($skey, $svalue) = each($value[1])) : // loop through Tier 2 ?>
<li><a href="<?php echo $svalue; ?>"><?php echo $skey; ?></a></li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
</li>
<?php endwhile; ?>
</ul>

ajcates
September 29th, 2009, 12:28 AM
Here is my go at it. I use recursive functions so I could nest sub sections down as deep as I need.


<h1>Uber nestable menu!</h1>
<?php
$tierOne = array(
'Item One' => '/itemone.php',
'Item Two' => '/itemtwo.php',
'Item Three' => '/itemfour.php',
'Item Four' => '/itemfour.php',
'Item Five' => '/itemfive/index.php'
);

$tierTwo = array(
'Item Three' => array(
'Item Three Sub 1' => '/itemthree/sub1.php',
'Item Three Sub 2' => '/itemthree/sub2.php'
),
'Item Five' => array(
'Item Three Sub 1' => '/itemfive/sub1.php',
'Item Three Sub 2' => '/itemfive/sub2.php',
'ubernest' => array(
'crazy?' => array(
'i know' => '/someUrl'
)
)
)
);

function item($url, $name) {
if($_SERVER['PHP_SELF'] == $url) { //if the current page url is equal to the url of the array index value, then give the list item a class of 'activePage' (for styling, etc)
$class = ' class="activePage"';
}
$return = '<li' . @$class . '>';
if(is_string($url)) {
$return .= '<a href="' . $url . '">' . $name . '</a>';
} elseif(is_array($url)) {
if(is_string($name)) {
$return .= $name;
}
$return .= makeMenu($url);
}
return $return . '</li>';
}

function makeMenu($menu) {
$return = '<ul>';
foreach($menu as $item => $url) {
$return .= item($url, $item);
}
return $return . '</ul>';
}

echo makeMenu(array('tierOne' => $tierOne, 'tierTwo' => $tierTwo));
show_source(__FILE__);
?>


Also I uploaded an example. http://ninjawebspace.com/ajcates/dump/flexableMenu.php

digitalmatt
September 29th, 2009, 10:58 AM
This is awesome guys. These are definitely more elegant solutions to generating the nav. But the issue I'm really having is figuring out if I'm in a second tier nav's subdirectory (ie. /secondtier/index.php or /secondtier/page1.php, etc). And if I am, then DISPLAY the second tier menu instead of making it pop out on rollover.

Does that make sense?


Here is my go at it. I use recursive functions so I could nest sub sections down as deep as I need.


<h1>Uber nestable menu!</h1>
<?php
$tierOne = array(
'Item One' => '/itemone.php',
'Item Two' => '/itemtwo.php',
'Item Three' => '/itemfour.php',
'Item Four' => '/itemfour.php',
'Item Five' => '/itemfive/index.php'
);

$tierTwo = array(
'Item Three' => array(
'Item Three Sub 1' => '/itemthree/sub1.php',
'Item Three Sub 2' => '/itemthree/sub2.php'
),
'Item Five' => array(
'Item Three Sub 1' => '/itemfive/sub1.php',
'Item Three Sub 2' => '/itemfive/sub2.php',
'ubernest' => array(
'crazy?' => array(
'i know' => '/someUrl'
)
)
)
);

function item($url, $name) {
if($_SERVER['PHP_SELF'] == $url) { //if the current page url is equal to the url of the array index value, then give the list item a class of 'activePage' (for styling, etc)
$class = ' class="activePage"';
}
$return = '<li' . @$class . '>';
if(is_string($url)) {
$return .= '<a href="' . $url . '">' . $name . '</a>';
} elseif(is_array($url)) {
if(is_string($name)) {
$return .= $name;
}
$return .= makeMenu($url);
}
return $return . '</li>';
}

function makeMenu($menu) {
$return = '<ul>';
foreach($menu as $item => $url) {
$return .= item($url, $item);
}
return $return . '</ul>';
}

echo makeMenu(array('tierOne' => $tierOne, 'tierTwo' => $tierTwo));
show_source(__FILE__);
?>
Also I uploaded an example. http://ninjawebspace.com/ajcates/dump/flexableMenu.php