jQuery搞清楚父母是否已经失去了“焦点”

我一直坚持要弄清楚下拉菜单键盘可以访问的逻辑。

HTML的结构如此(为了清晰起见,使用额外的类名称):

 

链接1和链接2,当hover时,将显示子菜单列表(下拉菜单)。 我有一些jQuery和jQuery hoverIntent插件可以正常工作。

问题是这只适用于鼠标。

接下来的挑战是通过键盘使其工作。

我可以轻松地将焦点事件添加到顶级链接,然后触发辅助菜单:

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

这很好。

要关闭菜单,一个选项是,当打开另一个菜单时,检查是否已经打开另一个菜单,如果是,则关闭它。

这也很好。

但是,如果你打开了最后一个菜单,那么它就会失败。 由于您没有标记到另一个菜单,这个菜单保持打开状态。

挑战在于弄清楚如何/何时关闭菜单以及需要的逻辑(jQuery)来弄清楚它。 理想情况下,当焦点位于页面上的元素上时,我会关闭菜单,而不是任何菜单的子元素。

逻辑上,我正在寻找这个:

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

但是,您不能这样做,因为LI实际上没有焦点,而是其中的锚标记。

有什么建议?

更新:

也许是一个更好/更简单的问题提问方式:

通过jQuery,有没有办法“观察”以查看焦点是否移动到特定对象的所有子节点之外?

您可以使用事件冒泡来检查焦点事件的焦点。 我使用以下代码取得了成功:

 $("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'); } }); 

你可以(应该)使它更优化,但它的工作原理。

使用新的jquery 1.4函数: focusinfocusout而不是blurfocus 。 以下是focusout不同之处:

当焦点事件或其内部的任何元素失去焦点时,会将焦点事件发送到元素。 这与模糊事件的区别在于它支持从父元素检测焦点丢失(换句话说,它支持事件冒泡)。

如果你这样做怎么样:

 $('#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's children }); 

试试这个

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

从逻辑上讲,如果您的用户标记出来,他一定是在关注最后一个锚。

您甚至可以像这样设置自己的事件处理程序:

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

并在最后一个锚点模糊事件中调用它:

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

这对我有帮助…… http://plugins.jquery.com/project/focus

它会自动检测您是否仍在父级内。 它基本上改变了jQuery焦点以这种方式工作,我觉得它应该如何工作。

 
$('#parent').focusout(function () { console.log('focusout of parent'); });

我不明白为什么按Tab键在子元素之间移动文本字段应该触发父节点上的焦点,因为你仍然在父节点内。 必须发生一些让你离开它的东西,我怀疑这是一个错误……有人和我在一起吗? 好吧无论如何上面的插件修复它。 只需在代码之前包含它即可“修复”此问题。 如果不是,我会爱一个人解释为什么这不是一个错误。

谢谢,Dom

我有一个类似的问题…我创建了一个jsfiddle来确定父字段集何时失去焦点然后调用一个函数。 它当然可以优化,但它是一个开始。

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'); } });