关于jquery:jqueryUI可排序:如何在拖动时强制更新占位符位置

jqueryUI sortable: how to force update of placeholder position while dragging

当jQueryUI可排序列表处于拖动操作的中间时,即使用户仅水平移动鼠标,是否有一种方法可以强制jQuery更新占位符的位置? (jQuery对垂直可排序项的命中测试似乎仅在鼠标也垂直移动时才起作用。)

涉及未整理或可拖拽等内部问题的未公开文档或骇人听闻的解决方案是万不得已的方法,如果没有已公开文档的解决方案。

这里的更多信息:

如果将项目拖到垂直jQueryUI可排序列表的右侧,除非将鼠标上下移动,否则列表将不排序。一旦向上或向下移动鼠标(甚至只有1px!),列表就会突然排序。示例位于http://jsfiddle.net/f3Lhg/,摘录如下。

这似乎是一个极端的情况,但是当连接的列表从一个列表横向拖到另一个列表时,这实际上很常见。即使整个拖动并非完全水平,但前30像素到100像素可能会出现这种情况,从而导致无法预测的拖动行为和糟糕的用户体验。即使问题在连接列表上发生的更多,您也可以通过从列表中拖动并从侧面回到列表中来轻松地对单个列表进行复制。

该问题不是特定于浏览器的。在我测试过的所有浏览器上,行为都是相同的。另外,添加tolerance选项不能解决问题。

这是jQueryUI错误还是预期行为?并且有已知的解决方法吗?

顺便说一句,在我的应用程序中,我已在右侧连接了列表,因此我无法使用{axis:'y'}选项,因为这将阻止拖动到连接的列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.js">
    <style type="text/css">
    .sortable { list-style-type: none; width: 400px; }
    .sortable li { margin: 5px 0; padding: 30px; border: 1px solid #999; }
    .sortable li.placeholder { margin: 0; height: 4px; border: 0; padding: 0; background-color: #800; }
    </style>
    <script type="text/javascript">
        $(document).ready(function () {
            $('.sortable').sortable({
                placeholder: 'placeholder'
            }).disableSelection();
        });
   
</head>
<body>
    <ul class="sortable">
       
<li>
Item #1
</li>

       
<li>
Item #2
</li>

       
<li>
Item #3
</li>

       
<li>
Item #4
</li>

       
<li>
Item #5
</li>

   
</ul>

</body>
</html>

看一下jQuery UI源代码,这似乎是预期的行为。

基于axis属性值的设置方式(或不设置),jQuery UI将属性floating设置为布尔值标志,以跟踪您的容器是垂直列表还是水平列表(第46行):

1
2
//Let's determine if the items are being displayed horizontally
this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;

此值用于确定用户拖动元素时jQuery UI如何处理碰撞检测。

具体是:

方法_intersectsWithSides(第492行)使用属性floating来确定您没有拖动水平列表,因此返回垂直碰撞结果。如果同时存在垂直拖动方向和元素的交集,则垂直碰撞检查仅返回true:

1
2
3
4
5
if (this.floating && horizontalDirection) {
    return ((horizontalDirection =="right" && isOverRightHalf) || (horizontalDirection =="left" && !isOverRightHalf));
} else {
    return verticalDirection && ((verticalDirection =="down" && isOverBottomHalf) || (verticalDirection =="up" && !isOverBottomHalf));
}

可能可以通过从_intersectsWithSides中的返回条件中删除verticalDirection要求来解决您的问题(这也可能导致无法预期的错误行为)。

或者:

如果存在垂直或水平拖动,则可以尝试编辑插件的_intersectsWithSides方法以返回true:

1
return (verticalDirection || horizontalDirection) && ((verticalDirection =="down" && isOverBottomHalf) || (verticalDirection =="up" && !isOverBottomHalf)) || ((horizontalDirection =="right" && isOverRightHalf) || (horizontalDirection =="left" && !isOverRightHalf));


对不起,也许我在这里看错了一些东西。

您是说问题是,如果您抓住第一个列表项,将其一直拖动到列表的最右边,然后将其拖动到项#4,则直到您选择完最后一个位置将光标向上或向下移动至少1px?

如果这样的话,我真的根本不认为这是一个严重的可用性问题。我按照上述方法复制了示例,并且需要非常小心才能完美地水平移动鼠标。

另外,我认为所有用户的本能都是拖动项目并垂直而不是水平移动它们。