How to swap element with jQuery UI draggable and droppable?

跟風遠走 提交于 2020-01-01 22:28:14

问题


I have two div.containers. Both containers have div.item. With jQuery, how can I swap div.item elements by drag & drop? Both element should able to re-swap again.

Is there any simple way to do this?

Thanks...


回答1:


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

});



回答2:


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.

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:

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

Then (on DOM ready) extend:

$.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...

$('.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).

I played around with using .trigger() on dragstart/dragstop originally, but they didn't trigger the drop event as I assumed they should.




回答3:


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.



回答4:


    $(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




回答5:


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...




回答6:


I found this solution at 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;
};


来源:https://stackoverflow.com/questions/1353241/how-to-swap-element-with-jquery-ui-draggable-and-droppable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!