jQuery Sortable - 取消并恢复不按预期工作

时间:2012-06-19 14:44:25

标签: javascript jquery jquery-ui

问题(jsFiddle demo of the problem

在与jQuery sortable中的revert方法结合使用时,我遇到了cancel设置的问题。取消方法,如jQuery Sortable documentation中所述:

  

取消当前可排序的更改并将其恢复为原样   是在当前排序开始之前。在停止和接收中很有用   回调函数。

这适用于stopreceive回调,但如果我将revert 持续时间添加到可排序的连接列表中,它就会开始行动好笑(见jsFiddle here)。

理想情况下,在取消时,revert可能根本不会发生,或者在更理想的世界中,它会优雅地恢复到它的原始位置。我有什么想法可以让revertcancel发挥得很好吗?

预期

  1. 从左侧列表拖动到右侧列表
  2. 删除项目
  3. 项目动画为原始位置 - 或 - 会立即转移到原始位置
  4. 实际

    1. 从左侧列表拖动到右侧列表
    2. 删除项目
    3. 项目动画为位置,假设可排序成功
    4. 项目立即转移到原始位置,因为可排序已取消
    5. 澄清

      revert属性会将项目移动到项目成功时放弃的位置,然后由于revert方法之前发生cancel而立即切换回原始位置。有没有办法改变生命周期,所以如果执行cancel方法,revert不是,而项目会立即返回到它的原始位置?

3 个答案:

答案 0 :(得分:5)

我在这里为你创建了一个演示:

the jsfiddle code

它似乎产生了你期望的输出。

我改变了接收回调方法:

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

到此:

$(ui.sender).sortable( "option", "revert", false );
希望这是你所期望的。

答案 1 :(得分:5)

在寻找解决方案几个小时后,我决定实现我想要做的唯一方法是修改jQuery可排序插件注册恢复时间的方式。目的是允许revert属性不仅接受booleaninteger,还接受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 :(得分:0)

我最终创建了一个名为beforeRevert的新事件,该事件应该返回true或false。如果为false,则调用cancel函数并将项目动画回原始位置。我没有考虑到helper选项对此进行编码,因此可能需要一些额外的工作来支持它。

带动画的jQuery可排序修补程序

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