我正在教自己如何编写jQuery插件。我使用jquery-hover-dropdown-box作为基础示例。它不只是复制/粘贴,我做了一些改变,试图更好地理解它。例如,我没有合并hover
事件,我添加了一个过滤器,目前没有使用任何默认值来命名一些。 Clicking on a div's scroll bar fires the blur event in I.E是我发现的唯一一个看起来像是一个很好的解决方案的帖子,我尝试实现类似的但却没有成功。
完成示例:jsFiddle
问题:
我点击input
并打开下拉菜单,但是当我第一次点击滚动条时,下拉菜单会关闭。当我第二次打开下拉列表并单击滚动条时,它不会关闭(正如我所料)。据我所知,我的问题出在blur
input
上。据我所知,当我点击滚动条时,input
已失去焦点。我尝试在Scrollbars not working on dropdown in IE8上实现与此帖子类似的内容,但无法使其正常运行。
重现步骤:
input
打开下拉列表input
并打开下拉列表 问题:
我第一次单击滚动条时导致下拉菜单关闭的错误是什么?
我尝试过的事情:
当我将ul
附加到div
(目前在jsFiddle的第68行附近注释掉)时,我添加了以下代码。我想如果我停止通过mousedown
上的ul
触发操作,它将解决我的问题。虽然它确实解决了Chrome中的问题,但它仍然存在于IE8中。
更新:我将以下代码从$list.mousedown...
更改为$container.mousedown...
,因为$list
是ul
而$container
是包含的div
它。我的想法是扩大了面积。结果虽然如此。
...
$container.append($list);
$list.mousedown(function(e) {
e.preventDefault();
});
...
由于这似乎很接近,我尝试在blur
事件中采用类似的方法。我使用此代码时会发生上述问题。在Chrome中,单击滚动条不会触发blur
事件,但在IE8中,它会触发...
// where $dom is the 'div' containing the 'ul'
$dom.unbind('mousedown.auto_dropdown_box_ul')
.bind('mousedown.auto_dropdown_box_ul', function(e) {
console.log('bind mousedown');
e.preventDefault();
});
setTimeout(function() {
console.log('hiding');
$dom.addClass('auto_dropdown_hide').hide();
}, 100);
...
事件。第一次打开下拉列表并单击滚动条时,它会记录“隐藏”。再次打开下拉列表并单击滚动条,它会记录“bind mousedown”。单击下拉列表外的任何位置,它将关闭(应该如此)并记录“隐藏”(应该如此)。对我来说似乎是倒退,但显然我并没有正确地理解它。 (下面的代码在jsFiddle的134行左右)
代码编辑:使用Goran.it suggestion更新,以防止发生多重绑定。
blur
我也尝试删除input
事件。我知道如果你从input
标签出来,这会阻止下拉关闭,但认为值得一试。在Chrome中,它的工作方式完全符合我的预期,在blur
外部点击关闭下拉菜单,单击滚动条不会关闭它,并且标签不会关闭它。在IE8中,单击下拉列表外部不会关闭它,也不会在您标签时关闭,但单击滚动条确实有效。这是我在删除// below where the 'blur' event was
$(document).click(function(e) {
if (e.target == dropdownArray[0].input[0] || e.target == dropdownArray[0].dom[0]) {
console.log('matches');
e.preventDefault();
} else {
console.log('does not match');
dropdownArray[0].dom.addClass('auto_dropdown_box_hide').hide();
}
});
后添加的代码(它不包含在jsFiddle中)。
{{1}}
同样,这是我的第一次尝试,我还在学习。我确信有很多事情我可能做错了,我可以改进等等。在我解决这些问题之前,我只想了解我在这里做错了什么以及我需要做些什么来纠正它。阅读plugin concepts之后,我知道我有很多东西需要学习。
答案 0 :(得分:1)
我第一眼看到的问题很少,你应该改变:
$dom.bind('mousedown.auto_dropdown_box_ul'
为:
$dom.unbind('mousedown.auto_dropdown_box_ul').bind('mousedown.auto_dropdown_box_ul'
为了防止多个事件绑定到dom节点,您还可以使用.one事件处理jQuery。 在同一事件处理中,您还应该:
console.log('bind mousedown');
e.preventDefault();
return false;
确保事件没有解雇。
希望这会有所帮助(我现在很长时间没有使用IE8)
答案 1 :(得分:0)
我相信我终于想出了这个。经过多次尝试后,我想我会把格式更改为一个似乎,至少在我看来更直接的格式。
以下是完整的jsFiddle
底层修复是正确设置/调整哪个元素具有焦点以及何时。由于mousedown
在click
之前执行,我在下拉列表中坚持使用该事件。在mousedown
事件中,我设置isVisible = true
并将焦点设置回input
(尽管后者并非完全必要)。在blur
事件中,我正在检查isVisible
。如果这是真的,那意味着滚动条中发生了单击,因此不要关闭下拉列表。如果是假,请关闭下拉列表。在整个事件中,我跟踪isVisible
所以我知道blur
执行时的状态。再次,我更改了格式,因此两个小提琴看起来不同。我相信我可以回去实现类似于原始小提琴的东西并使其正常工作,但我更喜欢这种方式。以下是相关更改的摘录:
{
// some code above
// where $list is the 'ul'
$list.bind('mousedown', methods.onDropdownMousedown);
// where $obj is the 'input'
$obj.bind('blur', methods.doOnBlur);
},
onDropdownMousedown: function(e) {
$input.focus(); // not really needed, just in case
isVisible = true;
},
doOnBlur: function(e) {
if (isVisible) {
$input.focus();
isVisible = false;
} else {
// where $container is the 'div' containing the list
$container.addClass('auto_dropdown_box_hide').hide();
isVisible = false;
}
isVisible = false;
}