IE事件传播在使用jQuery自动完成/滚动窗格时表现不如预期
IE事件传播在使用jQuery自动完成/滚动窗格时表现不如预期
我有一个文本输入框,使用ajax自动完成功能。结果在一个带有垂直滚动条的jScrollPane面板中显示。\n我在IE浏览器上遇到了一个问题,当用户点击jScrollPane下拉菜单的滚动条(滚动条的上下箭头会以锚点标签的形式生成)时,输入框的失焦事件会被触发。\n我理解使用return false应该可以阻止事件传播,这就是为什么锚点标签的mousedown和click事件都返回false的原因。在Firefox和Chrome中,这个方法很好用,但在IE中不起作用。\n虽然下面的代码没有显示,但我也尝试在我的事件中使用了以下代码,但没有成功:\ne.preventDefault ? e.preventDefault() : e.stop();\ne.returnValue = false;\ne.stopPropagation();\n我猜我的第一个问题是:\n我应该期望停止一种类型的事件传播能够停止其他类型的事件传播吗?\n也就是说,如果触发了mousedown事件并返回false,这会阻止blur或focusout事件的触发吗?\n我该如何解决这个问题,以确保IE的行为与Firefox和Chrome相同?\nvar rf = function() { return false; };\n$(\'\')\n.attr({\'href\':\'javascript:;\', \'className\':\'jScrollArrowUp\'})\n.css({\'width\':settings.scrollbarWidth+\'px\'})\n.html(\'Scroll up\')\n.bind(\'mousedown\', function()\n{\n currentArrowButton = $(this);\n currentArrowDirection = -1;\n onArrowMouseDown();\n return false;\n})\n.bind(\'click\', rf)\n$(\"#InputBox\").blur(function(e) {\nhasFocus = 0;\nif (!config.mouseDownOnSelect) {\n hideResultsNow();\n}
IE浏览器(版本≤8)的事件传播行为与其他浏览器不一致,导致jQuery的自动完成/滚动窗格功能无法按预期运行。问题的根本原因是在IE浏览器中,e.preventDefault()
在mousedown
事件中无法阻止选择和焦点的发生。然而,可以通过设置unselectable
属性来解决这个问题。
unselectable
属性可以阻止选择和焦点的发生,从而避免了通过mousedown
事件窃取焦点的问题。与其他常见的解决方法(如setTimeout(function() { thingIDidntWantFocusStolenFrom.focus(); })
)不同的是,unselectable
属性可以在event.target
上直接设置,从而在第一时间就防止了焦点的窃取。
有趣的是,unselectable
属性不会被继承,因此往往被人们忽视而选择使用能够冒泡的selectstart
事件来阻止选择(但e.preventDefault()
只能阻止选择,无法阻止焦点的发生),或者使用树遍历的方式在每个子元素上设置unselectable
属性。实际上,只需要在mousedown
事件的event.target
上设置unselectable
属性即可。
此外,jQuery也存在这个问题,相关的bug报告可以参考:http://bugs.jquery.com/ticket/10345。
解决IE浏览器中事件传播行为不符预期的问题的方法是通过设置unselectable
属性来阻止选择和焦点的发生。这种方法可以直接在mousedown
事件的event.target
上设置unselectable
属性,从而避免焦点的窃取。
问题原因:在IE浏览器中,事件传播不如预期,导致了这个问题的出现。
解决方法:在失去焦点事件和操作(隐藏列表)之间添加一个小的延迟。这样可以给点击事件触发的时间。然后在点击事件处理程序中,需要检查延迟的失去焦点事件是否已经处理,如果是,则取消该处理。
下面是一个示例代码:
var blurDelay; $('#input').blur(function() { blurDelay = setTimeout(function() { // hide the list }, 100); }); $('#input').click(function() { if (blurDelay) { clearTimeout(blurDelay); blurDelay = null; } // handle the click event });