I have added another div for external events in my FullCalendar implementation and the idea is to have this div storing favourites for later use if the user wish to (to visually illustrate the idea --> http://imgur.com/a/qZbWj). Im successfully able to drag and drop events from the first div to the second and i'm also able to drag them from div2 but NOT onto the calendar for some reason:
// 2nd div droppable setting
$('#external-events-fav').droppable( {
accept: '#external-events .fc-event',
drop: function (event, ui) {
var droppable = $(this);
var clone = ui.draggable.clone();
clone.draggable({ // clone element then make it draggable
helper: 'clone',
appendTo: 'body',
scroll: false,
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0
}).appendTo(droppable);
}
});
If I don't make the ui.draggable.clone() call, I'm able to drag the event from the new div to the calendar but i want to make a clone, so I can have the event appearing in both divs. Creating the clone using jQuery clone() makes it undraggable onto the calendar however for unknown reasons. Anyone know why? I have tried clone(true) and clone(true,true) but this didnt help the situation either.
fiddle: http://jsfiddle.net/a3q9c5tr/37
still need help with this :(
According to your comments I am assuming your problem description is as follows:
The cloned object is draggable (you can click and drag it around your
page) but not droppable onto the calendar (when you lift your finger
over the calendar the object goes back to its original position or it's simply not recorded as dropped).
If that's the case, my first guess it that the cloned object does not match the droppable accept selector. Is your cloned object inside #external-events and does it have the class fc-event?
If it does, you probably have to append it to the right place of the DOM before calling the draggable function on it. Try it like this:
$('#external-events-fav').droppable( {
accept: '#external-events .fc-event',
drop: function (event, ui) {
var clone = ui.draggable.clone();
clone.appendTo(this);
clone.draggable({ // clone element then make it draggable
helper: 'clone',
scroll: false,
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0
});
}
});
I found the solution to the problem. jQUery clone() function does not copy over the data attributes set by jQuery data('event', {}) function so i had to do this again for the clone in order to make it work, so therefore:
$('#external-events-fav').droppable( {
accept: '#external-events .fc-event',
drop: function (event, ui) {
var droppable = $(this);
var clone = ui.draggable.clone();
clone.data('event' {
title : ui.draggable.attr("name"),
// INSERT MORE ATTR HERE
});
clone.data('duration',ui.draggable.attr('duration'));
clone.draggable({ // clone element then make it draggable
helper: 'clone',
appendTo: 'body',
scroll: false,
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0
}).appendTo(droppable);
}
});
Hope this might help anyone ;)
Related
I am trying to create draggable objects that have each have their own properties. I am a beginner at Javascript with very minimal experience, and this is for a project that involves creating a simple circuit simulator.
So far, I have been able to drag, drop & clone components in a DOM courtesy of some very helpful stackoverflow-ers. But I am struggling to move on to the next bit, which is making each component unique, with editable properties such as name, type and coordinates, so that when I click on that object again, I can pull up something like a little pop-up menu that allows me to modify the properties of that specific object.
Would anyone be able to offer any pointers of how to go about doing it?
Here is the jsfiddle of what I have so far - http://jsfiddle.net/3Lnqocf3/
Any help is very much appreciated!
Javascript -
jQuery(function() {
jQuery(".component").draggable({
// use a helper-clone that is append to 'body' so is not 'contained' by a pane
helper: function() {
return jQuery(this).clone().appendTo('body').css({
'zIndex': 5
});
},
cursor: 'move',
containment: "document"
});
jQuery('.ui-layout-center').droppable({
activeClass: 'ui-state-hover',
accept: '.component',
drop: function(e, ui) {
if (!ui.draggable.hasClass("dropped")) {
var parentOffset = jQuery('.ui-layout-center').offset();
var dropped = jQuery(ui.draggable).clone().addClass("dropped").draggable();
dropped.css('left', (ui.position.left - parentOffset.left) +'px');
dropped.css('top', (ui.position.top - parentOffset.top) +'px');
jQuery(this).append(dropped);
}
}
});
});
I have a "draggable only" block where I have some images and another "sortable only" block where I can drop the items from the "draggable only".
What I want to do is when I drag the image into "sortable only" to append the larger version of the dragged image which is hosted on my server.
I think this can be relatively easy to do if there is a way to check when the item is dragged into the sortable list and then append the new image.
This is the actual JS :
$(document).ready(function () {
$(".sortableList").sortable({
revert: true,
/*update: function (event, ui) {
// Some code to prevent duplicates
}*/
});
$(".draggable").draggable({
connectToSortable: '.sortableList',
cursor: 'pointer',
helper: 'clone',
revert: 'invalid'
});
});
Here is a jsfiddle with what I currently have:
(Hover over the "Headers" and there you should drag an image into "HOVER OVER HEADERS AND DROP IMAGES HERE" block)
I've looked trhrough the plugin API but I can't find a way to track when the item was dragged into the sortable area ?
Any suggesions on how can I do this ?
If I understand what you're shooting for, a receive function on your sortable list should work.
Working Example
$(".sortableList").sortable({
receive: function (event, ui) {
alert('It works');
}
});
The documentation says:
This event is triggered when an item from a connected sortable list
has been dropped into another list. The latter is the event target.
But apparently it will also fire when using a connected draggable.
I was looking the jQuery UI API and found this:
$( "#sortable li" ).droppable({
drop: function( ) {
//do the magic
}
});
I have a draggable element using jQuery UI, and have a function attached the drag event that gets continuously called with the element's position while the user is dragging it.
I also have revert: true set on this element, so when the user stops dragging the element springs back to its original position. Is there a way I can attach a listener to perform the same functionality as when it's being manually moved?
I can't see anything specifically related to the revert property in the docs, so if that's not possible is there a more general event called while an element is moving?
Thanks!
It appears there's nothing in the API for this, so I've had to hack it using setInterval.
var revertInterval;
var revertEvent = function(el) {
revertInterval = setInterval(function() {
// Do things
// e.g. console.log(el.position().top);
}, 5);
}
$('#draggable').draggable({
revert: function() {
revertEvent($(this));
return true;
},
stop: function() {
clearInterval(revertInterval);
}
});
the revert is accept function as follow
revert: function(param){}
DEMO
I am trying to setup somme kind of drag and drop wysiwyg editor using JQuery UI.
I have succesfully setup the elements but they have a strange behavior.
It is almost impossible to sort items because of the constant flickering.
i setup my draggables like this:
el.draggable({
containement:'.main-form-container',
revert: "invalid",
connectToSortable: '.sortable'
}).disableSelection();
If i dont set it as draggable the sortable will place the placeholder on itself! why?
Sometimes when an element is dropped into another it becomes ONE draggable element and seem tobe glued together. though that seems fixed with overriding sortable update:
update: function (event, ui) {
$(ui.item).css({
position: 'relative',
top:0,
left:0,
width: 'auto'
});
// init droppable draggable and sortable on this item
setupDandD($(ui.item));
}
and the setupDandD method:
setupDandD($('.form-container'));
function setupDandD(el) {
el.draggable({
containement:'.main-form-container',
revert: "invalid",
connectToSortable: '.sortable'
}).disableSelection();
el.droppable({
accept: '[data-section="toolbox"]',
greedy: true,
hoverClass: 'droppable-hovered',
drop: handleDrop
}).disableSelection();
el.filter('.sortable').sortable({
tolerance:'pointer',
containement:'.main-form-container',
connectWith: ".sortable:not(#" + $(this).id + ")",
revert: 'invalid',
helper: function () {
return $(this);
},
update: function (event, ui) {
console.log('here');
$(ui.item).css({
position: 'relative',
top:0,
left:0,
width: 'auto'
});
setupDandD($(ui.item));
}
}).disableSelection();
};
I guess I need to pickup some event somewhere on the sortable but i am quite lost now...
Well well! I found it!
Actually my biggest mistake was to mix droppable and sortable at the same time. I just had to use sortables and draggables with the connectToSortable option set.
The other weird behavior I had was the sortable trying to insert into itself. This is because sortable "connectWith" was set to a selector that returned self and therefor it instantly placed the placeholder on self when dragged. Quite logical actually!
To overcome this I just surrounded each child sortable with a div. It makes the div a sortable item and prevents triggering the events on self.
One thing to take into consideration when using draggable+sortable is that the sortable will always clone the object as it was when drag started. Meaning that even if you use a custom helper on the draggable, it will still insert the original item. For this I had to replace the item in the "stop" event of the sortable by the one i wanted if it came from my toolbox:
$('.main-form-container').sortable({
placeholder: "sortable-placeholder",
opacity: .35,
connectWith: ".sortable",
stop: function (e, t) {
if (t.item.attr('data-section') == "toolbox") {
$(t.item).replaceWith(createContainer());
}
$(".sortable").sortable({
opacity: .35,
placeholder: "sortable-placeholder",
connectWith: ".sortable"
}).disableSelection();
}
}).disableSelection();
and here is the working fiddle: http://jsfiddle.net/jmorvan/ag659/
I realize there is probably a cleaner way of doing this last fix by overriding some maybe undocumented event in sortable/draggable, but that did the trick for me!
I have an element I want to allow to be dragged anywhere. However, if it is dropped onto a droppable which refuses it (via accept) I want it to revert to the original position before the drag. How can I accomplish this?
EDIT: to be more specific: I want two conditions to be met in order for the item to be moved back: 1. It was dropped on a droppable and 2. The droppable didnt accept said item. Draggable's revert option only checks condition 2.
I have some code which I think should work. Note that it doesn't use the accept option to specify which draggables the droppables will accept. Instead, you'll have to check whether or not a draggable should be rejected manually, in the drop event.
$(document).ready(function() {
$('.droppable-class').droppable({
drop: function(event, ui) {
// check whether or not draggable should be rejected here...
if (...) {
ui.draggable.data('rejected', true);
}
}
});
$('.draggable-class').draggable({
revert: false,
start: function(event, ui) {
ui.helper.data('rejected', false);
ui.helper.data('original-position', ui.helper.offset());
},
stop: function(event, ui) {
if (ui.helper.data('rejected') === true) {
ui.helper.offset(ui.helper.data('original-position'));
}
}
});
You want to use sortable dude - something like:
$('#sortable-area').sortable({
accept: '.child',
items: '.child',
revert: 300,
opacity: 0.8,
containment: 'document'
});
This should automatically snap the element back if it isn't far enough to replace one of the other elements. You just put this on the container