【问题标题】:jQuery UI sortable tolerance option not working as expectedjQuery UI 可排序容差选项未按预期工作
【发布时间】:2012-05-25 02:39:52
【问题描述】:

这是part from jQuery UI documentation 选项的tolerance 选项:

这是拖动过程中重新排序的行为方式。可能的值: '相交','指针'。在某些设置中,“指针”更自然。

intersect: draggable 与 droppable 重叠至少 50%

默认是intersect,但是如果鼠标指针不在可排序项的上方,排序就不会发生,不管被拖动的元素至少超过另一个可排序项的50%(我期望的功能)这个也发生在演示页面上(上面链接)

这是 jQuery UI 中的错误,还是我理解错误?

【问题讨论】:

标签: jquery jquery-ui jquery-ui-sortable


【解决方案1】:

这与您在 IE9、FF11 和 Chrome18 中描述的完全一样。

当鼠标在上方至少 50% 时相交重叠。
我认为这是不正确的文档。

编辑:我在 JQuery Bugtracker 中没有发现与此相关的错误。

【讨论】:

  • 谢谢...我会尝试在排序事件中做一些变通以达到预期的结果
【解决方案2】:

对于那些有同样问题的人,这是我使用的解决方法:

$('#sortable').sortable({
    axis: 'x',
    sort: function (event, ui) {
        var that = $(this),
            w = ui.helper.outerWidth();
        that.children().each(function () {
            if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) 
                return true;
            // If overlap is more than half of the dragged item
            var dist = Math.abs(ui.position.left - $(this).position().left),
                before = ui.position.left > $(this).position().left;
            if ((w - dist) > (w / 2) && (dist < w)) {
                if (before)
                    $('.ui-sortable-placeholder', that).insertBefore($(this));
                else
                    $('.ui-sortable-placeholder', that).insertAfter($(this));
                return false;
            }
        });
    },
});​

这适用于水平排序,垂直排序将outerWidth 更改为outerHeightposition.left 更改为position.top

Here's a complete working example

【讨论】:

  • 这对于单轴排序非常有效。然而,对于grid style,它不知道它结束了哪个“行”,而且完全是香蕉。关于如何处理两个轴的因素有什么想法吗?
  • 回答了我自己的问题。继续:)
  • 我必须添加 placeholder: "ui-sortable-placeholder", 才能让它在最新的 jquery-ui 中工作
  • 如果你使用connected sortable,更改:var that = ui.placeholder.parent()
【解决方案3】:

我有大小不均的可分类项目,这让事情变得更糟。我已经修改了 dioslaska 的代码,以便在处理程序的底部通过子项的底部(向下移动时)时更改顺序,并且对于顶部也是如此...

sort: function (event, ui) {
    var that = $(this),
        draggedHeight = ui.helper.outerHeight(),
        originalTop = ui.originalPosition.top,
        draggedTop = ui.helper.position().top,
        draggedBottom = draggedTop + draggedHeight;
    that.children().each(function () {
        if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) {
            return true;
        }
        var childTop = $(this).position().top,
            childHeight = $(this).outerHeight(),
            childBottom = childTop + childHeight,
            isChildAfter = originalTop < childTop,
            largeTop,largeBottom,smallTop,smallBottom;
        if (childHeight > draggedHeight) {
            largeTop = childTop;
            largeBottom = childTop + childHeight;
            smallTop = draggedTop;
            smallBottom = draggedBottom;
        } else {
            smallTop = childTop;
            smallBottom = childTop + childHeight;
            largeTop = draggedTop;
            largeBottom = draggedBottom;
        }
        if (smallBottom > largeTop || smallTop < largeBottom) {
            if (isChildAfter && draggedBottom >= childBottom) {
                $('.ui-sortable-placeholder', that).insertAfter($(this));
            } else if (!isChildAfter && draggedTop <= childTop) {
                $('.ui-sortable-placeholder', that).insertBefore($(this));
                return false;
            }
        }
    });
}

您可以看到重叠检测比以前有点棘手,因为您可能将一个大项目拖到一个小项目上,反之亦然。

它并不完美,但它比默认功能有了巨大的改进。

【讨论】:

【解决方案4】:

这是对@dioslaska 功能的补充。如果您需要在网格中排序(例如,您的元素是浮动的),您可以检查子元素的顶部位置,看看它是否在同一“行”中,如下所示:

sort: function (event, ui) {
  var self = $(this),
      width = ui.helper.outerWidth(),
      top = ui.helper.position().top;//changed to ;

  self.children().each(function () {
    if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) {
      return true;
    }
    // If overlap is more than half of the dragged item
    var distance = Math.abs(ui.position.left - $(this).position().left),
        before = ui.position.left > $(this).position().left;

    if ((width - distance) > (width / 2) && (distance < width) && $(this).position().top === top) {
      if (before) {
        $('.ui-sortable-placeholder', self).insertBefore($(this));
      } else {
        $('.ui-sortable-placeholder', self).insertAfter($(this));
      }
      return false;
    }
  });
}

【讨论】:

  • 第 4 行应以分号结尾,而不是逗号...我无法对其进行编辑以进行更正。
【解决方案5】:

稍微扩展 dioslaska 的回答。这是一个示例(我称之为)125% 重叠http://jsfiddle.net/yj1wwtsd/4/

这只会在您超过 25% 时翻转一个元素。在我的例子中,我将 droppable 和 sortable 结合起来,当拖动的项目在翻转之前可以完全重叠另一个(以允许放置)时感觉更好。

特别值得注意的是最后一行的 jQueryUI hack。如果没有这个,它总是默认为相交容差,即使排序方法试图做一些不同的事情。这可能会与 jQueryUI 的未来版本(使用 1.11.2 测试)中断。

$('#sortable').sortable({
    axis: 'x',
    sort: function (event, ui) {
        var that = $(this);
        var w = ui.helper.outerWidth();
        var centreOfDraggedItem = ui.position.left + w/2;

        that.children().each(function () {
            if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) 
                return true;
            var centreOfThisItem =  $(this).position().left + w/2;
            var dist = centreOfDraggedItem - centreOfThisItem;
            var before = centreOfDraggedItem > centreOfThisItem;
            if (Math.abs(dist) < w/2) {
                if (before && dist > w/4) { // moving right
                    $('.ui-sortable-placeholder').insertAfter($(this));
                    return false;
                }
                if (!before && dist < -(w/4)) { // moving left
                    $('.ui-sortable-placeholder').insertBefore($(this));
                    return false;
                }
            }
        });
    },
});
$('#sortable').data('ui-sortable')._intersectsWithPointer = function () {return false;};

【讨论】:

    【解决方案6】:

    这是我基于勾股定理和比较元素中心之间的距离对网格布局sort方法的实现:

    $("#sortable").sortable({
        ...
        sort: sort_jQueryBug8342Fix
    });
    
    function sort_jQueryBug8342Fix(e, ui) {
    
        // ui-sortable-helper: element being dragged
        // ui-sortable-placeholder: invisible item on the original place of dragged item
        var container = $(this);
        var placeholder = container.children('.ui-sortable-placeholder');
    
        var draggedCenterX = ui.helper.position().left + ui.helper.outerWidth()/2;
        var draggedCenterY = ui.helper.position().top + ui.helper.outerHeight()/2;
    
        container.children().each(function () {
            var item = $(this);
    
            if(!item.hasClass( 'ui-sortable-helper' ) && !item.hasClass( 'ui-sortable-placeholder' ) ) {
                var itemCenterX = item.position().left + item.outerWidth()/2;
                var itemCenterY = item.position().top + item.outerHeight()/2;
    
                // Pythagorean theorem
                var distanceBetweenCenters = Math.sqrt(Math.pow(itemCenterX - draggedCenterX, 2) + Math.pow(itemCenterY - draggedCenterY, 2));
    
                var minDimension = Math.min(item.outerWidth(), item.outerHeight(), ui.helper.outerWidth(), ui.helper.outerHeight());
                var overlaps = distanceBetweenCenters < (minDimension / 2);
    
                if (overlaps) {
                    if (placeholder.index() > item.index()) {
                        placeholder.insertBefore(item);
                    } else {
                        placeholder.insertAfter(item);
                    }
                    container.sortable('refreshPositions');
                    return false;
                }
    
            }
        });
    }
    

    它非常适用于网格布局和宽度和高度尺寸相近的项目,例如 4:3 或 16:10 比例的图像缩略图。在这种情况下,它需要 50-60% 的重叠来触发排序。如果您有非常宽的元素,例如 300x50 像素(或不同大小的元素),那么我想它也可以,但是您必须将它们与 X 轴重叠更多,例如 90%。

    注意:如果您对 Dropzone.js 元素进行排序,则应将 &amp;&amp; item.hasClass('dz-preview') 添加到第一个 if 语句中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-17
      • 2018-06-27
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多