I spent a little time on it last night and, IMO, inelegantly, heres the beginning of a solution...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="generator" content= "HTML Tidy, see www.w3.org" /> <title>n2menu - example</title> <link href="n2menu.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="jquery-1.js"> </script> <script type="text/javascript" src="n2menu.js"> </script> <script type="text/javascript"> function removeExpanded(q){ var li = q//.get(0); $(li.container).children(".subMenu").each(function(){ var ul = this; $ (ul).removeClass("subMenu").remove().appendTo(ul.opener); $(ul.opener).removeClass("expanded"); }); } $(document).ready(function(){ $("#m1").n2menu(); $("#m2").n2menu(); $('#m1, #m1 *').mousemove( function(e){ var li=$('#m2 .expanded'); li.each( function() { removeExpanded(this) }) }) $('#m2, #m2 *').mousemove( function(e){ var li=$('#m1 .expanded'); li.each( function() { removeExpanded(this) }) }) $('*:not(.n2menu)').mousemove( function(e) { var spot = $('#m2').offset().top + $('#m2').height() if ( e.pageY > spot+100 ) { var li=$('#m1 .expanded, #m2 .expanded'); li.each( function() { removeExpanded(this) }) } }); }); </script> </head> <body> <div class="n2menu"> <ul class="" id="m1"> <li><a href="http://menu.n2cms.com/">Home</a></li> <li><a href= "http://menu.n2cms.com/upload/ example.htm">example.htm</a></li> <li> <a href= "http://menu.n2cms.com/Features.aspx">Features</a> <ul> <li> <a href= "http://menu.n2cms.com/Features/Many %20levels.aspx"> Many levels</a> <ul> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20one.aspx"> Page one</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20two.aspx"> Page two</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20three.aspx"> Page three</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20four.aspx"> Page four</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20five.aspx"> Page five</a></li> </ul> </li> <li><a href= "http://menu.n2cms.com/Features/Indipendant %20menues.aspx"> Indipendant menues</a></li> <li><a href= "http://menu.n2cms.com/Features/Easy%20to %20style.aspx"> Easy to style</a></li> <li><a href= "http://menu.n2cms.com/Features/Untangles %20nested%20lists.aspx"> Untangles nested lists</a></li> <li><a href= "http://menu.n2cms.com/Features/Resonably %20accessible.aspx"> Resonably accessible</a></li> <li> <span>A menu item mustn't be a link.</span> <ul> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20one.aspx"> Page one</a></li> </ul> </li> </ul> </li> <li><a href= "http://menu.n2cms.com/Download.aspx">Download</a></ li> <li><a href= "http://menu.n2cms.com/FAQ.aspx">FAQ</a></li> </ul> </div> <div class="n2menu"> <ul id="m2"> <li><a href="http://menu.n2cms.com/">Home</a></li> <li><a href= "http://menu.n2cms.com/upload/ example.htm">example.htm</a></li> <li> <a href= "http://menu.n2cms.com/Features.aspx">Features</a> <ul> <li> <a href= "http://menu.n2cms.com/Features/Many %20levels.aspx"> Many levels</a> <ul> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20one.aspx"> Page one</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20two.aspx"> Page two</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20three.aspx"> Page three</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20four.aspx"> Page four</a></li> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20five.aspx"> Page five</a></li> </ul> </li> <li><a href= "http://menu.n2cms.com/Features/Indipendant %20menues.aspx"> Indipendant menues</a></li> <li><a href= "http://menu.n2cms.com/Features/Easy%20to %20style.aspx"> Easy to style</a></li> <li><a href= "http://menu.n2cms.com/Features/Untangles %20nested%20lists.aspx"> Untangles nested lists</a></li> <li><a href= "http://menu.n2cms.com/Features/Resonably %20accessible.aspx"> Resonably accessible</a></li> <li> <span>A menu item mustn't be a link.</span> <ul> <li><a href= "http://menu.n2cms.com/Features/Many %20levels/Page%20one.aspx"> Page one</a></li> </ul> </li> </ul> </li> <li><a href= "http://menu.n2cms.com/Download.aspx">Download</a></ li> <li><a href= "http://menu.n2cms.com/FAQ.aspx">FAQ</a></li> </ul> </div> <div id="position"> <span id='first'>1</span> <span id='last'>2</span> </div> </body> </html> ------------------ js ------------------------------- /* * n2menu 0.10 - Copyright (c) 2007 Cristian Libardo * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Usage example: * * <script type="text/javascript" src="/Js/jquery-1.2.pack.js"></ script> * <script type="text/javascript" src="/Js/n2menu.js"></script> * <script type="text/javascript"> * $(document).ready(function(){ * $("#myMenuRootId").n2menu(); * }); * </script> * * <!-- the unordered list defines the menu structure --> * * <ul id='myMenuRootId'> * <li> * <a href="#">just a link</> * <ul> * <!-- this is a submenu, when expanded it's moved below the topmost ul --> * <li>...</li> * </ul> * </li> * <li><a href="#">just another link</></li> * </ul> * * <!-- expanded submenues are moved here --> * */ (function($){ $.fn.n2menu = function(options) { for(var i=0; i<this.length; ++i){ var menuRoot = this.get(i); // defaults menuRoot.n2m = { delay: 0, container: null, current: null, expandTo: ".current" }; if(options) { $.extend(menuRoot.n2m, options); } if(!menuRoot.n2m.container) menuRoot.n2m.container = $(menuRoot).wrap("<div class='n2menu'></div>").parent().get(0); var initBranchRecursive = function(el, trail){ el.container = menuRoot.n2m.container; var q = $(el); if(q.is("ul")){ trail.push(el); el.level = trail.length; el.excludes = trail.slice(); q.addClass("level" + el.level); initExpansion(q); } q.children().each( function(){ if(q.is("li")) q.hover(DENonMouseOver, DENonMouseOut); initBranchRecursive(this, trail); }); if(q.is("ul")) trail.pop(); if(q.is(menuRoot.n2m.expandTo)) menuRoot.n2m.current = q.get(0); } var initExpansion = function(ulQ){ var liQ = ulQ.parent(); if(!liQ.is(".n2menu")) { var li = liQ.get(0); var ul = ulQ.get(0); li.opens = ul; ul.opener = li; liQ.addClass("expandable").hover(onMouseOver, onMouseOut); } } var onMouseOutCLEAR = function() { alert('out') this.addClass('current') } var DENonMouseOver = function(){ var li = this; $(li).children().each( function(){ $(this).css('color','blue') }) var q = $(li); q.css({ backgroundColor:"#EEE"}).css('color','blue') } var DENonMouseOut = function(){ var li = this; $(li).children().each( function(){ $(this).css('color','') }) var q = $(li); q.css({ backgroundColor:"" }) } var onMouseOver = function(){ var li = this; this.style.backgroundColor='green' var q = $(li); q.addClass("hover"); if(menuRoot.n2m.delay > 0) { setTimeout(function(){ if(q.is(".hover")){ removePreviouslyExpanded(q); expand(q); } }, menuRoot.n2m.delay); } else { removePreviouslyExpanded(q); expand(q); } } var onMouseOut = function(){ $(this).removeClass("hover"); } var expand = function(q){ var li = q.get(0); if(li.opens){ $ (li.opens).remove().appendTo(li.container).addClass("subMenu"); q.addClass("expanded"); } } var removePreviouslyExpanded = function(q){ var li = q.get(0); $ (li.container).children(".subMenu").not(li.opens.excludes).each(function() { var ul = this; $ (ul).removeClass("subMenu").remove().appendTo(ul.opener); $(ul.opener).removeClass("expanded"); }); } var expandToCurrentRecursive = function(q){ if(q.is(".n2menu")) return; else if (q.is("ul")) { expandToCurrentRecursive(q.parent()); } else if (q.is("li")) { expandToCurrentRecursive(q.parent()); expand(q); q.addClass("trail"); } else return; } var init = function(menuContainer){ $(menuContainer).each(function(){ var excludes = new Array(); initBranchRecursive(menuContainer, excludes); if(menuRoot.n2m.expandTo != null) expandToCurrentRecursive($ (menuRoot.n2m.expandTo)); }); $(menuContainer).addClass("initialized"); } init(menuRoot.n2m.container); } }; })(jQuery);