JQuery finds out if parent lost focus

I was stuck in figuring out the logic to make an accessible keyboard with a drop down menu.

HTML is structured as such (additional class names are 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 they freeze, will display lists of submenus (drop-down menu). This works fine for me with some jQuery and the jQuery hoverIntent plugin.

The trick is that this only works with the mouse at the moment.

The next task is to make it work from the keyboard.

I can easily add a focus event to the top-level links, which then trigger the secondary menus:

 $('ul.primaryMenuItem a:first').focus([call showMenu function]) 

It works great.

To close the menu, when you open another menu, select one of the options to check if there is another open and, if so, close it.

This also works great.

However, if this fails, it is if you open the last menu and exit it. Since you have not entered another menu, it remains open.

The task is to figure out how / when you need to close the menu and the necessary logic (jQuery) to understand this. Ideally, I would close the menu when the focus is on the item on the OTHER page than any child menu items.

Logically, I am looking for this:

 $('li.primaryMenuItem').blur([close $(this).find('ul.popUpMenu')) 

However, you cannot do this because the LI does not actually have a focus, but rather a snap tag inside it.

Any suggestions?

UPDATE:

perhaps a better / simpler way to ask a question:

Is there a way to β€œlook” through jQuery to see if the focus has been moved beyond all the children of a particular object?

+6
jquery blur children
source share
6 answers

You can use event bubbles to check what is focused 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.

+6
source share

Use the new jquery 1.4 features: focusin and focusout instead of blur and focus . Here's how focusout differs:

A focus event is dispatched to an element when it, or any element inside of it, loses focus. This is from the blur event in that it supports the detection of focus loss from the parent elements (in other words, it supports event bubbles).

+2
source share

How to do the following:

 $('#link_A_id, #link_A_id > *').focusout(function () { if ($(document.activeElement).closest('#link_A_id').length == 0) //focus is out of link A and it children }); 
+2
source share

try it

 $('li.primaryMenuItem:last li a:last').blur([do whatever you need to do]) 

Logically, if the user selects the tab, he must have focused the last anchor.

You can even configure your own event handler as follows:

 $('li.primaryMenuItem:last').bind('myblur', function() ...); 

and name it in the last anchor blur event:

 ...blur(function() { $(this).parents('li.primaryMenuItem').trigger('myblur'); ... 
0
source share

It helped me ... http://plugins.jquery.com/project/focus

It will detect that you are still inside the parent automatically. It basically changes the focus of jQuery to work this way, and I feel how it should work.

 <div class="parent"> <input type="text" /> <input type="text" /> </div> $('#parent').focusout(function () { console.log('focusout of parent'); }); 

I do not understand why clicking a tab to move a text field between children should trigger focus on the parent object, because you are still within that parent. Something must happen that pulls you out of it for a moment, and I suspect it's a mistake ... is anyone with me about this? Well, in any case, the plugin above fixes it. Just include it before your code to β€œfix” it. I would like to explain to someone why this is not a mistake, if it is not.

Thanks Dom

0
source share

I had a similar problem ... I created jsfiddle to determine when the parent set of fields loses focus and then calls the function. This, of course, could be optimized, but this is the beginning.

http://jsfiddle.net/EKhLc/10/

 function saveFields() { $.each($('fieldset.save'),function(index, value) { // WHERE THE POST WOULD GO alert('saving fieldset with id '+ value.id); $(value).removeClass('save'); }); } $('.control-group').focusin(function(){ var thefield = $(this).parent('fieldset'); if (!thefield.hasClass('active')) { if($('fieldset.active').length > 0){ $('fieldset.active').removeClass('active').addClass('save'); saveFields(); } thefield.addClass('active'); } else { console.log('already active'); } }); 
0
source share

All Articles