draggable 小部件(目前)还没有公开这样的事件。您可以修改它并维护您的自定义版本,或者更好的是,从中派生一个新小部件并在那里实现新事件。但是,还有第三种方法。
从this question,我们知道小部件在其snapElements 属性中存储了一个潜在“可对齐”元素的数组。反过来,这个数组中的每个元素都会暴露一个 snapping 属性,如果可拖动助手当前与该元素对齐,则该属性为 true,否则为 false(助手可以同时对齐多个元素)。
snapElements 数组会针对每个 drag 事件进行更新,因此它在 drag 处理程序中始终是最新的。从那里,我们只需要从与data() 关联的元素中获取draggable 小部件实例,并调用它的_trigger() 方法来引发我们自己的snapped 事件(实际上是dragsnapped 在后台)。顺便说一句,我们可以在$.extend() ui 对象中使用 jQuery 对象来包装被捕捉的元素:
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
if (element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement'...
}
});
但是,上面的代码仍然可以改进。就目前而言,只要可拖动帮助器保持与元素对齐,每个drag 事件(发生很多)都会触发snapped 事件。此外,捕捉结束时不会触发任何事件,这不是很实用,并且有损于此类事件成对发生的约定(snapped-in,snapped-out)。
幸运的是,snapElements 数组是持久的,所以我们可以使用它来存储状态。我们可以为每个数组元素添加一个snappingKnown 属性,以跟踪我们已经为该元素触发了snapped 事件。此外,我们可以使用它来检测自上次调用以来元素已被抢购并做出相应的反应。
请注意,下面的代码不是引入另一个 snapped-out 事件,而是选择在 ui 对象中传递一个额外的 snapping 属性(反映元素的当前状态)(当然,这只是偏好):
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
ui = $.extend({}, ui, {
snapElement: $(element.item),
snapping: element.snapping
});
if (element.snapping) {
if (!element.snappingKnown) {
element.snappingKnown = true;
draggable._trigger("snapped", event, ui);
}
} else if (element.snappingKnown) {
element.snappingKnown = false;
draggable._trigger("snapped", event, ui);
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement' and 'ui.snapping'...
var snapper = ui.snapElement.attr("id"),snapperPos = ui.snapElement.position(),
snappee = ui.helper.attr("id"), snappeePos = ui.helper.position(),
snapping = ui.snapping;
// ...
}
});
你可以测试这个解决方案here。
最后,另一个改进可能是使snapped 事件可取消,就像drag 事件一样。为了实现这一点,如果对_trigger() 的调用之一返回false,我们将不得不从drag 处理程序中返回false。不过,在实现此功能之前,您可能需要三思而后行,因为在一般情况下,取消对 snap-in 或 snap-out 的拖动操作看起来不是一个非常用户友好的功能。
更新: 从 jQuery UI 1.9 开始,the data() key becomes the widget's fully qualified name, with dots replaced by dashes。因此,上面用于获取小部件实例的代码变为:
var draggable = $(this).data("ui-draggable");
代替:
var draggable = $(this).data("draggable");
在 1.9 中仍支持使用非限定名称,但已弃用,并且将在 1.10 中放弃支持。