JqueryUI sortable: how to force update the position of a replacement item when dragging

When the jQueryUI sortable list is in the middle of a drag operation, is there a way to get jQuery to update the position of the placeholder, even if the user only moves the mouse horizontally? (jQuery hit-testing for vertical sorting seems to work only when the mouse moves also vertically).

Undocumented or hacked solutions, which include deactivating with the internal elements of the sortable, draggable, etc., in order, if the last resort is not available.

Here's more info:

If you drag an item on the right side of the jQueryUI vertical sort list, unless you move the mouse up or down, the list is not sorted. As soon as you move the mouse up or down (even 1px right away!), The list is sorted. An example is located at http://jsfiddle.net/f3Lhg/ and is given below.

This may seem like a corner, but it's actually a common occurrence when connected lists are dragged sideways from one list to another. Even if the full drag and drop is not absolutely horizontal, it may be the first 30px-100px, which will lead to unpredictable loss of behavior and disgusting user experience. Despite the fact that the problem is with connected lists, you can easily play one list by dragging it from the list and returning to the list on the side.

The problem is browser independent. The behavior was the same in all the browsers I tested with. In addition, adding the tolerance option does not solve the problem.

Is this a jQueryUI error or an expected behavior? And are there any workarounds?

By the way, in my application, I connected the lists on the right, so I can not use the {axis:'y'} parameter, because this will prevent the connected lists from being dragged and dropped.

 <!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> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.js"></script> <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(); }); </script> </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> 
+4
source share
2 answers

Looking at the jQuery UI source code, this is expected to be a behavior.

Depending on how the axis property is set (or not), the jQuery user interface sets the floating property as a boolean flag to track whether your container is a vertical or horizontal list (line 46):

 //Let 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; 

This value is used to determine how the jQuery user interface handles conflict detection when a user drags an item.

In particular:

The _intersectsWithSides method (line 492) uses the floating property to determine that you are not dragging and dropping into a horizontal list, and therefore returns the results of a vertical collision. Vertical collision checking returns true only if there is a vertical direction of drag and drop and the intersection of elements:

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

You may be able to solve the problem by removing the verticalDirection requirement from the return condition in _intersectsWithSides (this may also cause unexpected behavior with an error).

As an alternative:

You can try changing the plugin method _intersectsWithSides to return true if there is vertical OR horizontal drag:

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

Sorry, Maybe I misunderstood something.

You say that the problem is that if you grab the first element of the list, drag it all the way to the right, outside the list, and then drag it to point No. 4, it does not select the appropriate finish position until you move the cursor at least 1px up or down?

Because, if that is the case, I really don't think this is a serious use issue. I reproduced the example as described above, and it took me VERY carefully to move the mouse perfectly horizontally.

Plus, I think that the instinct of all users will drag and drop elements and move them vertically, not horizontally.

0
source

Source: https://habr.com/ru/post/1435875/


All Articles