简体   繁体   English

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

[英]Event listener conflict between jQuery and OpenLayers

The application is a web map (OpenLayers 2) on which one can open dialog boxes by clicking certain features.该应用程序是一个 Web 地图 (OpenLayers 2),可以通过单击某些要素在其上打开对话框。 Dialog boxes are handled with jQuery-ui.对话框使用 jQuery-ui 处理。

The Bug : On resizing a dialog, if the user drags the cursor too quickly, the cursor outpaces the size updating of the dialog.错误:在调整对话框大小时,如果用户拖动光标太快,光标会超过对话框的大小更新。 Normally this would require pretty jerky movements, but due to just how packed this application has gotten I guess it's a little bit slower.通常这将需要非常生涩的动作,但由于这个应用程序已经变得如此拥挤,我猜它有点慢。

But there's some event-handling conflict between jQuery and OpenLayers.但是 jQuery 和 OpenLayers 之间存在一些事件处理冲突。 When the cursor outpaces the div anywhere else it's fine, but if it's over the map, the resize stops (as well if you mouse-up, the stop drag state isn't registered so if you return to the dialog, it resizes with mouse movement).当光标超过其他任何地方的 div 时,它很好,但如果它在地图上,则调整大小停止(如果您将鼠标向上,停止拖动状态未注册,因此如果您返回对话框,它会使用鼠标调整大小运动)。

This means to expand the dialog, you have to move the cursor intentionally smoothly and not too fast otherwise it breaks, which is obviously too problematic for the user experience.这意味着要展开对话框,您必须有意识地平滑移动光标,不要太快,否则它会中断,这对于用户体验来说显然太成问题了。

Set up a very simple jsfiddle ( http://jsfiddle.net/a6uu5vav/ ) simply try to drag or resize the dialog quickly.设置一个非常简单的 jsfiddle ( http://jsfiddle.net/a6uu5vav/ ) 只需尝试快速拖动或调整对话框大小即可。 May vary by computer/browser, but working (that is, not working) for me in Chrome.可能因计算机/浏览器而异,但在 Chrome 中为我工作(即不工作)。

The Reason : jQuery-ui seems to attach the event listeners related to drag/resize to document so the functionality should work regardless of mouse outpacing div.原因:jQuery-ui 似乎将与拖动/调整大小相关的事件侦听器附加到document因此无论鼠标超过 div,该功能都应该工作。 However OpenLayers also puts a ton of event listeners on everything it creates.然而,OpenLayers 还在它创建的所有内容上放置了大量事件侦听器。 It uses event.stopPropagation() so that only the listeners on the target element are notified however.它使用event.stopPropagation()以便只通知目标元素上的侦听器。

So, when the cursor is over the OpenLayers map, it fires the target's event listeners, but the event does not propagate to the resize listeners.因此,当光标位于 OpenLayers 地图上时,它会触发目标的事件侦听器,但该事件不会传播到调整大小的侦听器。 While commenting out stopPropagation() technically solves it, because of how nested OpenLayers is and how it gives event listeners to everything, this makes it pretty slow just hovering over the map.虽然注释掉stopPropagation()技术上解决了这个问题,但由于 OpenLayers 的嵌套方式以及它如何为所有内容提供事件侦听器,这使得仅将鼠标悬停在地图上的速度非常慢。

I tried making the dialog modal to test that it is indeed conflicting event listeners.我尝试制作对话框模式来测试它确实是冲突的事件侦听器。 Modal fixes the resize issue, but we don't want it to be modal. Modal 修复了调整大小的问题,但我们不希望它是模态的。 Potentially though a "hacky" solution is to have an invisible modal and appears/disappears with the mousedown/up events that start/end the drag.虽然“hacky”解决方案可能是有一个不可见的模式,并且随着开始/结束拖动的 mousedown/up 事件出现/消失。

My Fix Attempt : I went into jQuery-ui (in the ui.mouse definition) to modify the event listeners to fire on capture (instead of bubble), which since they are added to the document will then be guaranteed to fire.我的修复尝试:我进入 jQuery-ui(在ui.mouse定义中)修改事件侦听器以在捕获时触发(而不是气泡),因为它们被添加到文档中,然后保证触发。 Since jQuery.bind() doesn't support that, I switched to old-school addEventListener() , for consistency I also changed any related unbind() to removeEventListener() .由于jQuery.bind()不支持,我切换到老式addEventListener() ,为了保持一致性,我还将任何相关的unbind()更改为removeEventListener()

Now here's the thing, if I only did that, but still set the onCapture param for addEventListener() to false, it works exactly how it did before -- working as usual with the resize bug.现在事情是这样的,如果我只这样做,但仍然将addEventListener()onCapture参数设置为 false,它的工作方式与以前完全一样 - 像往常一样处理调整大小错误。 If I change the onCapture param to true for the mousemove listener (doesn't matter if I set mouseup to true/false), the resize problem is fixed, technically, but now other stuff is being wonky.如果我将 mousemove 侦听器的onCapture参数更改为 true(如果我将 mouseup 设置为 true/false 无关紧要), onCapture技术上讲,调整大小问题已解决,但现在其他东西变得不稳定。

It drags/resizes fine, but on mouseup, the event listeners don't seem to be removed (thus moving mouse still drags or resizes the dialog), also div shifts for no reason.它可以很好地拖动/调整大小,但是在 mouseup 上,事件侦听器似乎没有被删除(因此移动鼠标仍然会拖动或调整对话框的大小),div 也无缘无故地移动。 _mouseUp() is being called and the event listeners removed at least in those lines, I know it's not a callback reference issue, I've tested for that. _mouseUp()正在被调用,并且至少在那些行中删除了事件侦听器,我知道这不是回调参考问题,我已经对此进行了测试。 I think they are getting removed properly but somehow readded.我认为它们正在被正确删除,但不知何故已被阅读。 Seems there's something in jQuery firing on mouse-up that has to go first and somehow rearranging order, even just that bit completely throws it off.似乎 jQuery 中的某些东西在鼠标向上触发时必须首先进行并以某种方式重新排列顺序,即使只是那一点完全将其抛弃。

This might be a losing game (ie total time sink relative to seriousness of bug) to try and "patch" jQuery-ui for this, but wondering if there may be some other ideas on how to try and solve this.这可能是一个失败的游戏(即相对于错误严重性的总时间下降)尝试为此“修补”jQuery-ui,但想知道是否可能有其他一些关于如何尝试解决这个问题的想法。

Ugh, I feel silly.呃,我觉得很傻。 My fix idea does work, but if you set the addEventListener() 's onCapture param to true, you have to set the onCapture param in removeEventListener() to true as well.我的修复想法确实有效,但是如果将addEventListener()onCapture参数设置为 true,则还必须将removeEventListener()onCapture参数设置为 true。

As for the full fix for the original problem, you have to edit the bind() and unbind() in jQuery-ui for mousemove and mouseup to addEventListener() and removeEventListener() with onCapture=true for both, for these definitions:至于原始问题的完整修复,您必须在 jQuery-ui 中为 mousemove 和 mouseup 编辑bind()unbind()addEventListener()removeEventListener()以及onCapture=true对于这些定义:

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

So far it appears to be working well for me.到目前为止,它似乎对我来说效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM