jQuery可排序获取交换的2个元素

19

我无法找到如何使用jQuery UI sortable获取目标元素的方法。

    $("#pages").sortable({
        opacity: 0.6,
        update: function(event, ui) {
            var first = ui.item; // First element to swap
            var second = ???? // Second element to swap
            swapOnServer(first, second);
        }
    });
我尝试过的所有选项都指向被拖动的元素,而不是与之交换的元素:ui.item [0]event.srcElementevent.toElement。另外,this 指向列表 (OL) 元素。
这里“第二个”是指下面的情况:
初始顺序为: | 0 | 1 | 2 | 3 |
我们将元素 1 拖到位置 3 并放下。结果如下: | 0 | 3 | 2 | 1 |
所以第一个元素是 3,第二个元素是 1(WRONG!请看下文)。
更新:我意识到自己理解错了。在这种情况下,新的顺序应该是: | 0 | 2 | 3 | 1 |
因此我的问题实际上没有意义。谢谢大家的帮助。我会投票并标记一个答案。
所以问题是如何在这里获得第二个元素?
当前的解决方法(因为在 sortable 中没有“交换”这个术语)如下所示。它使用具有顺序的临时数组。
    var prevPagesOrder = [];
    $("#pages").sortable({
        start: function(event, ui) {
            prevPagesOrder = $(this).sortable('toArray');
        },
        update: function(event, ui) {
            var currentOrder = $(this).sortable('toArray');
            var first = ui.item[0].id;
            var second = currentOrder[prevPagesOrder.indexOf(first)];
            swapOnServer(first, second);
        }
    });

谢谢,
Dmitriy。


3
@Dimitriy,由于没有“第二个项目”,所以你的问题非常不清楚。如果您允许用户在列表中任何位置拾取和放置一个项目,则仅需移动索引以腾出空间。但是,如果他将其向上或向下移动一个位置,则只有两个项目受到影响。但是,如果他从列表顶部获取该项目,并在后面的三个项目之后放下它,则前三个项目的位置都会受到影响。这里并没有发生“切换”。请更详细地描述您需要完成的任务。 - Doug Neiner
swapOnServer 方法怎么样? - San Diago
尝试了解决方案,似乎这一行代码:var second = currentOrder[prevPagesOrder.indexOf(first)]; 应该改为 var second = prevPagesOrder[currentOrder.indexOf(first)]; - nazar kuliyev
6个回答

7
您可以使用 draggabledroppable 来实现可替换效果,而不是使用 sortable。在实践中,这将如下所示:
(function() {
    var droppableParent;

    $('ul .element').draggable({
        revert: 'invalid',
        revertDuration: 200,
        start: function () {
            droppableParent = $(this).parent();

            $(this).addClass('being-dragged');
        },
        stop: function () {
            $(this).removeClass('being-dragged');
        }
    });

    $('ul li').droppable({
        hoverClass: 'drop-hover',
        drop: function (event, ui) {
            var draggable = $(ui.draggable[0]),
                draggableOffset = draggable.offset(),
                container = $(event.target),
                containerOffset = container.offset();

            $('.element', event.target).appendTo(droppableParent).css({opacity: 0}).animate({opacity: 1}, 200);

            draggable.appendTo(container).css({left: draggableOffset.left - containerOffset.left, top: draggableOffset.top - containerOffset.top}).animate({left: 0, top: 0}, 200);
        }
    });
} ());

演示,请访问http://jsfiddle.net/FZ42C/1/


6

看一下"Swapable" jQuery插件:

http://plugins.jquery.com/project/Swapable

它类似于"Sortable",但只影响选定组中的两个元素:拖动的元素和被放置的元素进行交换。所有其他元素保持在当前位置。该插件是基于现有的"Sortable" jQuery插件构建的,并继承了所有可排序选项。


这真是太好了!我想提醒任何试图将他们的代码从sortable更新到swappable的人,非常重要的是你必须明确定义你想拖动的项目,并且光标位置在拖动元素的边界之外,像这样:$('#my-list').swappable({items: 'li', cursorAt: {top:-10}});否则它将无法正常工作。 - Jules Colle
但很糟糕的是,你必须安装另一个插件。 - Donato

6
尝试使用序列化函数,它会给你一个排序好的项目列表哈希值。
如果你只需要新项目放置之前的项目,可以这样做:
$("#pages").sortable({
    opacity: 0.6,
    update: function(event, ui) {
        var first = ui.item; // First element to swap
        var second = ui.item.prev();
        swapOnServer(first, second);
    }
});

如果第二个在列表的开头,它将为空(null)。


整个列表我没什么可做的。我只需要交换了的2个项目,这样我就可以将更改发布到服务器上。我不需要将整个列表交换2个项目后再发布到服务器上。 - Dmytrii Nagirniak
我认为Dmitriy指的是jQuery UI Sortable,而你指的是Interface元素的sortable。 - Ben
更新了我的答案,向您展示如何获取放置物品之前的物品。 - PetersenDidIt
1
ui.item.prev()错误的。它会返回前一个元素。我需要获取被交换的第二个元素。没有任何东西表明它将是前一个元素。 - Dmytrii Nagirniak
4
"被替换"其实并不存在,你只是在列表中间删除某个元素。你可以返回整个列表的新形式,或者返回该元素在新位置前后的一个或多个元素。你并没有进行交换操作。 - PetersenDidIt
1
@petersendidit,非常感谢你的帮助。我刚意识到我的做法有误。实际上并不存在“交换”这种操作,我必须使用整个列表。已更新问题以反映这一点,并赞同了你的回答。 - Dmytrii Nagirniak

5

实际上,并不存在“第二个”项目。您有一个项目,只是将其放置在另一个位置而已。周围的项目会相应地调整其位置。如果要获取所有项目的数组,可以使用 toArray 方法。


0

-2

经过代码审查,我进行了一些行为改进:

<!doctype html>

<html><head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title></title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="robots" content="noindex, nofollow">
  <meta name="googlebot" content="noindex, nofollow">
  <meta name="viewport" content="width=device-width, initial-scale=1">

<style id="compiled-css" type="text/css">

ul,
li{ margin: 0; padding: 0; }

ul { float:left; height: 120px; background: #CCC; overflow:auto; }

li { list-style: none; float: left; width: 100px; height: 100px; background: yellow; margin: 10px;  position: relative; border: "1px solid yellow"}
li.drop-hover .element { opacity: .5; }

.element { position: absolute; width: 100px; height: 100px; background: #00f; color: #fff; text-align: center; line-height: 100px; z-index: 5; }
.element.being-dragged { background-color: #f00; z-index: 9999; }

</style>

<script src="//...jquery-3.6.0.min.js"></script>
<script src="//...jquery-ui.min.js"></script>

</head>

<body style="cursor: auto;">

<ul>
    <li class="ui-droppable">
        <div class="element a ui-draggable">a</div>
    </li>
    <li class="ui-droppable">
        <div class="element b ui-draggable">b</div>
    </li>
    <li class="ui-droppable">
        <div class="element c ui-draggable">c</div>
    </li>
</ul>

<script type="text/javascript">

(function() {
    var droppableParent;
    var superDrop;
    
    $('ul .element').draggable({
        revert: true,
        revertDuration: 200,
        
        start: function (event, ui) {
        
            droppableParent = $(this).parent();
            
            ui.helper.css({zIndex: 9999, opacity: 0.5, border: "1px solid black"})
        },
        stop: function (event, ui) {
        
            ui.helper.css({zIndex: 1, opacity: 1, border: "1px solid blue"})
        }
    });
    
    $('ul li').droppable({

        over: function( event, ui ) {
            
            var draggable_clase = ui.draggable.attr("class");
            var clase_actual = $(event.target).find(" > .element").attr("class")
            var droppable = $(this).find(" > .element");
            superDrop = $(this).find(" > .element")
            
            if(draggable_clase != clase_actual)
                droppable.css({border: "3px solid red", backgroundColor : "yellow"});
            
            console.log(draggable_clase + "\n" + clase_actual)
        },
        out: function( event, ui ) {
        
            var draggable_clase = ui.draggable.attr("class");
            var clase_actual = $(event.target).find(" > .element").attr("class")
            var droppable = $(this).find(" > .element");
            
            if(draggable_clase != clase_actual)
                droppable.css({border: "0px solid red", backgroundColor : "blue"});
                
            var droppable = $(this).find(" > .element");
            //droppable.css({border: "0px", backgroundColor : "#00f"});
        },
        drop: function (event, ui) {
        
            var draggable = $(ui.draggable[0]),
                draggableOffset = draggable.offset(),
                container = $(event.target),
                containerOffset = container.offset();
            
            $(this).find(" > .element").appendTo(droppableParent);
            //$(this).find(" > .element").css({zIndex: 1, opacity: 0.5, border: "1px solid black"})
            //$(this).find(" > .element").css({opacity: 0.35}).animate({opacity: 1}, 200);
            
            superDrop.css({border: "0px solid orange", backgroundColor : "blue"});
            
            draggable.appendTo(container).css({
                left: draggableOffset.left - containerOffset.left, 
                top: draggableOffset.top - containerOffset.top})
            .animate({left: 0, top: 0}, 200);
        }
    });
} ());

</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接