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.
Related
I am trying to make the list items (cards) sortable, but for usability improvements I want to show the user an placeholder on the old (with text "FROM") and one on the new (with text "TO") before user releases mouse (ends .sortable).
helper: 'clone',
placeholder: {
element: function(currentItem) {
return $('<li class="placeholder">FROM or TO</li>')[0];
},
update: function(container, p) {
return;
},
}
right above, you see what I have for now, but is it possible to split "FROM" and "TO"?
I made it myself. Was quite complicated to introduce a second "placeholder" on old position. See here:
If you move an li, you now have an "FROM"-Container at old-pos and and "TO"-Container on future-pos, wich will be removed after positioning.
$(function() {
var oldList, newList, item;
$(".selector").sortable({
start: function(event, ui) {
item = ui.item;
newList = oldList = ui.item.parent().parent();
var activeElem = item.index();
$(this).children().eq(activeElem).after('<li class="placeholder">From</li>');
},
stop: function(event, ui) {
//alert("Moved " + item.text() + " from " + oldList.attr('id') + " to " + newList.attr('id'));
$(".selector > li").remove(".placeholder");
},
change: function(event, ui) {
if(ui.sender) newList = ui.placeholder.parent().parent();
},
connectWith: ".selector",
helper: 'clone',
placeholder: {
element: function(currentItem) {
return $('<li class="placeholder">To</li>')[0];
},
update: function(container, p) {
return;
}
}
}).disableSelection();
});
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());
}
});
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;
}
});
$("li").draggable({
helper: "clone"
});
$("#div1").droppable({
drop: function (event, ui) {
$("<p></p>").appendTo("#div1");
}
});
I have objects in a list that can be dragged and dropped into a div named div1. But when I drop one into the div i don't want to be able to drop another into it. I have tried using, for, if and while loops with a count.
Here is a full solution, it allows only one item dropped, but also, if one exists, it gets replaced on the next drop with the new one. (Usefull if someone changes their mind. Just call
refreshDragDrop(dragClassName,dropDivId);
refreshDragDrop = function(dragClassName,dropDivId) {
$( "." + dragClassName ).draggable({
connectToSortable: "#" + dropDivId,
helper: "clone",
revert: "invalid"
});
$("#" + dropDivId).droppable({
accept: '.' + dragClassName,
drop: function (event, ui) {
var $this = $(this),
maxItemsCount = 1;
if ($this.children('div').length == maxItemsCount ){
//more than one item,just replace
$(this).html($(ui.draggable).clone());
} else {
$(this).append($(ui.draggable).clone());
}
}
});
}
This should help:
drop: function (event, ui) {
var $this = $(this),
maxItemsCount = 1;
if ($this.children('li').length > maxItemsCount ){
ui.sender.draggable('cancel');
alert("To much items!");
}
}
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 + ")");
}
});
});