最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery Sortable - cancel and revert not working as expected - Stack Overflow

programmeradmin1浏览0评论

Problem (jsFiddle demo of the problem)

I'm having some trouble with the revert setting when used in conjunction with the cancel method in the jQuery sortable. The cancel method, as documented in the jQuery Sortable documentation states:

Cancels a change in the current sortable and reverts it back to how it was before the current sort started. Useful in the stop and receive callback functions.

This works fine in both the stop and receive callbacks, however if I add a revert duration to the sortable connected list, it starts to act funny (see jsFiddle here).

Ideally, upon cancelling, the revert could simply not happen, or alternatively in a more ideal world, it would gracefully revert to it's original location. Any ideas how I can get the revert and cancel to play nice?

Expected

  1. Drag from left list to right list
  2. Drop item
  3. Item animates to original location - or - immediately shifts to original location

Actual

  1. Drag from left list to right list
  2. Drop item
  3. Item animates to new location, assuming sortable is successful
  4. Item immediately shifts to original location, as sortable was cancelled

Clarification

The revert property moves the item to the location where the item would drop if successful, and then immediately shifts back to the original location due to the revert occurring before the cancel method. Is there a way to alter the life-cycle so if the cancel method is executed, revert isn't, and instead the item is immediately return to it's original location?

Problem (jsFiddle demo of the problem)

I'm having some trouble with the revert setting when used in conjunction with the cancel method in the jQuery sortable. The cancel method, as documented in the jQuery Sortable documentation states:

Cancels a change in the current sortable and reverts it back to how it was before the current sort started. Useful in the stop and receive callback functions.

This works fine in both the stop and receive callbacks, however if I add a revert duration to the sortable connected list, it starts to act funny (see jsFiddle here).

Ideally, upon cancelling, the revert could simply not happen, or alternatively in a more ideal world, it would gracefully revert to it's original location. Any ideas how I can get the revert and cancel to play nice?

Expected

  1. Drag from left list to right list
  2. Drop item
  3. Item animates to original location - or - immediately shifts to original location

Actual

  1. Drag from left list to right list
  2. Drop item
  3. Item animates to new location, assuming sortable is successful
  4. Item immediately shifts to original location, as sortable was cancelled

Clarification

The revert property moves the item to the location where the item would drop if successful, and then immediately shifts back to the original location due to the revert occurring before the cancel method. Is there a way to alter the life-cycle so if the cancel method is executed, revert isn't, and instead the item is immediately return to it's original location?

Share Improve this question edited Mar 7, 2013 at 14:30 Richard asked Jun 19, 2012 at 14:44 RichardRichard 8,2803 gold badges39 silver badges60 bronze badges 6
  • 1 Apologies, updated the question for clarity. – Richard Commented Jun 19, 2012 at 15:25
  • I've been playing around with it on jsfiddle. It seems that the revert option also delays when the beforeStop, stop and receive event functions are called. Check jsfiddle.net/reygonzales/MBTAm/12 – Rey Gonzales Commented Jun 19, 2012 at 17:51
  • That's interesting @ReyGonzales, I think I may have to resort to amending the jQuery-ui library itself, or alternatively write my own revert animation which executes at the appropriate time if the sortable was successful. – Richard Commented Jun 20, 2012 at 8:07
  • all those jsfiddle's are deleted, what now? :( – EaterOfCode Commented Mar 7, 2013 at 14:26
  • 1 @EaterOfCorpses, I've updated the links to point to a new jsFiddle which has the same problem. :) – Richard Commented Mar 7, 2013 at 14:30
 |  Show 1 more comment

3 Answers 3

Reset to default 5

i created a demo for you here:

the jsfiddle code

it seems to produce the output you expect.

i changed the receive callback method from this:

$(ui.sender).sortable('cancel');

to this:

$(ui.sender).sortable( "option", "revert", false );

hopefully, this is what you expected.

After many hours for searching for a solution I decided the only way to achieve what I was trying to do was to amend the way in which the jQuery sortable plugin registered the revert time. The aim was to allow for the revert property to not only accept a boolean or integer, but also accept a function. This was achieved by hooking into the prototype on the ui.sortable with quite a lot of ease, and looks something like this.

jQuery Sortable Hotfix

$.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;
}

Implementation

$('ul').sortable({
    revert: function(ev, ui)
    {
        // do something here?
        return 10;
    }
});

I ended up creating a new event called beforeRevert which should return true or false. If false then the cancel function is called and the item is animated back to its original position. I didn't code this with the helper option in mind, so it would probably need some additional work to support that.

jQuery Sortable Hotfix with animation

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);
};

Implementation

$('ul').sortable({
  revert: true,
  beforeRevert: function(e, ui) {
    return $(ui.item).hasClass('someClass');
  }
});
发布评论

评论列表(0)

  1. 暂无评论