jQuery UI Draggable and Droppable, reverting and accepting elements - javascript

I have been experimenting with this code: jsfiddle It highlights and let you know which boxes you can drop the boxes onto but it is not accepting any droppables. Does anyone know how I can alter this code to accept a droppable instead of it just reverting back?
$(".DragItem").draggable({
revert: true,
helper: "clone"
});
$(".DropItem").droppable({
tolerance: "touch",
over: function (event, ui) {
var dropItem = $(this);
var dragItem = $(ui.draggable);
var valid = String(dropItem.data("id")).indexOf(dragItem.data("id")) > -1;
if (valid) {
dropItem.addClass("DropTargetValid");
} else {
dropItem.addClass("DropTargetInvalid");
}
},
out: function (event, ui) {
var dropItem = $(this);
dropItem.removeClass("DropTargetValid");
dropItem.removeClass("DropTargetInvalid");
},
deactivate: function (event, ui) {
var dropItem = $(this);
dropItem.removeClass("DropTargetValid");
dropItem.removeClass("DropTargetInvalid");
}
});

You will need to append the clones() to the correct divs and revert them if they don't match, first accept: all the dragable elements and then handle the revert in the drop: section.
also you will need to create and save the origin position for the ellement you clone and drag so you can revert him to its original position and then removing it from the page.
Here is the finall script demo:
JSnippet demo draggable & droppable
have fun!

I would start from something like this:
re-use the built-in query-ui functionality, e.g. "accept" or "activeClass" parameters of a droppable
if there is a small number of containers - you might declare "droppables" separately and use "accept" to e.g. allow only certain classes of draggables (like in the demo below)
trying to "hack" draggables & droppables is possible but not very easy, especially with complex elements (if draggables and droppables have more complex html structure than just flat divs)
Sample:
$(".drop1").droppable({
accept: '.drag1',
activeClass: 'DropTargetValid',
drop: function (ev, ui) {
$(ev.target).append(ui.draggable.clone());
}
});
Fiddle demo
--- EDIT ---
Updated demo

Related

Jquery UI Draggable clone disappearing

I am trying to use the jquery-ui draggable to make some element draggable.
I set the helper option to clone the current element.
It's making the clone correctly but when I drop the clone disappears. It doesn't stay at the dragged place.
See this for Demo Fiddle Link
$('#drag').draggable({
helper: function (e, ui) {
return $(this).clone();
}
});
What am I missing ?
There maybe a simpler way, but through data of draggable, you can target a property that deals with this. Like this:
stop : function(e, ui){
$('#drag').draggable().data()["ui-draggable"].cancelHelperRemoval = true;
}
fiddle: http://jsfiddle.net/n10ucrLd/
I think there's been a lot of troubles with helper: 'clone'. I always got it to work, when I defined a droppable as well. E.g.:
HTML:
<div id="drag">Drag This</div>
<div class="container"></div>
JavScript:
$('#drag').draggable({
helper: function (e, ui) {
return $(this).clone(true);
}
});
$( ".container" ).droppable({
drop: function (event, ui) {
ui.draggable.clone().appendTo($(this)).draggable();
}
});
Live example: http://jsbin.com/vibeqaganu/1/edit?html,css,js,output

jquery UI draggable: ui.children is not a function

i have a draggable list, a sortable-droppable list and a couple of li's inside the first.
now i want to pull them over, in the stop-funtion i have a function that adds a class to the first child (it's a span representing the clip-number like
<li>
<span>1.</span>
<span>Title</span>
<span>1min23sec</span>
</li>
). the reason for this is, i want to represent the original clip number in the playlist(sortable).
but i get a console error saying
TypeError: ui.children is not a function
ui.children("li")[0].addClass(".slot_clip_info");
i am not 100% sure, but i think this exact code HAS already worked in the past time, i might have changed somthing without knowing, but i am not aware of that.
draggable:
$(function() {
$(".pl_clipEntry").draggable({
appendTo: "body",
revert: "invalid",
connectToSortable: "#tracks",
distance: 20,
helper: function(){
return $(this).clone().width($(this).width()); // hack for the drag-clone to keep the correct width
},
stop: function(ui) {
ui.children("li")[0].addClass(".slot_clip_info");
},
zIndex: 100
});
});
sortable:
$(function() {
var removeItem;
$("#tracks").sortable({
items: "li:not(.placeholder)",
connectWith: "li",
placeholder: "sort_placeholder",
helper: "clone",
distance: 20,
sort: function () {
$(this).removeClass("ui-state-default");
updatePlaylist();
},
over: function (event,ui) {
updatePlaylist();
removeItem = false;
console.log(event);
console.log(ui);
var originalClass = ui.helper.context.childNodes[0].className;
console.log(originalClass);
var small_clip = originalClass.match(/(\d+)/g)[1];
ui.item.context.children[0].innerHTML = small_clip;
ui.item.context.children[0].classList.add("slot_clip_info");
},
out: function () {
updatePlaylist();
removeItem = true;
},
beforeStop: function(event,ui) {
if (removeItem) {
ui.item.remove();
}
},
stop: function(event,ui) {
console.log("checking placeholder");
var list = $(this);
var count = list.children(':not(.placeholder)').length;
list.children('.placeholder').css("display", count > 0 ? "none" : "block");
savePlaylist();
}
});
as soon as i pull and element IN or reorder them, i get the said error.
also, on refresh, the list seems to multiply itself.. but i guess that's another issue...
Full fiddle (pretty messy, functionality in top dropdown button "PL TOGGLE"
UPDATE: another thing i noticed: the first drag works without problems, then shows the error on release, subsequent drags will (mostly.. sometimes they do...) not work
you need to make ui a jquery object, and then wrap the first element in another jquery object to do what you want.
so change:
ui.children("li")[0].addClass(".slot_clip_info");
to
$($(ui).children("li")[0]).addClass(".slot_clip_info");
In jQuery UI's draggable module, the stop function has 2 parameters : event and ui.
ui is a javascript object (and not a jQuery one, there's a difference.)
This object has 3 attributes :
helper which is a jQuery object
position which is a javascript object
offset which is a javascript object
Depending on your HTML code (we don't have), you could replace
ui.children("li")[0].addClass(".slot_clip_info");
by
ui.helper.children("li")[0].addClass(".slot_clip_info");

Sortable, droppable nested list issue [duplicate]

I'm working on a project where I'm dragging elements from a 3rd party jQuery control to a jQuery sortable, using a combination of droppable and sortable.
This works perfectly fine, except the item being added is always added to the bottom of the sortable list, and you must then move it to the correct location as a separate step.
Is it possible to have the item added to the location where you dropped it in the list?
You can see this behavior in the jQuery shopping card droppable demo from here. Here is a jsfiddle of the same code. As you add items from the products to your cart at the bottom, it always adds at the bottom, even if you drop it near the top.
Here's the jQuery code:
$(function () {
$("#catalog").accordion();
$("#catalog li").draggable({
appendTo: "body",
helper: "clone"
});
$("#cart ol").droppable({
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
accept: ":not(.ui-sortable-helper)",
drop: function (event, ui) {
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
}).sortable({
items: "li:not(.placeholder)",
sort: function () {
$(this).removeClass("ui-state-default");
}
});
});
use droppable's drop event's callback to compare the current top offset position of the draggable helper with the top offset of every element already present or previously added in the droppable
drop: function (event, ui) {
if($(this).find(".placeholder").length>0) //add first element when cart is empty
{
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
else
{
var i=0; //used as flag to find out if element added or not
$(this).children('li').each(function()
{
if($(this).offset().top>=ui.offset.top) //compare
{
$("<li></li>").text(ui.draggable.text()).insertBefore($(this));
i=1;
return false; //break loop
}
})
if(i!=1) //if element dropped at the end of cart
{
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
}
}
DEMO WITH CODE
FULL SCREEN DEMO
What about doing this? Using both the connectToSortable AND connectWith options works, I think. There might be a more clever way to hide/show the placeholder, but this definitely works.
$(function () {
$("#catalog").accordion();
$("#catalog li").draggable({
appendTo: "body",
helper: "clone",
connectToSortable: "#cart ol"
});
$("#cart ol").sortable({
items: "li:not(.placeholder)",
connectWith: "li",
sort: function () {
$(this).removeClass("ui-state-default");
},
over: function () {
//hides the placeholder when the item is over the sortable
$(".placeholder").hide();
},
out: function () {
if ($(this).children(":not(.placeholder)").length == 0) {
//shows the placeholder again if there are no items in the list
$(".placeholder").show();
}
}
});
});
Work Demo in Fiddle

jQuery - drag and drop of cloned element

I have a cloned element which I am able to drag however I wish to drop it in a specific div element and if valid not revert back to its original position, however it is always reverting back to its original position whether it is valid or not.
I am currently using the code below:
$("ul#objectsList li").draggable({
revert: 'invalid',
snap: "#objectsDropBox",
snapMode: "inner",
helper: function() { return $(this).clone().appendTo('body').show(); },
start: function(e, ui) { $(ui.helper).addClass("ui-draggable-helper");}
});
$("#objectsDropBox").droppable({
accept: "ul#objectsList li",
drop: function( event, ui ) {
alert('hi');
}
});
Why is it not staying in the div when a valid draggable is dropped?
Try this
$("#objectsDropBox").droppable({
accept: "ul#objectsList li",
drop: function (event, ui) {
$(this).append(ui.draggable);
//if you want to retain the element use ui.draggable.html() or clone it.
}
});
Fiddle - http://jsfiddle.net/dmNhZ/

Sortable list, sort items just between different list

In this example http://jqueryui.com/sortable/#connect-lists is possible to drag and drop the items between different list and also the same list.
Will it be possible to dis-activate the drag and drop in the same list and allow just the drag and drop between different lists? how?
This is the best Ican do here:
$("#sortable1, #sortable2").sortable({
connectWith: ".connectedSortable",
stop: function(event, ui) {
if (ui.item[0].parentNode == this) {
$(this).sortable('cancel');
}
}
}).disableSelection();​
Demo http://jsfiddle.net/dfsq/J6uM5/
Working Demo :) http://jsfiddle.net/UnFdU/1/
I have built a small logic behind three events, recieve, start and stop. Everytime if the list is same list then user cannot drop it else if different list they can, try it your self. Little Explanation below
When user starts Dragging start says: canDropThat = false;
recieve only gets triggered if it item is dropped from connected list, i.e. if receive is triggered make canDropThat = true; ; hence allow dropping.
In the end stop checks for the flag and if its the right flag it allows dropping else reject.
Hope it fits the cause :))
Code
$(function() {
canDropThat = false;
var sortlists = $("#List1, #List2").sortable({
tolerance: 'pointer',
connectWith: '#List1, #List2',
helper: 'original',
scroll: true,
receive: function(event, ui) {
//Run this code whenever an item is dragged and dropped into this list
canDropThat = true;
},
start: function(event, ui) {
canDropThat = false;
},
stop: function(event, ui) {
if (!canDropThat) {
$(this).sortable('cancel');
}
}
}).on('scroll', function() {
sortlists.scrollTop($(this).scrollTop());
});
});​

Categories

Resources