可访问的全宽下拉菜单与Jquery悬停,焦点和模糊



我有一个全宽下拉菜单,显示悬停或聚焦时的所有子菜单(使其可通过键盘访问)。这是一个你经常看到的菜单,但我还没有找到以模拟悬停行为的方式实现键盘可访问性的例子(换句话说:扩展菜单)。

这是菜单的HTML:

<div id="menu">
<div class="container">
<ul class="row">
<li class="first"><a href="link">Home</a></li>
<li><a href="link">Projects</a>
<ul class="inner">
<li class="first"><a href="link">Project 1</a></li>
<li class="last"><a href="link">Project 2</a></li>
</ul>
</li>
<li class="last"><a href="link">Contact</a>
<ul class="inner">
<li class="first"><a href="link">Visit us</a></li>
<li class="last"><a href="link">Email</a></li>
</ul>
</li>
</ul>
</div>
</div>

我一直在尝试各种方法来使用Jquery(仍在学习Jquery),它部分起作用。悬停功能可以正常工作,但仍有一些奇怪的事情发生。问题出在聚焦/模糊功能上。我为模糊功能添加了一个超时,否则每次我点击另一个链接时它都会触发。但有了这个暂停,模糊效果就不会再发生了。(菜单保持展开状态)。

与其他解决方案不同的是,我希望悬停、聚焦和模糊事件发生在#菜单div上,而不是单个链接上。我希望它能这样工作,因为它是一个全宽菜单,当你悬停在菜单上时,你可以同时看到所有子菜单。我发现在div中添加"tabindex=0"可以使用焦点和模糊。因此,我决定也通过Jquery添加此内容。

我的Jquery看起来像这样:

$(document).ready(function() {
/* dropdownmenu */
$("#menu")
.attr("tabindex",0)
// HOVER
.hover
( function () 
{
$(this).addClass('dropdown');
$(this).animate({ height: '20em'});
},
//hover out
function() 
{
$(this).animate(
{ height: '6em' }, 
{ complete: function() { $(this).removeClass('dropdown'); } }
)
}
)
// FOCUS
.focus 
( function () 
{
$(this).addClass('dropdown');
$(this).animate({height: '20em'});
}
)
// BLUR
.blur 
( function() 
{
setTimeout(function()
{
$(this).animate(
{height: '6em'}, 
{ complete: function() { $(this).removeClass('dropdown'); } }
)
},500);
}
);

我希望有人能帮我一点忙,让Jquery变得更好。太长了吗?为什么悬停功能表现奇怪,模糊功能根本不起作用?我应该换一种方式吗?

我还在jsfiddle中添加了这一点:http://jsfiddle.net/CpdM2/1/这里的高度不同,以更好地展示行为。

谢谢你的帮助!

编辑

我现在正在尝试一种不同的Jquery方法。我越来越接近了,唯一的问题仍然是模糊函数。

我的新jquery:

$.fn.accessibleDropDown = function ()
{
var el = $(this);
$(el).mouseenter(function() {
$("#menu").addClass('dropdown');
$("#menu").animate({ height: '7em'});
}).mouseleave(function() {        
$("#menu").animate(
{ height: '1em' }, 
{ complete: function() { $("#menu").removeClass('dropdown'); } }
);
});

/* Make dropdown menus keyboard accessible */
$("#menu").focus(function() {
//alert("focus");
$("#menu").addClass('dropdown');
$("#menu").animate({ height: '7em'});
}).blur(function() {
setTimeout(function() { 
if ($('#menu').find(':focus').length > 0) {
return false;
} else {
alert("menu does not have focus");
$("#menu").animate(
{ height: '1em' }, 
{ complete: function() { $("#menu").removeClass('dropdown'); } }
);
}
}, 50);
});
};

$("#menu").attr("tabindex",0).accessibleDropDown();
​

请在此处查看其实际操作:http://jsfiddle.net/kBNRv/

查看#菜单div是否已失去焦点的代码由于某种原因无法工作。我真的希望有人能给我指明正确的方向。提前谢谢。

一个更简单的方法是使用这个:

$("#menu").mouseenter(function() {
$(this).addClass('dropdown');
$(this).animate({height: '7em'});
$(this).focus(); /*OPTIONAL*/       
});
$("#menu").mouseleave(function() {
$(this).removeClass('dropdown'); 
$(this).animate({height: '1em' });
$(this).blur(); /*OPTIONAL*/  
});

focus和blur方法可以在"mouseenter"one_answers"mouseleave"上调用,因为此列表元素不是输入类型,所以它不会以相同的方式单击来接受焦点。不知道你为什么需要专注,除非你在某种程度上倾听这种行为。

此外,请注意,如果元素的z索引高于菜单,则这种方法(与原始方法非常相似)不会考虑。如果在菜单上方放置一个元素,那么如果鼠标滚动到该元素上,就会触发"mouseleave"方法。要查看示例,请在此处滚动"结果"框:http://jsfiddle.net/CpdM2/17/.因此,为了对抗你可能想要的行为:

a) 不要在菜单上添加任何元素。

b) 在触发"mouseleave"方法之前,检查鼠标的x、y位置,看看它们是否在菜单区域内/外。检查鼠标位置的示例如下:http://docs.jquery.com/Tutorials:Mouse_Position

当使用flash很酷时,这是flash back中的一种常见方法。。。。。叹息