Sortable table and Draggable TR - javascript

I am trying to do something very simple. I am trying to make the TRs of a table sortable with JQuery UI and also Draggable to a different div which I will use as a trash can. I have the following script. But for some reason Drag and Sort are conflicting
$("#TBL_OUTPUT").sortable({
items: 'tr:not(:first)'
});
$("#TBL_OUTPUT tr").draggable({
helper: "clone",
start: function(event, ui) {
c.tr = this;
c.helper = ui.helper;
}
});
$("#TRASHCAN").droppable({
hoverClass: "TRASH_Hover",
drop: function(event, ui) {
$(c.tr).remove();
$(c.helper).remove();
}
});
Any thoughts?

You can simply use two sortables. Like:
$("table").sortable({
items: 'tr:not(:first)',
connectWith: 'div.bin',
helper: 'clone',
start: function (e, ui) {
$('.bin').css("background-color", "red");
},
stop: function (e, ui) {
$('.bin').css("background-color", "green");
}
});
$('div.bin').sortable({
connectWith: 'table',
update: function (e, ui) {
var content = ui.item.children('td').text();
if (confirm('Delete item: ' + content + '?')) {
$('div.bin').empty();
alert('Item ' + content + ' deleted!');
} else {
alert(content + 'will stay in the bin and you can drag it back to table');
}
}
});
FIDDLE: https://jsfiddle.net/rte2by43/4/
If you want to keep droppable, this will also work:
$("#TBL_OUTPUT").sortable({
items: 'tr:not(:first)',
connectWith: '#TRASHCAN'
});
$("#TRASHCAN").droppable({
hoverClass: "TRASH_Hover",
drop: function(event, ui) {
alert($(ui.draggable).children('td').text());
}
});

Related

Iterate through each li in ul

I have a calendar. Each days has the following structure to begin with.
<td>
<ul class="calendar-tasks">
</ul>
</td>
Now, I drag tasks inside the ul with the following:
$(function() {
var $tasks = $(".list-tasks"),
$calendar = $(".calendar-tasks");
$("li", $tasks).draggable({
revert: false,
helper: function (event, ui) {
return $("<div class='task-image'><span class='icon-pushpin'></span></div>");
},
cursorAt: { left: 25 },
containment: "document",
zIndex: 500
});
$("li", $calendar).draggable({
revert: false,
helper: function (event, ui) {
return $("<div class='task-image'><span class='icon-pushpin'></span></div>");
},
cursorAt: { left: 25 },
containment: "document",
zIndex: 500
});
$calendar.droppable({
accept: ".list-tasks > li, .calendar-tasks > li",
activeClass: "highlight-active",
hoverClass: "highlight-hover",
drop: function (event, ui) {
var dropped = $(this).append(ui.draggable);
var task = $(ui.draggable).attr("data-task"),
classname = $(ui.draggable).attr("data-class");
$(this).find("li").each(function() {
if ($(this).hasClass("has-task")) {
// Do nothing
} else {
$(this).find("li").append("<div data-task='" + task + "' class='listed-task " + classname + "'>#" + task + "</div>");
$(this).find("li").addClass("has-task");
}
});
}
});
$tasks.droppable({
accept: ".calendar-tasks > li",
activeClass: "highlight-active2",
hoverClass: "highlight-hover2",
drop: function (event, ui) {
$(this).append(ui.draggable);
}
});
});
Each drop is an <li></li> itself with some content in it. After each drop the li should get a class has-task. I'm kinda struggling atm to get this thing working. All is happening in the following piece of code:
$calendar.droppable({
accept: ".list-tasks > li, .calendar-tasks > li",
activeClass: "highlight-active",
hoverClass: "highlight-hover",
drop: function (event, ui) {
var dropped = $(this).append(ui.draggable);
var task = $(ui.draggable).attr("data-task"),
classname = $(ui.draggable).attr("data-class");
$(this).find("li").each(function() {
if ($(this).hasClass("has-task")) {
// Do nothing
} else {
$(this).find("li").append("<div data-task='" + task + "' class='listed-task " + classname + "'>#" + task + "</div>");
$(this).find("li").addClass("has-task");
}
});
}
});
I though that if I iterate through each <li> this will be subject to that li.
What am I doing wrong?
The first $(this).find("li").each() function iterates through each li element. By calling $(this).find("li").each again, you're referring to li elements listed in the first list of li elements: which I assume do not exist.
$(this).find("li").each(function() { //check what 'this' object is giving. }
Based on 'this' object use prev() or next() to point the li object and follow ur code as usual.

Drop on same dragged element

I want to create a jquery drag and drop like below
1) I can drag a element with the class doDrag
2) I can drop that doDrag into a div called #content
3) Also doDrag elements should be able to drop into the older doDrag divs which were dropped before into the #content div
I did it like below. But got issues.
$(".doDrag").draggable({
helper:"clone"
});
makeDroppable($("#content"));
function makeDroppable(elements) {
console.debug(elements);
$(elements).droppable({
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
drop: function (event, ui) {
var uuid = guid();
$(this).append("<div style='border:2px solid;height:50px;width:400px;' id='" + uuid + "'>Drop</div>");
makeDroppable($("#" + uuid));
return false;
}
});
}
What happened was drop event is calling multiple times.
Can anyone help me on this please
Finally found the answer.
what i had to do is add greedy:true
elements.droppable({
greedy: true,
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
drop: function (event, ui) {
console.debug($(this));
var uuid = guid();
$(this).append("<div style='border:2px solid;height:50px;width:400px;' id='" + uuid + "'>Drop</div>");
makeDroppable($("#" + uuid));
return false;
}
});

JQuery: dropped divs are sortable only after second click

When I drop some divs into a sortable pane, I can grab the newly created divs only after the second time I click on them.
I suppose this is a refresh-related issue, but I cannot figure out how to make it work.
Here is the jsfiddle: http://jsfiddle.net/DvE5Q/
And the code:
$(".box").draggable({
helper: 'clone'
});
$("#left").droppable({
accept: '.box.out',
drop: function (e, ui) {
$(this).append('<div class="box"></div>');
var droppedBox = $(this).children().last();
$(droppedBox).html(ui.helper.html());
}
});
$("#left").sortable();
Thanks for your help!
I would use the attribute connectToSortable: '#left'
DEMO http://jsfiddle.net/DvE5Q/1/
$(".box").draggable({
helper: 'clone',
connectToSortable: '#left'
});
$("#left").droppable({
accept: '.box.out',
drop: function (e, ui) {
}
});
$("#left").sortable();

JQuery - If x number of classes are detected on page, then do y

I'm making a drag-and-drop matching game for a client.
Question 1: Once all images are matched to their words, how can I make a popup appear saying "Game Over" or something similar?
Question 2: Once an image has been matched to its word, is it possible to have both the image and the word fade out of view (so the page isn't cluttered by images that have already been matched)?
Here is my Javascript:
$("#bottle, #butterfly").draggable({ revert: "invalid", containment: "#wrapper"});
$("#bottleDrop").droppable({
accept: "#bottle",
drop: function(event, ui) {
if(ui.draggable.is("#bottle")){
$(this).addClass("correct").find("p").html("correct!");
}
}
});
$("#butterflyDrop").droppable({
accept: "#butterfly",
drop: function(event, ui) {
if(ui.draggable.is("#butterfly")){
$(this).addClass("correct").find("p").html("correct!");
}
}
});
JSFiddle
Here is one way it could be done:
var done = true;
$("#bottle, #butterfly").draggable({
revert: "invalid", containment: "#wrapper",
start: function(event, ui){
if(!done)
return false;
},
stop: function(event, ui){
if($(".correct").length == $(".drop").length){
setTimeout(function(){
alert('All items have been matched!');
},2000);
}
}
});
$("#bottleDrop").droppable({
accept: "#bottle",
drop: function(event, ui) {
if(ui.draggable.is("#bottle")){
$(this).addClass("correct").find("p").html("correct!");
ui.draggable.fadeOut(2000);
$(this).fadeOut(2000);
}
}
});
$("#butterflyDrop").droppable({
accept: "#butterfly",
drop: function(event, ui) {
if(ui.draggable.is("#butterfly")){
$(this).addClass("correct").find("p").html("correct!");
done = false;
ui.draggable.fadeOut(2000);
$(this).fadeOut(2000,function(){
done = true;
});
}
}
});
Example:
http://jsfiddle.net/trevordowdle/Uf8Tq/2/

jQuery UI: Drag and clone from original div, but keep clones

I have a div, which has jQuery UI Draggable applied. What I want to do, is click and drag that, and create a clone that is kept in the dom and not removed when dropped.
Think of a deck of cards, my box element is the deck, and I want to pull cards/divs off that deck and have them laying around my page, but they would be clones of the original div. I just want to make sure that you cannot create another clone of one of the cloned divs.
I have used the following, which didn't work like I wanted:
$(".box").draggable({
axis: 'y',
containment: 'html',
start: function(event, ui) {
$(this).clone().appendTo('body');
}
});
I figured out my solution:
$(".box-clone").live('mouseover', function() {
$(this).draggable({
axis: 'y',
containment: 'html'
});
});
$(".box").draggable({
axis: 'y',
containment: 'html',
helper: 'clone'
stop: function(event, ui) {
$(ui.helper).clone(true).removeClass('box ui-draggable ui-draggable-dragging').addClass('box-clone').appendTo('body');
}
});
Here is what I finally did that worked:
$(".box-clone").live('mouseover', function() {
$(this).draggable({
axis: 'y',
containment: 'html'
});
});
$(".box").draggable({
axis: 'y',
containment: 'html',
helper: 'clone',
stop: function(event, ui) {
$(ui.helper).clone(true).removeClass('box ui-draggable ui-draggable-dragging').addClass('box-clone').appendTo('body');
}
});
If you're tring to move elements (say <li/>) from a #source <ul/> to a #destination <ul/>, and you'd like them to clone (as opposed to move), and still be sortable on the right, I found this solution:
$(function() {
$("#source li").draggable({
connectToSortable: '#destination',
helper: 'clone'
})
$("#destination").sortable();
});
I know it seems ultra simple, but it worked for me! :)
Here was his solution:
$(".box-clone").live('mouseover', function() {
$(this).draggable({
axis: 'y',
containment: 'html'
});
});
$(".box").draggable({
axis: 'y',
containment: 'html',
helper: 'clone'
stop: function(event, ui) {
$(ui.helper).clone(true).removeClass('box ui-draggable ui-draggable-dragging').addClass('box-clone').appendTo('body');
}
});
Here is how I got it working:
PS: 'marker' is the object to drag and 'map' is the destination container.
$(document).ready(function() {
//source flag whether the drag is on the marker tool template
var template = 0;
//variable index
var j = 0;
$(".marker").draggable({
helper: 'clone',
snap: '.map',
start: function(event, ui) {
//set the marker tool template
template = 1;
}
});
$(".map").droppable({
accept: ".marker",
drop: function(event, ui) {
$(this).find('.map').remove();
var item = $(ui.helper);
var objectid = item.attr('id');
//if the drag is on the marker tool template
if (template == 1) {
var cloned = $(item.clone());
cloned.attr('id', 'marker' + j++);
objectid = cloned.attr('id');
cloned.draggable({
containment: '.map',
cursor: 'move',
snap: '.map',
start: function(event, ui) {
//Reset the drag source flag
template = 0;
}
});
cloned.bind("contextmenu", function(e) {
cloned.remove();
return false;
});
$(this).append(cloned);
}
i++;
var offsetXPos = parseInt(ui.offset.left - $(this).offset().left);
var offsetYPos = parseInt(ui.offset.top - $(this).offset().top);
alert("Dragged " + objectid + " to (" + offsetXPos + "," + offsetYPos + ")");
}
});
});

Categories