【发布时间】:2011-06-08 21:57:23
【问题描述】:
似乎当使用两个相互接触的 jquery UI droppables 时,droppable 事件没有正确触发。如果在将一个可拖动元素从其中一个元素上拖动到其下方的 到下一个元素上时,则会为第一个可放置元素触发 out 事件,但不会为第二个元素触发 over 事件。如果此时您放下,则不会触发任何放置事件。
最好举个例子。试试this fiddle(在 IE7、8、9 和 Chrome11 中测试)。确保浏览器的控制台日志已打开。如果将可拖动对象拖到第一行上,然后慢慢地向第二行拖动,您很快就会在日志中看到第一行的 out 事件被触发,但第二行的 over 事件未被触发。如果您在这种情况下放下,则不会触发 drop 事件。
导致问题的行之间似乎只是一条 1 像素的线。再拖一个像素会触发 over 事件,并且 drop 事件会正常工作。
这对我来说似乎是一个错误,但我找不到其他任何人使用表行作为可放置对象并报告了该问题。我对表格进行了样式设置,因此您可以看到行确实是齐平的,中间没有空格。
这对我来说是个大问题,因为在我们的应用程序中,表格行是嵌套的贪婪 droppables。因此,如果用户在发生这种情况时掉落,则该掉落实际上是由外部 droppable 拾取的。
此外,我们在可拖动帮助器中以图标和消息的形式向用户提供反馈,该图标和消息会根据您结束的拖放操作而变化。当您在行之间拖动时,它会闪烁片刻,因为它认为您实际上并没有超过任何可放置对象。
我的问题:
- 是否有针对此问题的修复或解决方法?
- 我应该将此报告为错误吗?
更新
@davin,
我们最终确实更改了 $.ui.ddmanager 中的拖动功能以修复事件顺序。我们的问题是我们嵌套了贪婪的droppables。当您从其中一个嵌套的 droppables 从下到上移动到另一个时,over 事件实际上会为父级触发,从而导致坏事发生。
所以我们添加了逻辑来检查是否从一个嵌套贪婪移动到另一个,如果是,则不触发父事件。
要求您快速检查一下并确保我们的逻辑合理,会不会太过分了?有两个逻辑变化。如果我们从贪婪的孩子变成了贪婪的孩子:
- 不要取消设置 parentInstance.greedyChild
- 不要触发 parentInstance._over 事件。
这是代码。请参阅我们添加的处理 isParentStateChanged 闭包变量的行:
drag: function(draggable, event) {
//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
var isParentStateChanged = false;
//Run through all droppables and check their positions based on specific tolerance options
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(this.options.disabled || this.greedyChild || !this.visible) return;
var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
if(!c) return;
var parentInstance;
if (this.options.greedy && !isParentStateChanged) {
var parent = this.element.parents(':data(droppable):eq(0)');
if (parent.length) {
parentInstance = $.data(parent[0], 'droppable');
parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
}
}
// we just moved into a greedy child
if (parentInstance && c == 'isover') {
isParentStateChanged = true;
parentInstance['isover'] = 0;
parentInstance['isout'] = 1;
parentInstance._out.call(parentInstance, event);
}
this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
this[c == "isover" ? "_over" : "_out"].call(this, event);
// we just moved out of a greedy child
if (parentInstance && c == 'isout') {
if (!isParentStateChanged) {
parentInstance['isout'] = 0;
parentInstance['isover'] = 1;
parentInstance._over.call(parentInstance, event);
}
}
});
}
【问题讨论】:
-
出于好奇,我修改了您的 jsfiddle here 以使用 div 并得到相同的结果,因此您使用表格似乎并不重要。也许这种行为是有意的。
-
@squidbe,感谢您提供的好信息。考虑到它不仅发生在表格行中,编辑的标题和初始描述更通用。
-
看看我的插件.. myabe它会帮助你:[stackoverflow.com/a/16720944/1308461][1] [1]:stackoverflow.com/a/16720944/1308461
标签: javascript jquery jquery-ui draggable droppable