jQuery UI可排序容差选项无法按预期工作

以下是tolerance选项的jQuery UI文档中的部分 :

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

相交:draggable与droppable重叠至少50%

默认值是intersect ,但如果鼠标指针不在可排序项目之上,则排序不会发生,无论被拖动的元素是否比其他可排序项目至少高50%(我期望的function)这发生在演示页面上以及(上面链接)

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

这与您在IE9,FF11和Chrome18中描述的完全相同。

当鼠标至少高于50%时,相交会重叠。
我认为这是不正确的文档。

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

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

 $('#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更改为outerHeight ,将position.top更改为position.top

这是一个完整的工作示例

我的可排序项目大小不均匀,这会使事情变得更糟。 我已经修改了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; } } }); } 

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

它并不完美,但它是对默认function的巨大改进。

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

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

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

当你超过25%时,它只会翻转一个元素。 在我的情况下,我结合了droppable和sortable,当被拖动的项目在翻转之前可以完全重叠另一个(允许掉落)时感觉更好。

特别值得注意的是最后一行的jQueryUI hack。 如果没有这个,它总是默认为交叉容差,即使sort方法试图做一些不同的事情。 这可能会破坏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;}; 

以下是基于毕达哥拉斯定理和比较元素中心之间距离的网格布局 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%的重叠来触发排序。 如果你有非常宽的元素,比如300×50像素(或不同大小的元素),那么我认为它也会起作用,但你必须更多地将它们重叠X轴,比如90%。

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