Creating multiple draggable Javascript objects with individual properties - javascript

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);
}
}
});
});

Related

jQuery UI replacement for "distance" and "delay" options

According to the jQuery UI API Documentation, the "Distance" and "Delay" options are deprecated as of version 1.12. Specifically:
(#10615) Interactions should be instantaneous. These settings are typically used to prevent accidental drags, but a proper fix for that is to improve the user experience, e.g., using handles to avoid accidental drags.
I am using jQuery UI to develop an RPG map builder. Users can drag tiles from the selection area to the grid to place them, or they can click a tile to set it as the "active" tile, then click on tiles in the grid to convert them to a copy of the "active" tile. The issue I run into is that a click-and-very slight drag on a set tile will cause the tile to be removed. I feel using a handle to drag tiles that are already on the map would detract from the user experience by causing them to have to set their pointer to an even smaller area than the tile.
So my question is: What can I use in place of these functions? Would it be best to stay on an old version of jQuery UI? Would it be better to write code to mimic this functionality? Should I use a handle for items already on the grid?
I think I can do a check for if (the dragged element (ui.draggable) is the same as the drop target (event.target), but I'm having trouble coming up with the logic.
My code is located at https://codepen.io/Qumez/pen/OzvbdV. The relevant functions are setDraggableTiles() and setDroppableTiles(), below:
function setDroppableTiles() {
$("#grid .tile").droppable({
accept: ".tile",
drop: function(event, ui) {
drop(event,ui);
}
});
}
function setDraggableTiles() {
$(".tile").not("#grid .placeholder").draggable({
revert: false,
helper: "clone",
stop: function(event, ui) {
var $ele = $(event.target);
console.log($ele);
console.log($(ui.draggable));
if ($ele.hasClass("tile-set")) {
$ele
.removeClass()
.addClass("placeholder tile");
}
}
});
$("#grid .tile").not(".placeholder").addClass("tile-set");
}
Thanks in advance!

Why is jQuery clone making events not draggable onto calendar? fullcalendar

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 ;)

Change the dragged object when draggable begins

I am trying to create some thing like a UI designer. So I have a 'toolbox' and a 'canvas'. When I mark the tool box items as draggable, I am able to drag them. But what I need is to drag a copy, so that I can drag multiple instances of a tool item to the canvas.
$('.tool-box-item').draggable({
helper : 'clone',
drag : function (event, ui){
// jQuery does not allow object modification here
},
});
This does not work as the cloning is applied only while dragging and as soon as the drag is complete, the original element moves. I tried overriding the drag property, but I am unable to modify the dragged element. Same was the case with start.
Note : I can not use the stop event as I want to create the copy when the drag starts and not after it. I was also able to create a copy by defining the canvas as droppable and making a copy there, But then again I want to create a copy when the drag starts.
I think I will need to create a custom drag function but was hoping if jQuery has any other alternative way.
Here is a jsfiddle, but I want to clone the element at the start and not after the drag.
EDIT : The destination is a 3rd party control. It has its own implementation for drop event (stacking and aligning). In case I clone it at the end I will have to modify their implementation.
To keep "dragend" event, try to use original element for dragging, and clone it for place to your "toolbox".
var graggableConfig = {
helper:"clone",
stop: function(event, ui){
var clon = $(this).clone();
clon.attr("style","")
.appendTo(".src")
.draggable(graggableConfig);
$(this).detach()
.attr("style","")
.appendTo(".dst")
.draggable( "destroy" );
}
};
$(".item").draggable(graggableConfig);
codepen here
You can use jquery's clone (https://api.jquery.com/clone/) method to clone your draggable element once it is dropped. Would something like this meet your needs?
$( function() {
makeDraggable($( "#draggable" ));
});
function makeDraggable(element) {
$(element).attr('style', 'position:absolute').draggable({
start: function() {
makeDraggable($('#draggable').clone().attr('style', '').appendTo('body'));
}
});
}
Its a little rough but here is the jsbin: https://jsbin.com/tasodixoka/edit?html,output
Edit: I updated your fiddle: https://jsfiddle.net/z9rrL6po/6/

JQuery Draggable - Odd Behavior

I have a draggable element that I am creating a clone of and dragging to a drop zone. I want the draggable element to be re-draggable once it is set down in the drop zone correctly.
The odd behavior comes into play when I encapsulate the draggable div within another div. When it is encapsulated, it will not set the clone element to draggable, so I cannot re-drag the element. However, if in the jFiddle, you remove the divs from surrounding the draggable div, the thing works fine.
Working:
<div id="draggable"></div>
Not Working:
<div><div id="draggable"></div></div>
I need to know why the encapsulation is fooling around with this. It seems like it would be difficult to build a meaningful thing with a problem like this because I want to have a sidebar containing multiple draggables similar to these. Since building a sidebar requires encapsulating all these draggable elements within another div, you can see the conundrum I've happened upon.
The jFiddle links below contain the Jquery, and such.
Here is the jFiddle that doesn't work rightly: here.
And, here is the jFiddle that works correctly: here.
The only difference in the one that doesn't work: the dome class div is encapsulated by another div.
You need to remove the draggable on blah and add the draggable to the clone that is appended in the stop block.
Try this:
$(function() {
var i=1;
var indexP;
var blah
$(".dome").draggable({
revert: 'invalid',
helper: 'clone',
start: function(event, ui) {
var newId = i;
$(ui.helper).attr("id",newId);
indexP = $(ui.helper).attr('id');
blah = "#" + indexP;
},
stop: function(event, ui) {
$(ui.helper).append("<br><span>"+blah+"</span>");
$(ui.helper).clone().appendTo('#cont').draggable();
i++;
},
});
$("#cont").droppable({
});
});
function updateStatus (x,y,i) {
var xPos = "#x" + i;
var yPos = "#y" + i;
$(xPos).text(x);
$(yPos).text(y);
}

JQuery UI: Cancel Sortable upon Droppable Drop

I am using JQuery 1.5.1 and JQuery UI 1.8.11.
I have added sortable for a number of items - the task here is to allow drag to sort, this all works fine.
But I also want to incorporate droppable, so that the item can be dropped onto a "copy me" area - the task there will be to duplicate the item (I will work that bit out later)
Problem is the droppable target is at the bottom of the sortable list (I do not want to move this) and once the drop occurs the sortable item moves to the bottom of the list.
What I want to do is cancel this sort when the drop event fires.
You can see my problem in action here (just drag "Item 1" onto the "Drop to Copy Item" area and you will see the sort does not get cancelled)
As you can see I have tried the following in the droppable "drop" event (suggested from JQuery UI Docs) but it does not seem to work...
$(this).sortable('cancel');
I am also open to any other recommendations on how to achieve this "drop to copy" effect I am looking for.
Thanks
OK, so I have worked out a solution which does the job.
the cancel code does work if you have it in the "stop" event of the sortable function. However, it will only apply once the "revert" has completed. The problem is that I was trying to copy/revert the element from the droppable "drop" event and this was too early.
The solution is to wait for the "stop" event to complete, and to achieve this I had to create a "awaiting copy" flag, to be checked in the "stop" event.
Here is an example
It still doesn't feel right (UX-wise) but it works correct, and you could always set revert to false on the sortable function to get a slightly better feel.
The code from the example is as follows...
var itemCount = 3;
var awaitingCopy = false;
$(init);
function init() {
$("#Items").sortable({
revert: true,
placeholder: "ItemPlaceHolder",
opacity: 0.6,
start: StartDrag,
stop: StopDrag
});
$("#CopyItem").droppable({
hoverClass: "CopyItemActive",
drop: function(event, ui) {
awaitingCopy = true;
}
});
$("#NewItem").click(function(e) {
e.preventDefault();
itemCount++;
var element = $("<div class='Item'>Item " + itemCount + "</div>");
$("#Items").append(element);
element.hide().slideDown(500);
});
}
function CopyItem(element) {
awaitingCopy = false;
var clone = element.clone();
$("#Items").append(clone);
clone.hide().slideDown(500);
}
function StartDrag() {
$("#NewItem").hide();
$("#CopyItem").show();
}
function StopDrag(event, ui) {
if (awaitingCopy) {
$(this).sortable('cancel');
CopyItem($(ui.item));
}
$("#NewItem").show();
$("#CopyItem").hide();
}
Anyway, hopefully this will help others who want the same kind of effect... no stealing my design though ;)

Categories

Resources