Client-Side menu separators with jquery
March 11th, 2007Have you ever pulled your hair about separators between menu entries on websites? Or just plain fell asleep? The task is trivial, but it is boring. Depending on what server side solution you are using, you end up with 4 to twenty lines of code.
CSS3 would save us from that boredom, but there is almost no CSS3 support in today’s browsers. That is, there’s no native CSS3 support. We can do the same and more with jquery, which does have CSS3 support.
What I have is:
(this is the HTML as output to the browser).
<div id="mainmenu"><ul><li><a href="Impressum.html">Impressum</a></li><li><a href="UeberMich.html">Über Mich</a></li><li><a href="Moebel.html">Möbel</a></li><li><a href="Innenausbau.html">Innenausbau</a></li><li><a href="SonstigeLeistungen.html">Sonstige Leistungen</a></li></ul></div>
Which gives me this:

But what I want is:

I could inject conditions into my server-side code to insert the bullets after all but the last menu entry (or before all but the first). But this has many drawbacks: usually, there’s more conditions involved in such menus like considering hidden pages if I am working in a CMS or similar, navigation states (which is the current page, etc), and so on. Also, it makes the HTML cluttered and charges the server-side code with view-dependant details. The server-side code in this case would be considered UI-driven anyway, so this is not inherently bad. But it’s still nicer not to.
Anyway, there’s a rather easy way with jquery (if you are new to jquery, just grab jquery.js from jquery.com). The relevant code:
<script src="jquery.js" type="text/javascript"></script><script language="javascript" type="text/javascript">$(document).ready(function(){$("#mainmenu ul li:not(:last-child)").after("<li class='bull'><b>•</b></li>");});</script>
Explanations:
The $(document).ready function is executed after the DOM is completely available.
$(”#mainmenu ul li:not(:last-child)”) selects DOM elements with a CSS3 selector, in this case all li elements that have a ul as their parent and #mainmenu as their grandparent and that are not the last child of their parent.
after(”<li class=’bull’><b>•</b></li>”) simply injects the HTML after each element in the collection just selected.
The CSS, for completeness’ sake:
#mainmenu{width: 800px;border: 1px solid #006633;border-left: none;border-right: none;background-color: #e5e5e5;}#mainmenu ul{display: block;margin: 0;margin-left: auto;margin-right: auto;height: 18px;}#mainmenu ul li{display: block;float: left;margin-left: 10px;margin-right: 10px;}#mainmenu ul li.bull{margin-top: 2px;}#mainmenu ul li a{display: block;text-decoration: none;color: #006633;background-color: #e5e5e5;font-size: 14px;}



