I'm stuck on figuring out the logic to make a drop down menu keyboard accessible.
The HTML is structured as such (extra class names used for clarity):
<ul>
<li class="primaryMenuItem">
<a href="">Link 1</a>
<ul class="popUpMenu">
<li><a href="">Sub Link 1</a></li>
<li><a href="">Sub Link 2</a></li>
</ul>
</li>
<li class="primaryMenuItem">
<a href="">Link 2</a>
<ul class="popUpMenu">
<li><a href="">Sub Link 1</a></li>
<li><a href="">Sub Link 2</a></li>
</ul>
</li>
</ul>
Link 1 and Link 2, when hovered, will show the sub-menu lists (pull down menu). I have this working just fine with some jQuery and the jQuery hoverIntent plugin.
The catch is that this only works with the mouse at the moment.
Next challenge is to get this to work via the keyboard.
I can easily add a focus event to the top level links that then trigger the secondary menus:
$('ul.primaryMenuItem a:first').focus([call showMenu function])
That works fine.
To close the menu, one option is to, when opening another menu, check to see if there is another open already and, if so, close it.
That also works fine.
Where that fails, however, is if you have the last menu open, and tab out of it. Since you haven't tabbed into another menu, this one stays open.
The challenge is to figure out how/when to close the menu and the logic needed (jQuery) to figure it out. Ideally, I'd close the menu when the focus is on an element on the page OTHER than any of the menu's child elements.
Logically, I'm looking for this:
$('li.primaryMenuItem').blur([close $(this).find('ul.popUpMenu'))
However, you can't do that, since the LI doesn't actually have focus, but rather the anchor tag within it.
Any suggestions?
UPDATE:
perhaps a better/simpler way to ask the question:
Via jQuery, is there a way to 'watch' to see if focus has moved outside of all children of a particular object?
You can use event bubbling to check what has focus on the focusin event. I had success with the following code:
$("li:has(ul.popUpMenu)").focusin(function(e) {
$(this).children().fadeIn('slow');
});
$('body').focusin(function(e) {
if (!$(e.target).parent().is('ul.popUpMenu li')) {
$('ul.popUpMenu').fadeOut('slow');
}
});
You could(should) probably make it more optimized, but it works.