Main Page Content
Javascript Navigation Cleaner Not Meaner
It is common practise to enhance the user experience of an HTML document by
adding interactivity via Javascript. DHTML drop downs, tabs, layer navigations, image slide shows and so on and so forth are scattered all over the web.The times are changing
In the days of the wild wild web, when browsers sported fours in their navigator
string many a bloated script was developed to make the pages come alive. Developersfollowed the dark path of browser detection and implemented several different DOM solutions in parallel to supportevery dodgy brower that claimed to understand CSS and Javascript.Furthermore, they did the nasty by making the navigation dependent onJavascript, rather than enhanced through it.The times have changed, the browsers have matured and so should we. Accessibility
guidelines and SEO practises tell usnot to rely on Javascript, but neither do they forbid us to use it.The trick is to use it wisely.
This article is not showing off any special javascript navigation treat, all it does is
to show a small trick that helps us keep our markup as clean as possible.The HTML structure
Every Javascript enhanced navigation should provide a real link, to avoid dead links
should Javascript be turned off (if this is still news to you and you wonder why, read the superb Links & JavaScript Living Together in Harmony article). Normally, this is achieved thus:<a href="#target" onclick="myfunction(myparameters);return false">Link</a>
If you want to ensure that your links are also usable for people without a mouse, add
an onkeypress handler.<a href="#target" onclick="myfunction(myparameters);return false" onkeypress="myfunction(myparameters);return false">Link</a>
In most navigation scripts, myparameters is some sort of ID. The
script does something with that, and, should javascript be disabled, the browser simplytakes the user to the target the link points to.Easy and fully accessible — but bloated.
Leaner but not meaner
Let's be greedy. All we want to appear in our HTML is this:
<a href="#target">Link</a>
Impossible? No, actually it is rather easy. We need a helper, who adds the onclick and
onkeypress handlers and we need to find the right ID somehow.Adding the event handlers is rather easy. Let's take this navigation for example:
<ul id="mainnav"> <li><a href="#why">Why</a></li> <li><a href="#now">Now</a></li> <li><a href="#brown">Brown</a></li> <li><a href="#cow">Cow</a></li></ul>
To add the handlers to this one, we need to execute the following after the page
has loaded:1 function init()2 {3 if(document.getElementById && document.createTextNode)4 {5 var mn=document.getElementById('mainnav');6 var as=mn.getElementsByTagName('a');7 for (var i=0;i<as.length;i++)8 {9 as[i].onclick=function(){show(this);return false}10 as[i].onkeypress=function(){show(this);return false}11 } 12 }13 }
First, we check if the browser is capable of handling the W3C DOM(line 3).
Then we grab the element with the ID mainnav (line 5) and get all the elements with the name A that are inside this element — our links(line 6).Then we loop through these links (line 7 to 11) and add an onclick
(line 8) and an onkeypress (line 9) handler to them, assigning both these handlers a function that calls the function show() with the link object itself as the parameter and ending with a return false to prevent the browser from jumpingto the anchors after the script was executed. (line 8 and 9)After this loop is executed, all links in the navigation will call the function
show() with the link object as the parameter.Clickable, but what about the parameter?
The this we send onclick and onkeypress is a mighty tool. We can read
all the attributes of the link from it. In our case, we need the url value of the link.This means our function show() should do the followingfunction show(l){ var urldata=l.href;}
to retrieve the url data. Now, the only remaining issue, is that the url sent from
the browser is the complete one, whereas all we need is the last bit, the name of the ID we'd like to manipulate.Regular Expressions help us there:
function show(l){ var urldata=l.href.match(/#(\w.+)/)[1];}
The variable urldata now contains the id that we want to manipulate (we checked
the url data for the hash character and matched the following word).Ok, nice, but what then?
This is it, we turned the UL with the links into a javascript enhanced navigation,
that executes the function show() onclick and onkeypress. What we want to do with it, is ours to explore.One quick example? OK:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html dir="ltr" xml:lang="en" lang="en"><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Showme hideme</title> <script type="text/javascript"> function init() { if(document.getElementById && document.createTextNode) { var mn=document.getElementById('mainnav'); var as=mn.getElementsByTagName('a'); for (var i=0;i<as.length;i++) { as[i].onclick=function(){show(this);return false} as[i].onkeypress=function(){show(this);return false} } hidem(); } } function show(l) { hidem(); var id=l.href.match(/#(\w.+)/)[1]; document.getElementById(id).style.display='block'; } function hidem() { for (var i=0;i<document.getElementsByTagName('div').length;i++) { document.getElementsByTagName('div')[i].style.display='none'; } } window.onload=init; </script></head><body><ul id="mainnav"> <li><a href="#why">Why</a></li> <li><a href="#now">Now</a></li> <li><a href="#brown">Brown</a></li> <li><a href="#cow">Cow</a></li></ul><div id="why">...why data...</div><div id="now">...now data...</div><div id="brown">...brown data...</div><div id="cow">...cow data...</div></body></html>
We added a new function called hidem() Which hides all the DIV elements
in the document (granted, a crude approach, as you might want to use other DIVs).We call this function in the init() function to hide all texts our navigationpoints to (this could have been done in CSS, too, but that'll mean the page is not accessible, as it needs Javascript to show the text!). Then we call it againin our show() function to hide the last shown text (we could use a global variable for that and spare us the looping, knock yourselves out). Then we retrieve the ID via the regular expression, and show the DIV with this ID.