问题
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:
- When a draggable item is dropped in a droppable area, get the (previous) parent element of the draggable item.
- Remove the children from the droppable area and append them to the parent element of the draggable item.
- Remove the draggable item from its (previous) parent element and append it to the droppable area where it was dropped.
- 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