Thou shalt not link to thyself

The concept of pages not linking to themselves is not new – but if you’re using Dreamweaver-style templates there’s a bit of extra work to make that happen.

The Man in Blue posted an article about using CSS to make it appear that the page was not linking to itself, which received a mixed response. Inventive, but not really a complete solution. One of his readers then posted a javascript solution which loops through the page and removes any self-links automatically.

Clever thinking!

And that got me thinking… (Dangerous, I know)

So here goes:

<?php
// ---------------------------------------------------
//
// Format for links array: anchor text^URL^tooltip^flyout
// Example:
// $link[] = 'Home^/index.php^Home page^null';
//
// To start a flyout, use the fourth declaration on the parent link
// The URL on the parent link should also be null - for example:
// $link[] = 'Products »^null^Please choose a product^start';
// To finish the flyout, add a fourth declaration to the last flyout item - for example:
// $link[] = 'Widgets^/products/widgets.php^Our range of Widgets^end';
//
// IMPORTANT!
// For this to work properly, please use full paths from the site root for each link.
// Each link needs to start with a forward slash, indicating the site root
// So 'index.php' becomes '/index.php'
// And 'products/widgets.php' becomes '/products/widgets.php'
// ---------------------------------------------------
$link[] = 'Home^/index.php^Home Page^null';
$link[] = 'Menu 1 »^null^This will be a flyout^start';
$link[] = 'Flyout 1^#^Going somewhere^null';
$link[] = 'Flyout 2^#^Going somewhere^null';
$link[] = 'Flyout 3^#^Going somewhere^end';
$link[] = 'Menu 2^#^Link to menu 2^null';
$link[] = 'Menu 3^#^Link to menu 3^null';
$link[] = 'Contact Us^/contact.php^All contact information^null';
// ------------------ Don't edit below this
echo '<ul id="nav">';
// Loop through link array
foreach($link as $rawlink){
$linkparts = explode('^',$rawlink); // break $link into Link Name (0), URL (1), title (2), and flyout start ot end (3)
$self=$_SERVER['PHP_SELF'];
if ($self!=$linkparts[1] && $linkparts[1]!="null"){ // If PHP_SELF is different from URL in $link array, echo <a> element
echo '<li><a xhref="'.$linkparts[1].'" mce_href="'.$linkparts[1].'" title="'.$linkparts[2].'">'.$linkparts[0].'</a>';
}elseif($self==$linkparts[1]){ // If we're on the current page, add the class to indicate such
echo '<li class="currentpage" title="You are here">'.$linkparts[0];
}else{ // If the link is null, just echo the <li> - probably a flyout parent
echo '<li>'.$linkparts[0];
}
if($linkparts[3]=="start"){
echo '<ul>'; // Start a nested list for flyout
}else{
echo '</li>'; // otherwise close <li> element
}
if($linkparts[3]=="end"){
echo '</ul></li>'; // Close nested list and <li> element of parent
}
}
echo '</ul>';
// get last bit of PHP_SELF after last /
// if required - but better to just use paths from the root for everything and then they'll all match
/*
$thispage=explode("/",$_SERVER['PHP_SELF']);
foreach($thispage as $pagepart){
$self=$pagepart; // this will loop so only the last part should end up as $self
}
*/
?>

Couple the above with the following Javascript:

// To trigger CSS flyouts
startList = function() {
if (document.all&&document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes[i];
if (node.nodeName=="LI") {
node.onmouseover=function() {
this.className+=" over";
}
node.onmouseout=function() {
this.className=this.className.replace(" over", "");
}
}
}
}
}
window.onload=startList;

And a bit of CSS:

ul#nav {
font: 0.8em/1.6em Verdana, Arial, Helvetica, sans-serif;
float:left;
margin: 0;
padding: 0;
list-style: none;
width: 150px; /* Width of Menu Items */
border-bottom: 1px solid #ccc;
}
ul#nav li {
position: relative;
width: 150px;
color: #777;
background: #fff; /* IE6 Bug */
line-height: 2em;
border: 1px solid #ccc; /* IE6 Bug */
border-bottom: 0;
list-style: none;
}
li ul {
position: absolute;
left: 110px; /* Set 1px less than menu width */
top: 0;
display: none;
border-bottom: 1px solid #ccc;
list-style: none;
}
/* Styles for Menu Items */
ul#nav li a {
display: block;
text-decoration: none;
color: #777;
}
/* Holly Hack. IE Requirement */
* html ul#nav li { float: left; height: 1%; }
* html ul#nav li a { height: 1%; }
/* End */
#nav a:hover {
background-color:#999999;
}
li:hover ul, li.over ul {
display: block; width:100%;  /* The magic */
}
ul#nav li.currentpage {
background-color: #666;
color: #fff;
}

And we’ve got a CSS-based flyout menu that doesn’t link to itself – even when the page you’re on is one of the flyout pages!

Of course – the CSS flyout but was pinched from A List Apart.

Is that pretty neat, or what?

Advertisements