jQuery 和 OpenLayers 之间的事件侦听器冲突

Event listener conflict between jQuery and OpenLayers

该应用程序是一个 web 地图 (OpenLayers 2),可以通过单击某些功能在其上打开对话框。对话框用 jQuery-ui.

处理

错误:在调整对话框大小时,如果用户拖动光标太快ui,光标会超过对话框的大小更新。通常这会需要ui非常不稳定的动作,但由于这个应用程序的打包程度,我猜它有点慢。

但是 jQuery 和 OpenLayers 之间存在一些事件处理冲突。当光标在其他任何地方超过 div 时都很好,但如果它在地图上方,则调整大小会停止(同样,如果您向上移动鼠标,则停止拖动状态未注册,因此如果您 return到对话框,它会随着鼠标移动而调整大小)。

这意味着要展开对话框,你必须有意地平滑地移动光标,不要太快否则它会中断,这显然对用户体验来说是有问题的。

设置一个非常简单的 jsfiddle (http://jsfiddle.net/a6uu5vav/) 只需尝试拖动或调整对话框 quickly。可能因 computer/browser 而异,但在 Chrome.

对我有效(即无效)

原因: jQuery-ui 似乎将与 drag/resize 相关的事件侦听器附加到 document 所以无论鼠标速度如何 div,功能都应该有效。然而,OpenLayers 还在其创建的所有内容上放置了大量的事件监听器。它使用 event.stopPropagation() 以便只通知目标元素上的侦听器。

因此,当光标位于 OpenLayers 地图上时,它会触发目标的事件侦听器,但事件不会传播到调整大小的侦听器。虽然注释掉 stopPropagation() 从技术上解决了它,但由于 OpenLayers 的嵌套方式以及它如何为所有内容提供事件侦听器,这使得将鼠标悬停在地图上变得非常慢。

我尝试将对话框设为模态以测试它确实是冲突的事件侦听器。模态修复了调整大小的问题,但我们不希望它是模态的。 "hacky" 解决方案可能是使用不可见的模态和 appears/disappears 以及 start/end 拖动的 mousedown/up 事件。

我的修复尝试:我进入 jQuery-ui(在 ui.mouse 定义中)修改事件侦听器以触发在捕获时(而不是气泡),因为它们被添加到文档中,所以将保证触发。由于 jQuery.bind() 不支持,我切换到老派 addEventListener(),为了保持一致性,我还将任何相关的 unbind() 更改为 removeEventListener()

现在事情是这样的,如果我只这样做了,但仍然将 addEventListener()onCapture 参数设置为 false,它的工作方式与之前完全一样——像往常一样调整大小漏洞。如果我将 mousemove 侦听器的 onCapture 参数更改为 true(如果我将 mouseup 设置为 true/false 无关紧要),调整大小的问题在技术上是固定的,但现在其他东西是不稳定的。

它 drags/resizes 很好,但是在 mouseup 上,事件侦听器似乎没有被删除(因此移动鼠标仍然会拖动或调整对话框的大小),div 也无缘无故地移动。 _mouseUp() 正在被调用并且至少在这些行中删除了事件侦听器,我知道这不是回调引用问题,我已经对此进行了测试。我认为它们被正确删除但不知何故被重新添加。 jQuery 似乎有一些东西在按下鼠标时触发,必须首先进行并以某种方式重新排列顺序,即使只是那一点也完全把它扔掉了。

这可能是一个失败的游戏(即相对于 bug 严重性的总时间下降)尝试 "patch" jQuery-ui,但想知道是否可能关于如何尝试解决这个问题的一些其他想法。

呃,我觉得很傻。我的修复想法确实有效,但如果将 addEventListener()onCapture 参数设置为 true,则还必须将 removeEventListener() 中的 onCapture 参数设置为 true。

至于对原始问题的完整修复,您必须将 jQuery-ui 中的 bind()unbind() 编辑为 addEventListener()removeEventListener()onCapture=true 对于这些定义:

$.ui.mouse._mouseDestroy()$.ui.mouse._mouseDown()$.ui.mouse._mouseUp()

到目前为止,它似乎对我来说效果很好。