jQuery UI-перетаскиваемое событие " snap
Я ищу способ связывания snap
событие.
когда я перетаскиваю элемент по моей поверхности и разрешить элемент огрызнулась в объявленную позицию привязки я хочу вызвать событие.
что-то вроде этого:
$(".drag").draggable({
snap: ".grid",
snaped: function( event, ui ) {}
});
бонусный балл: со ссылкой на .grid
элемент, где разрешить элемент огрызнулась.
2 ответов
на draggable
виджет не выставляет такое событие из коробки (пока). Вы можете изменить его и сохранить свою пользовательскую версию или, лучше, получить из него новый виджет и реализовать новое событие. Однако есть и третий способ.
С этот вопрос, мы знаем, что виджет хранит массив потенциально "привязываемых" элементов в своем snapElements
собственность. В свою очередь, каждый элемент в этом массиве предоставляет snapping
имущества true
если перетаскивать helper в настоящее время привязан к этому элементу и false
в противном случае (помощник может привязать к нескольким элементам одновременно).
на snapElements
массив обновляется для каждого drag
событие, поэтому оно всегда актуально в drag
обработчики. Оттуда нам нужно только получить draggable
экземпляр виджета из связанного элемента с data (), и назвать его _trigger()
метод, чтобы поднять наш собственный snapped
событие (на самом деле dragsnapped
под капотом). Попутно мы можем $.extend () the 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'...
}
});
код выше, однако, все еще может быть улучшен. В его нынешнем виде a snapped
событие будет запускаться для каждого drag
событие (что происходит большое) до тех пор, пока перетаскиваемый помощник остается привязанным к элементу. Кроме того, никакое событие не запускается при замыкании концов, что не очень практично и отвлекает от конвенции для таких событий парами (snapped-in
, snapped-out
).
к счастью,snapElements
массив-это постоянные, поэтому мы можем использовать его для хранения. Мы можем добавить snappingKnown
свойство для каждого элемента массива, чтобы отслеживать, что мы уже вызвали snapped
событие для этого элемента. Более того, мы можем использовать его, чтобы обнаружить, что элемент был вырван с момента последнего вызова и реагировать соответствующим образом.
обратите внимание, что вместо того, чтобы вводить еще один snapped-out
событие, код ниже выбирает передать дополнительные snapping
свойство (отражающее текущее состояние элемента) в ui
объект (который, конечно, является только вопросом предпочтения):
$(".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;
// ...
}
});
вы можете проверить это решение здесь.
в заключение, еще одно улучшение может заключаться в том, чтобы сделать snapped
событие отменено, как drag
событие. Чтобы достичь этого, нам придется вернуться false
наших drag
обработчик, если один из вызовов _trigger()
возвращает false
. Вы можете подумать дважды, прежде чем реализовать это, хотя, как отмена операции перетаскивания на оснастке или оснастки не выглядит как очень удобная функция в общем случае.
обновление: от jQuery UI 1.9 и далее,the data()
ключ становится полным именем виджета, с точками, замененными тире. Соответственно, код, используемый выше для получения экземпляра виджета, становится:
var draggable = $(this).data("ui-draggable");
вместо из:
var draggable = $(this).data("draggable");
использование неквалифицированного имени по-прежнему поддерживается в 1.9, но устарело, и поддержка будет отброшена в 1.10.
в jquery-ui 1.10.0 вышеуказанный код не работает. Функция перетаскивания вместо этого:
drag: function(event, ui) {
var draggable = $(this).data("ui-draggable")
$.each(draggable.snapElements, function(index, element) {
if(element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
}