JQuery Sortable - отмена и возврат не работает как ожидалось
У меня возникают проблемы с параметром revert
при использовании в сочетании с методом cancel
в сортировке jQuery. Метод отмены, описанный в jQuery Sortable documentation, гласит:
Отменяет изменение текущей сортировки и возвращает ее обратно до начала текущего сортировки. Полезно для остановки и получения функции обратного вызова.
Это отлично работает как в обратных вызовах stop
, так и receive
, однако, если я добавлю продолжительность revert
в сортируемый список подключений, он начинает действовать смешно (см. jsFiddle здесь).
В идеале, при отмене, revert
может просто не произойти, или, альтернативно, в более идеальном мире, он изящно вернется к нему в оригинальном месте. Любые идеи, как я могу заставить revert
и cancel
играть хорошо?
Ожидаемые
- Перетащите из списка слева в правый список.
- Удалить элемент
- Элемент анимируется в оригинальном месте - или - немедленно переходит в исходное местоположение
Фактические
- Перетащите из списка слева в правый список.
- Удалить элемент
- Элемент анимируется в новом месте, предполагая, что сортировка успешна.
- Пункт немедленно переходит в исходное местоположение, поскольку сортировка отменена
Разъяснение
Свойство revert
перемещает элемент в место, где элемент упадет в случае успеха, а затем сразу же вернется в исходное местоположение из-за revert
, встречающегося перед методом cancel
. Есть ли способ изменить жизненный цикл, поэтому, если выполняется cancel
метод, revert
нет, и вместо этого элемент немедленно возвращается к исходному местоположению?
Ответы
Ответ 1
Спустя много часов для поиска решения я решил, что единственный способ добиться того, что я пытался сделать, - изменить способ, с помощью которого сортируемый плагин jQuery зарегистрировал время возврата. Цель состояла в том, чтобы позволить свойству revert
принимать не только boolean
или integer
, но и принимать function
. Это было достигнуто путем легкого подключения к prototype
на ui.sortable
и выглядело примерно так.
jQuery Сортируемое исправление
$.ui.sortable.prototype._mouseStop = function(event, noPropagation)
{
if (!event) return;
// if we are using droppables, inform the manager about the drop
if ($.ui.ddmanager && !this.options.dropBehaviour)
$.ui.ddmanager.drop(this, event);
if (this.options.revert)
{
var self = this;
var cur = self.placeholder.offset();
// the dur[ation] will not determine how long the revert animation is
var dur = $.isFunction(this.options.revert) ? this.options.revert.apply(this.element[0], [event, self._uiHash(this)]) : this.options.revert;
self.reverting = true;
$(this.helper).animate({
left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
}, !isNaN(dur) ? dur : 500, function ()
{
self._clear(event);
});
} else
{
this._clear(event, noPropagation);
}
return false;
}
Реализация
$('ul').sortable({
revert: function(ev, ui)
{
// do something here?
return 10;
}
});
Ответ 2
я создал демо для вас здесь:
код jsfiddle
он, кажется, производит ожидаемый результат.
я изменил метод обратного вызова приема:
$(ui.sender).sortable('cancel');
:
$(ui.sender).sortable( "option", "revert", false );
надеюсь, это то, что вы ожидали.
Ответ 3
Я закончил создание нового события с именем beforeRevert, которое должно возвращать true или false. Если false, то вызывается функция отмены, и элемент возвращается в исходное положение. Я не кодировал это с помощью вспомогательной опции, поэтому для ее поддержки, вероятно, потребуется дополнительная работа.
jQuery Сортировка Hotfix с анимацией
var _mouseStop = $.ui.sortable.prototype._mouseStop;
$.ui.sortable.prototype._mouseStop = function(event, noPropagation) {
var options = this.options;
var $item = $(this.currentItem);
var el = this.element[0];
var ui = this._uiHash(this);
var current = $item.css(['top', 'left', 'position', 'width', 'height']);
var cancel = $.isFunction(options.beforeRevert) && !options.beforeRevert.call(el, event, ui);
if (cancel) {
this.cancel();
$item.css(current);
$item.animate(this.originalPosition, {
duration: isNaN(options.revert) ? 500 : options.revert,
always: function() {
$('body').css('cursor', '');
$item.css({position: '', top: '', left: '', width: '', height: '', 'z-index': ''});
if ($.isFunction(options.update)) {
options.update.call(el, event, ui);
}
}
});
}
return !cancel && _mouseStop.call(this, event, noPropagation);
};
Реализация
$('ul').sortable({
revert: true,
beforeRevert: function(e, ui) {
return $(ui.item).hasClass('someClass');
}
});