I want do edit the nesting of fullcalendar.io Resources with drag & drop. Is there any posibility to do so.
My approach:
resourceRender: function(resource, cellEls) {
cellEls.draggable({ handle: ".icon-resize-vertical",
revert: true,
helper: "clone",
zIndex: 999,
snap: true,
opacity: 0.7
});
cellEls.droppable({
hoverClass: "ui-state-active",
drop: function( event, ui ) {
$( this ).css( "font-weight", "bolder" );
var childid = $(ui.draggable).closest("tr").attr("data-resource-id");
var childEl = $("#calendar").fullCalendar( 'getResourceById', childid );
var parentid = $( this ).closest("tr").attr("data-resource-id");
var parentEl = $("#calendar").fullCalendar( 'getResourceById', parentid );
childEl.parent = parentEl;
parentEl.children.push(childEl);
$('#calendar').fullCalendar('destroy');
$('#calendar').fullCalendar('render');
}
});
},
The resource-objects show correct children and parent, but the calendar does not rerender.
If you destroy the calendar, your changes will be lost.
At the end of drag&drop, call
$('#calendar').fullCalendar('refetchEvents');
Related
Ok, I have an issue with drag and drop.
What they do, they click a button, it initializes the whole drag and drop.
function sortElements() {
// Place droppable elements
var x = 0;
$("#content-body div[data-type='column'],#content-body div[data-type='carousel']").each(function() {
var el = $(this);
if(x == 0){
el.before('<div class="neoDroppableEle" id="neoDroppableEle-' + x + '"><\/div>');
x++;
}
el.addClass('edit_el').after('<div class="neoDroppableEle" id="neoDroppableEle-' + x + '"><\/div>');
x++;
el.append('<div class="drag-handle"><i class="fa fa-arrows"></i></div>');
var w = el.width();
el.css('width',w+'px');
});
$("#content-body div[data-type='insertable']").each(function() {
var el = $(this);
el.prepend('<div class="neoDroppableEle" id="neoDroppableEle-' + x + '"><\/div>');
x++;
});
// Swap entire columns
$("#content-body div[data-type='column']").draggable({
refreshPositions: true,
helper: "clone",
handle:'.drag-handle',
appendTo: "body",
zIndex: 10000,
start: function( event, ui ) {
$(".neoDroppableEle").addClass('dragging');
},
stop: function( event, ui ) {
$(".neoDroppableEle").removeClass('dragging');
}
});
$(".neoDroppableEle").droppable({
accept: "div[data-type='column']",
tolerance: "pointer",
hoverClass: "focus_in",
activeClass: "focus_in_active",
drop: function(event, ui) {
cur_ele = this.id;
var el = ui.draggable;
var html = el.html();
el.remove();
$("#" + cur_ele).replaceWith('<div class="row" data-type="column">'+html+'</div>');
}
});
// Swap individual photos within columns
$("#content-body div[data-type='imagewrap']").each(function(){
$(this).draggable({
revert: "invalid",
helper: "clone" ,
zIndex: 10001,
});
$(this).droppable({
accept: "div[data-type='imagewrap']",
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
drop: function( event, ui ) {
var draggable = ui.draggable, droppable = $(this);
draggable.swap(droppable);
}
});
});
}
When they are done, they click the button again.
function sortElementsComplete() {
$(".ui-droppable").droppable("destroy");
$(".ui-draggable").draggable("destroy");
$(".edit_el").removeAttr('style').removeClass('edit_el');
$(".neoDroppableEle").remove();
$(".drag-handle").remove();
}
This all runs and works great!
But now I am tryng to save the HTML code after each drop for undo's. And when I save the undo, I need to remove all additional classes and elements my function to drag and drop add's. Because they may not be in the sorting area when they click undo and do not want drag handles and my borders I set up as visual aids just appearing.
So now I have:
$(".neoDroppableEle").droppable({
accept: "div[data-type='column']",
tolerance: "pointer",
hoverClass: "focus_in",
activeClass: "focus_in_active",
drop: function(event, ui) {
cur_ele = this.id;
var el = ui.draggable;
var html = el.html();
el.remove();
$("#" + cur_ele).replaceWith('<div class="row" data-type="column">'+html+'</div>');
setTimeout(function(){
sortElementsComplete();
editor_add();
},1000);
}
});
The above with the timeout code always fails with:
Error: cannot call methods on droppable prior to initialization;
attempted to call method 'destroy'
How so? It IS initialized and running. After the drop I should be able to destroy it, make my save and rebuild it. Using disable gives the same error. To me the error makes no sense.
After editor_add() is ran, it re-builds whatever they were doing, in this case it will fire sortElements(); after the save.
But the below runs fine?
// Swap individual photos within columns
$(this).droppable({
accept: "div[data-type='imagewrap']",
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
drop: function( event, ui ) {
var draggable = ui.draggable, droppable = $(this);
draggable.swap(droppable);
setTimeout(function(){
sortElementsComplete();
editor_add();
},250);
}
});
It will error if I do not have the timeout above. Seems 250 is the min, anything lower it errors. But the first one will not ever work, no matter how long or short I make the timeout.
Really hope this makes sense.
Maybe if I used
var draggable = ui.draggable, droppable = $(this);
draggable.swap(droppable);
On it instead it would work. o.O
I'm building some sort of a playlist creator. I have some items the user can choose from and a horizontal sortable timeline area to drop those items on.
The Draggable:
$(".Name:not(#Add a .Name)").draggable({
revert: 'invalid',
start: function(){
$('#MainPage').css('cursor', '-moz-grabbing');
$(".Name").css('cursor', '-moz-grabbing');
},
// helper: "clone",
helper: function() {
return $("<div class='"+$(this).parent().attr('class')+"' id='"+$(this).parent().attr('id')+"'><div class='"+$(this).attr("class")+"' id='"+$(this).attr("id")+"'>"+ $(this).attr("class").split(' ')[1] +"</div></div>");
},
stop: function() {
$('#MainPage').css('cursor', 'auto');
$(".Name").css('cursor', '-moz-grab');
},
connectToSortable: "#TimelineDrop",
appendTo: '#MainPage',
containment: 'DOM',
zIndex: 800,
addClasses: false
});
The Sortable:
$("#TimelineDrop").sortable({
over: function(event, ui) {
var Breite = ((TimeSpace*5)/(TimeSpace/(currentspacing+24)))-2;
$("#TimelineDrop").append("<div class='TimelineMarker' style='width:"+ Breite +"px;'>\u00A0</div>");
},
receive: function(event, ui) {
dropped=true;
AddElementToTimeline($(this), event, ui, dropped);
},
start: function( event, ui ){
$('#MainPage').css('cursor', '-moz-grabbing');
$('.TimelineElement').css('cursor', '-moz-grabbing');
drag=true;
},
axis: "x",
stop: function( event, ui ){
$('#MainPage').css('cursor', 'auto');
$('.TimelineElement').css('cursor', '-moz-grab');
database.updateElementPosition($('.TimelineElement').index($(ui.item)), $(ui.item).children('.TimelineElementTitle').attr('id').split('D')[1], GET('id'));
drag=false;
}
});
I tried all kinds of different stuff but can't get it to work propperly. What would like to be able to is drag items from the available area to the timeline und drop them between allready appended ones. So far the helper allways get appended (vertically) above the existing elements and when I drop it the final element get append at the very last position. I hope It's clear what I'm trying to archive...
I have a fiddle right here:
http://jsfiddle.net/5SBax/4/
I want the marker to be displayed where the element will be added (between others). And I need to get rid of the helper element which also get added every time...
Take a look at this fiddle. I'm not quite sure what you are asking, but this is a good example of drag and drop capabilities. I can't comment, and I am not quite sure what you are asking. But best of luck to you!
http://jsfiddle.net/cuhuak/4CHDZ/
function FieldType(typeName, name) {
var self = this;
self.TypeName = ko.observable(typeName || "");
self.Name = ko.observable(name || this.TypeName());
self.createField = function () {
return new Field(
{
Name: this.Name(),
TypeName: this.TypeName()
}
);
}
self.onDragStart = function(event, ui) {
dropFieldType = ko.utils.domData.get(this, "ko_drag_data");
};
self.onDragStop = function(event, ui) {
dropFieldType = null;
};
}
Demo: http://jsfiddle.net/py3DE/
$(".source .item").draggable({ revert: "invalid", appendTo: 'body', helper: 'clone',
start: function(ev, ui){ ui.helper.width($(this).width()); } // ensure helper width
});
$(".target .empty").droppable({ tolerance: 'pointer', hoverClass: 'highlight',
drop: function(ev, ui){
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) item = item.clone().draggable();// if item was dragged from the source list - clone it
this.innerHTML = ''; // clean the placeholder
item.css({ top: 0, left: 0 }).appendTo(this); // append item to placeholder
}
});
$(".target").on('click', '.closer', function(){
var item = $(this).closest('.item');
item.fadeTo(200, 0, function(){ item.remove(); })
});
My goal here is when an item is taken from .source and dropped on to .target, I want to disable the draggable that was dropped so that I can only have a single instance of an item from .source end up in .target. Conversely, I am also trying to re-enable the item once it is removed from .target.
Given that your creating a clone of the original you need to track this and be able to tie back to the original when you close the clone.
var mapOrig = [];
$(".source .item:not(.added)").draggable({ revert: "invalid", appendTo: 'body', helper: 'clone',
start: function(ev, ui){ ui.helper.width($(this).width()); } // ensure helper width
});
$(".target .empty").droppable({ tolerance: 'pointer', hoverClass: 'highlight',
drop: function(ev, ui){
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) {
var orig = item;
item = item.clone().draggable();// if item was dragged from the source list - clone it
orig.draggable('disable');
mapOrig.push({item: item, orig: orig});
}
this.innerHTML = ''; // clean the placeholder
item.css({ top: 0, left: 0 }).appendTo(this); // append item to placeholder
}
});
$(".target").on('click', '.closer', function(){
var item = $(this).closest('.item');
for(var i = 0; i < mapOrig.length; ++i){
if(item.is(mapOrig[i].item)){
mapOrig[i].orig.draggable('enable');
mapOrig.splice(i, 1);
}
}
item.fadeTo(200, 0, function(){ item.remove(); })
});
I've created an updated fiddle at http://jsfiddle.net/xmltechgeek/FCj2a/ that show a way to do this using a tracking array for your old item when you create the clone. You can just use the enable/disable functionality from jquery for the actual task of enabling or disabling.
use this code inside droppable -
deactivate: function( event, ui ) {
var item = ui.draggable;
item.draggable('disable');
}
Demo Fiddle
Edit: I'd still like to know the answer to this question for knowledge's sake. I managed to get a similar effect to what I want using the out event on a drop event though.
I have a working drag and drop that will record which box an image has been placed in. However, when I created a drag event to account for the fact a user removes an image from the box it breaks the drag and drop causing the images to be undraggable.
The only difference between the two code sections below is the latter has the addition of
start: handleDragEvent and it's associated function to write "Moved".
Code Works:
function init() {
$('#ImageE1, #ImageE2, #ImageE3').draggable({ containment: '#ForDualScreen', cursor: 'move', zIndex: 20000, handle: 'img'});
$('#BoxE1, #BoxE2, #BoxE3, #BoxE4, #BoxE5, #BoxE6, #BoxE7, #BoxE8, #BoxE9, #BoxE10, #BoxE11, #BoxE12, #BoxE13, #BoxE14, #BoxE15').droppable( {
drop: handleDropEvent
} );
}
function handleDropEvent( event, ui ) {
var draggable = ui.draggable;
var draggableId = ui.draggable.attr("id") + 'PLACE';
var droppableId = $(this).attr("id");
alert( 'BLARGH "' + draggableId + '" was dropped onto me!' + droppableId );
document.getElementById(draggableId).value = droppableId;
}
Code no longer works:
function init() {
$('#ImageE1, #ImageE2, #ImageE3').draggable({ containment: '#ForDualScreen', cursor: 'move', zIndex: 20000, handle: 'img', start: handleDragEvent});
$('#BoxE1, #BoxE2, #BoxE3, #BoxE4, #BoxE5, #BoxE6, #BoxE7, #BoxE8, #BoxE9, #BoxE10, #BoxE11, #BoxE12, #BoxE13, #BoxE14, #BoxE15').droppable( {
drop: handleDropEvent
} );
}
function handleDragEvent( event, ui ) {
var draggable = ui.draggable;
var draggableId = ui.draggable.attr("id") + 'PLACE';
document.getElementById(draggableId).value = "Moved";
}
function handleDropEvent( event, ui ) {
var draggable = ui.draggable;
var draggableId = ui.draggable.attr("id") + 'PLACE';
var droppableId = $(this).attr("id");
alert( 'BLARGH "' + draggableId + '" was dropped onto me!' + droppableId );
document.getElementById(draggableId).value = droppableId;
}
You need to pass in the event and ui parameters to your handleDragEvent() and handleDropEvent() functions.
function init() {
$('#ImageE1, #ImageE2, #ImageE3').draggable({ containment: '#ForDualScreen', cursor: 'move', zIndex: 20000, handle: 'img', start: handleDragEvent});
$('#BoxE1, #BoxE2, #BoxE3, #BoxE4, #BoxE5, #BoxE6, #BoxE7, #BoxE8, #BoxE9, #BoxE10, #BoxE11, #BoxE12, #BoxE13, #BoxE14, #BoxE15').droppable( {
drop: function(event, ui) { handleDropEvent(event, ui); }
});
}
I have 2 draggable DIVs that that i want stacked depending on where in the parent DIV they are located. I tried to set z-index, while this works in IE 9, I cannot get it to work in Firefox 4.
Using Firebug I see that the dragged elements has z-index set to auto.
Full demo of what I want to accomplish at http://jsfiddle.net/a5jgm/6/
Thank you for your time
$( ".draggable" ).draggable({
// zIndex: 5,
start: function(event, ui) {
// console.log(this);
var zIndex = $(this).draggable( "option", "zIndex" );
$('#zindex').val(zIndex);
// $( this ).draggable( "option", "zIndex", 100 );
},
drag: function( event, ui ) {
var pos = $( "#"+this.id).position();
$( "#offset" ).val( ""+pos.left +" "+pos.top );
},
stop: function(event, ui){
console.log(this);
if(ui.offset.left > 220){
var currentz = parseInt( $('#zindex').val() )+1;
$( this ).draggable( "option", "zIndex", currentz);
$('#zindex').val(currentz);
console.log(' z index is: '+$(this).draggable( "option", "zIndex" ));
}
}
});
var i = 10;
$( ".draggable").each(function(){
i = i +1;
$( this ).draggable( "option", "zIndex", i );
});
Try setting the position attribute as well. Set it to relative, absolute etc whichever is appropriate as per your implementation. That might probably solve the issue.