简体   繁体   English

如何用jQuery UI拖放和交换元素?

[英]How to swap element with jQuery UI draggable and droppable?

I have two div.containers. 我有两个div.containers。 Both containers have div.item. 两个容器都有div.item。 With jQuery, how can I swap div.item elements by drag & drop? 使用jQuery,如何通过拖放交换div.item元素? Both element should able to re-swap again. 这两个元素都应该可以重新交换。

Is there any simple way to do this? 有没有简单的方法可以做到这一点?

Thanks... 谢谢...

@Ei Maung.. @Ei Maung ..

I got smooth solution from your dirty solution.. 我从您的肮脏解决方案中得到了解决方案。

$(document).ready(function () {
    src = null;
    options = {
        revert:true,
        /*axis: 'x',*/
        opacity: 0.8,
        start: function() {
                src = $(this).parent();
        }
    };

    $(".item").draggable(options);
    $(".container").droppable({
        drop: function(event, ui) {
                src.append(
                        $('.item', this).remove().clone()
                        .removeClass().addClass("item")
                        .css({"left": '', "opacity": '',"top":''})
                        .draggable(options)
                );

                $(this).append(
                        ui.draggable.remove().clone()
                        .removeClass().addClass("item")
                        .css({"left": '', "opacity": '',"top":''})
                        .draggable(options)
                );
        }
    });

});

A little late maybe, but I think this is a better solution... Will post for documentation/search purposes in case other people find this useful 也许有点晚了,但是我认为这是一个更好的解决方案...如果其他人觉得这很有用,将出于文档/搜索目的而发布

Note: you also need jQuery UI's Position element loaded in your UI build for this solution to work. 注意:您还需要在UI生成中加载jQuery UI的Position元素,此解决方案才能起作用。

In my example, I'm creating a set of draggable "coupons" which can be placed in various positions. 在我的示例中,我正在创建一组可拖动的“优惠券”,这些优惠券可以放置在各个位置。 Only one coupon can sit in any droppable area at a given time. 在给定的时间,只有一张优惠券可以坐在任何可放置的区域。

In order to manage coupon assignment to droppable areas, I created some helper objects which I will use to extend the options object of the draggable & droppable prototypes: 为了管理将优惠券分配到可放置区域,我创建了一些帮助对象,这些对象将用于扩展可拖动和可放置原型的options对象:

var dropObj = { hasCoupon: false, couponId: null }
var couponObj = { dropId: null }

Then (on DOM ready) extend: 然后(准备好DOM)扩展:

$.extend( $.ui.droppable.prototype.options, dropObj );
$.extend( $.ui.draggable.prototype.options, couponObj );

Finally, setup your draggables & droppables... When you're setting up the droppable use jquery UI's position helper to assist in swapping the draggables... 最后,设置您的可拖动对象和可放置对象...设置可放置对象时,请使用jquery UI的位置助手来帮助交换可拖动对象...

$('.selector').droppable({
    drop: function( event, ui ) {   
        var current, swapId;
        if ( $(this).droppable('option', 'hasCoupon') === false ) {
            // ...
        } else {
            current = $(this).droppable('option', 'couponId');
            swapId = ui.draggable.draggable('option', 'dropId');
            if ( swapId !== null ){
                current.position({ 
                    my: "center", at: "center", of: swapId,
                    using: function(to) {
                        $(this).animate({
                            top: to.top,
                            left: to.left
                        }, ui.draggable.revertDuration, function() {
                            swapId.droppable('option', 'hasCoupon', true);
                            swapId.droppable('option', 'couponId', current);
                            current.draggable('option', 'dropId', swapId);
                        });
                    }
                });
            }
        }
        $(this).droppable('option', 'hasCoupon', true);
        $(this).droppable('option', 'couponId', ui.draggable);
        ui.draggable.draggable('option', 'dropId', $(this));
        ui.draggable.position({ my: "center", at: "center", of: $(this),
            using: function(to) { $(this).animate({ top: to.top, left: to.left }, 150 ); }
        });
    }
});

Note: We're manually setting the values for couponId/dropId in the animation callback for the swap, since drag events are not actually firing in that situation (movement is handled via a jquery animation call instead). 注意:我们在交换的动画回调中手动设置couponId / dropId的值,因为在这种情况下拖动事件实际上并未触发(而是通过jquery动画调用来处理运动)。

I played around with using .trigger() on dragstart/dragstop originally, but they didn't trigger the drop event as I assumed they should. 我最初在dragstart / dragstop上使用.trigger()进行操作,但是它们并没有像我认为的那样触发drop事件。

Maybe I'm missing something, but I think I have a much simpler solution: 也许我缺少了一些东西,但是我认为我有一个简单得多的解决方案:

$('.droppable').droppable({
    drop: function (event, ui) {
        ui.draggable.parent().append($(this).children());

        $(this).append(ui.draggable);

        ui.draggable.css({
            left: '',
            top: ''
        });
    }
});

In a nutshell: 简而言之:

  1. When a draggable item is dropped in a droppable area, get the (previous) parent element of the draggable item. 将可拖动项放置在可拖放区域中时,获取可拖动项的(上一个)父元素。
  2. Remove the children from the droppable area and append them to the parent element of the draggable item. 从可放置区域中删除子项,并将其附加到可拖动项的父元素中。
  3. Remove the draggable item from its (previous) parent element and append it to the droppable area where it was dropped. 从其(上一个)父元素中删除可拖动项,并将其附加到放置它的可放置区域。
  4. The draggable item's position will be something weird at this point because we've removed elements from the page and re-appended them, so reset its position. 此时可拖动项的位置会有些奇怪,因为我们已经从页面中删除了元素并重新添加了元素,因此请重置其位置。
    $(function () {
        $('#sortable').sortable({
            start: function (e, ui) {
                // creates a temporary attribute on the element with the old index
                $(this).attr('data-previndex', ui.item.index());
            },
            update: function (e, ui) {
                // gets the new and old index then removes the temporary attribute
                newIndex = ui.item.index();
                oldIndex = $(this).attr('data-previndex');
                $(this).removeAttr('data-previndex');
                tempNew = newIndex - 1;
                tempoldIndex = oldIndex;
                if (oldIndex > newIndex) {
                    tempNew = newIndex + 1;
                    $("#sortable li:eq(" + tempNew + ")").insertAfter($("#sortable li:eq(" + tempoldIndex + ")"));
                } else {
                    $("#sortable li:eq(" + tempNew + ")").insertBefore($("#sortable li:eq(" + tempoldIndex + ")"));
                }
            }
        });
    });

// coded by ubaidullah chan and verified //由ubaidullah chan编码并验证

OK, I got the dirty solution... 好,我得到了肮脏的解决方案...

$(document).ready(function () {
    src = null;
    options = {
        revert:true,
        axis: 'x',
        opacity: 0.8,
        start: function() {
            src = $(this).parent();
        }
    };

    $(".item").draggable(options);
    $(".container").droppable({
        drop: function(event, ui) {
            src.append(
                $('.item', this).remove().clone()
                .removeClass().addClass("item")
                .css({"left": '', "opacity": ''})
                .draggable(options)
            );

            $(this).append(
                ui.draggable.remove().clone()
                .removeClass().addClass("item")
                .css({"left": '', "opacity": ''})
                .draggable(options)
            );
        }
    });
});

Hope, someone could improve this... :) 希望有人可以改善这个... :)

Cheer... 欢呼...

I found this solution at pengoworks: 我在pengoworks找到了以下解决方案:

jQuery.fn.swap = function(b) {
    b = jQuery(b)[0];
    var a = this[0];
    var t = a.parentNode.insertBefore(document.createTextNode(''), a);
    b.parentNode.insertBefore(a, b);
    t.parentNode.insertBefore(b, t);
    t.parentNode.removeChild(t);
    return this;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM