Even if only one icon from my draggable box is dropped into the droppable area, I would like a hidden button to appear.
I am unsure if I could reference the css class I used to hide it or have the JavaScript generate the button.
This button will be needed later for an onClick event for a modal box.
Any help would be appreciated. :)
jsfiddle to look at http://jsfiddle.net/JeLZr/4/
The code below is what I am having issues with.
if ($(this).find('.draggable').length === 0) {
$(this).append($(ui.draggable));
if($(ui.draggable).find('button.generateReport').length === 0){
$(ui.draggable).append('<input type="button" id="generateReport" class="BtnReport" />');
}
}
[edit] I realize this is a lot of to ask but is there any chance anyone can help with; as well as dragging the icon, if it is double clicked it will move into the droppable box?? Is this even possible with draggable/droppable??
An attempt to answer the first question:
$("#drop").droppable({
accept: ".draggable",
drop: function (event, ui) {
$('.BtnReport').show();
console.log("drop");
$(this).addClass("over");
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({
top: 0,
left: 0
}).appendTo(droppedOn);
},
over: function (event, elem) {
$(this).addClass("over");
console.log("over");
},
out: function (event, elem) {
$(this).removeClass("over");
}
});
$("#drop").sortable();
$("#grid").droppable({
accept: ".draggable",
drop: function (event, ui) {
if($('#drop img').length == 1)
$('.BtnReport').hide();
console.log("drop");
$(this).removeClass("over");
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({
top: 0,
left: 0
}).appendTo(droppedOn);
http://jsfiddle.net/trevordowdle/JeLZr/5/
I can look into the second question as well but it might be best to Create another question for it.
Related
I'm trying to drag "templates" (initially as clones) from a "store" into droppable slots. Thereafter I want to be able to drop the dragged item into whatever slot I wish. Draggables are set as follows:
$( ".template" ).draggable({
helper: "clone",
}
);
$( ".item" ).draggable();
I got round the issue of the thing re-cloning by replacing the "template" class with an "item" class on first drop and within the drop function switching from a clone to a straight element as follows:
$( ".template-slot" ).droppable({
accept: ".template, .item",
drop: function( event, ui ) {
if(ui.draggable.hasClass("template")) {
$(this).append(ui.draggable.clone())
// add item class
$(".template-slot .template").addClass("item");
// remove template class
$(".item").removeClass("ui-draggable template");
// expand to fit the slot
$(".item").addClass("expand-to-slot");
// make it draggable again
$(".item").draggable();
}
if(ui.draggable.hasClass("item")) {
$(this).append(ui.draggable);
}
}
});
The first drag and drop works okay. the problem arises on the second drag and drop. The element drags okay but when dropped it gets placed twice as far in whatever direction I drag it. So, for example, if I've dragged it 50px to the right, it drops 100px to the right. the same with up and down etc.
I suspect it's something to do with the offset being cumulative but haven't worked out why it's doing this or how to fix it.
I've created a fiddle here: https://jsfiddle.net/stefem1969/a86jmnxu/10/ to show the problem.
Hope someone can help.
Working Example: https://jsfiddle.net/Twisty/fu83zq2y/11/
JavaScript
$(function() {
function makeDrag(obj, opt) {
if (obj.hasClass("ui-draggable")) {
obj.removeClass("ui-draggable");
obj.attr("style", "");
}
if (opt === undefined) {
opt = {};
}
obj.draggable(opt);
}
makeDrag($(".template, .item"), {
helper: "clone",
});
$(".template-slot").droppable({
accept: ".template, .item",
drop: function(event, ui) {
if (ui.draggable.hasClass("template")) {
console.log("it has the template class!");
var newItem = ui.draggable.clone();
newItem.toggleClass("template item");
newItem.addClass("expand-to-slot");
newItem.appendTo($(this));
makeDrag(newItem);
}
if (ui.draggable.hasClass("item")) {
console.log("it has the item class!")
var droppableOffset = $(this).offset();
console.log("droppableOffset: ", droppableOffset);
ui.draggable.attr("style", "").appendTo($(this));
}
}
});
$(".template-store, .thagomizer").droppable({
accept: ".item",
drop: function(event, ui) {
ui.draggable.remove();
}
});
});
Part of draggable is to set a top and left when moving it around. Even if you append the item to another element, it will still have those. Clearing that can help accomplish what you're looking for.
The makeDrag() is just helpful to perform the same operations a lot.
Hope this helps.
On this script I have drag and drop fieldsets (left menu - top). Drag multiple fieldsets into the right "working area". In those fieldsets is an area for dropping Fields (of which I have one, left menu - bottom). Drop "Field One" into any of the dropped Fieldset (under the line in the "Drop Fields Here" area) in the working area.
I want to then move that Field One from the Fieldset I dropped it into and into the other Fieldset in the working area. I have got the Field One draggable but I cannot get it to append to the new Fieldset.
I am not wanting to delete the Field and replace it with another clone from the left menu. I am new to jquery so my code may be a bit messy. Any help is greatly appreciated. Jsfiddle and code below.
I believe the code issue is between line 21-29...but I am not sure.
JsFiddle Link
$(document).ready(function() {
var fs_count = 0;
$("#drop-area").droppable({
accept: '.ui-draggable:not(.draggableField , .activeField)',
drop: function(event, ui) {
fs_count++;
var clone = $(ui.draggable).clone()
clone.addClass('.connectedSortable')
// clone.removeClass('.ui-draggable');
if (clone.hasClass('dropped')) {
return false;
}
clone.addClass('.connectedSortable').addClass('dropped').attr('id', 'fs_' + fs_count);
$(this).append(clone);
var fs_class = clone.attr('class');
alert('You added a field with class ' + fs_class);
var fieldsDroppable = $('#drop-area .ui-draggable:last-child .fieldDroppable');
fieldsDroppable.droppable({
accept: '.draggableField , .activeField',
drop: function(event, ui) {
var clone = $(ui.draggable).clone();
if (clone.hasClass('draggableField')) { // If else to prevent clones reproducing in Fieldsets when moving from original Fieldset.
clone.removeClass('ui-draggable , draggableField').addClass('activeField');
$(this).append(clone);
}
else {
// Append the div here?
}
var cloneClass = clone.attr('class'); // Temporary varialble for develpoment alert below
alert('you dropped a field' + cloneClass); // Temporary for development only
// Below re-register the "field" with jquery....not sure this is entirely correct.
var fieldsDraggable = $('#drop-area .ui-draggable .fieldDroppable .activeField');
fieldsDraggable.draggable();
}});
} });
$(".fieldDroppable").droppable({
accept: '.draggableField , .activeField',
drop: function(event, ui) {
var clone = $(ui.draggable).clone()
$(this).append(clone);
}
});
$(".ui-draggable").draggable({
opacity: 1.0,
helper: 'clone',
revert: 'invalid'
});
$(".draggableField").draggable({
opacity: 1.0,
helper: 'clone',
revert: 'false'
});
$(".activeField").draggable();
$("#drop-area").sortable({
handle: '.drag-handle',
update: function () { //triggered when sorting stopped
var dataAuto = $("#drop-area").sortable("serialize", {
key: "za",
attribute: "id",
});
alert(dataAuto);
}
});
$("#drop-area").disableSelection();
});
There will be a lot of work to do here, yet you can get over this hurdle like so:
https://jsfiddle.net/Twisty/6trmrfoo/32/
Basically, you want to assign a new .droppable() to a specific element in the field set when it is added to the #drop-area. I would advise using a function as you will do this a multitude of times.
You can also make use of .data() to store a source value along with the draggable elements. I only did this for fields since that was the only pace it seemed like it was needed. You can updated this once it's dropped into a fieldset so that future drag-n-drop operations can be handled properly, we don't want to clone the object we move it.
To move it, consider using .detach(). It'll detach the element from the current parent and can be used in chain to append or move into memory as a variable. Similar to .clone() just we're manipulating the actual object. .clone() is to "Copy & Paste" as .detach() is to "Cut & Paste".
JavaScript
$(function() {
var fs_count = 0;
function makeFieldTarget($fs) {
$fs.droppable({
accept: '.draggableField, .activeField',
drop: function(event, ui) {
var clone, cloneClass;
if (ui.draggable.data("source") == "sidebar") {
clone = $(ui.draggable).clone();
clone.removeClass('draggableField').addClass('activeField');
$(this).append(clone);
cloneClass = clone.attr('class');
console.log('DROPFIELD - you dropped a field from the side bar: ' + cloneClass);
clone.data("source", "fieldset").draggable({
zIndex: 1000
});
}
if (ui.draggable.data("source") == "fieldset") {
clone = ui.draggable;
clone.detach().attr("style", "").appendTo($(this));
cloneClass = clone.attr('class');
console.log('DROPFIELD - you dropped a field from a Field set: ' + cloneClass);
}
}
});
}
$("#drop-area").droppable({
accept: '.ui-draggable:not(.draggableField, .activeField)',
drop: function(event, ui) {
fs_count++;
var clone = $(ui.draggable).clone()
clone.addClass('connectedSortable');
if (clone.hasClass('dropped')) {
return false;
}
clone.addClass('connectedSortable dropped').attr('id', 'fs_' + fs_count);
$(this).append(clone);
var fs_class = clone.attr('class');
console.log('DROPAREA - You added a field with class ' + fs_class);
makeFieldTarget(clone.find(".fieldDroppable"));
$("#drop-area").sortable("refresh");
}
});
$(".ui-draggable").draggable({
opacity: 1.0,
helper: 'clone',
revert: 'invalid'
});
$(".draggableField").data("source", "sidebar").draggable({
opacity: 1.0,
helper: 'clone',
revert: 'false',
zIndex: 1000
});
$("#drop-area").sortable({
handle: '.drag-handle',
placeholder: "drop-place-holder",
items: ">div.dropped",
update: function() { //triggered when sorting stopped
var dataAuto = $("#drop-area").sortable("serialize", {
key: "za",
attribute: "id",
});
alert(dataAuto);
}
});
$("#drop-area").disableSelection();
});
I have two issues,
I am able to move div element once dropped in RED div, but if I try to reposition the element code messes up.
I want to save position X/Y & ID of div moved to RED Div on SAVE button Click.
$(".draggable").draggable({ cursor: "crosshair", revert: "invalid"});
$("#drop").droppable({ accept: ".draggable",
drop: function(event, ui) {
console.log("drop");
$(this).removeClass("border").removeClass("over");
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({}).appendTo(droppedOn);
},
over: function(event, elem) {
$(this).addClass("over");
console.log("over");
}
,
out: function(event, elem) {
$(this).removeClass("over");
}
});
$("#drop").sortable();
$("#origin").droppable({ accept: ".draggable", drop: function(event, ui) {
console.log("drop");
$(this).removeClass("border").removeClass("over");
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({top: 0,left: 0}).appendTo(droppedOn);
}});
$(".save").click(function() {
getCordinates();
});
function getCordinates(){
var c = document.getElementById("drop").children.length;
alert(c);
}
Fiddler link for the code: Code Fiddler
The first point I could not replicate it, regarding to the second point you can obtain the id in the event drop of your div (#origin or #drop) like this:
$(ui.draggable).attr("id")
and the X and Y Position of the img has been dropped you can obtain this way:
//position X
$(ui.draggable).offset().left
//Position Y
$(ui.draggable).offset().top
I'm new to jquery, there is no question on this, I wanted my submit button able to get ids of multiple images in droppable, anyone can help? please help me or guide me along... I need to get the ids of the image that is only dragged inside the droppable and when submit button is pressed.. Display the image that is only inside droppable..
jsFiddle
https://jsfiddle.net/xInfinityMing/azvvhxvL/
JavaScript
$(function() {
$("#dragIcons img").draggable({
revert: "invalid",
refreshPositions: true,
cursor: "move",
cursorAt: {
top: 56,
left: 56
},
drag: function(event, ui) {
ui.helper.removeClass("end-draggable");
ui.helper.addClass("draggable");
},
stop: function(event, ui) {
ui.helper.addClass("end-draggable");
ui.helper.removeClass("draggable");
}
});
$("#briefcase-full").droppable({
greedy: true,
tolerance: 'touch',
drop: function(event, ui) {
var id = ui.draggable.attr("id");
alert(id);
if ($("#briefcase").length == 0) {
$("#briefcase-droppable").html("");
}
ui.draggable.addClass("dropped");
$("#briefcase-droppable").append(ui.draggable);
}
});
});
Basically, all the dragged element will go inside the droppable. so you can use children to check every elements.
$("#briefcase-droppable").children(".icons").each(function() {
var icon_id= $(this).attr("id");
});
JSFiddle : Link
I suggest you to use class instead of using img element to attach draggable event.
https://jsfiddle.net/ianderso222/y9ynouxs/36/
I hope this makes sense, If I need to elaborate I will do so.
Right now the code is working pretty well, doing everything I need it to except this one issue. I just need to alert the order that the squares have been dropped in, after all 4 have been placed.
So, if square4 is placed in the large container, that would show up first in the alert. If square2 is in the last, smallest box it would be last in the list, and so on.
I would use sortable but I am afraid it would not work with the current setup. The resizing to different sized containers would not work, or at least I was not able to get it to work. If there is a way to keep the current structure of resizing to fill container and sliding into place I would say do that, but from everything I have seen I feel I would have to essentially start from scratch.
Here is the JavaScript, pardon the messy code:
$('.holderList li').droppable({
drop: function(event, ui) {
var droppable = $(this);
var draggable = ui.draggable;
console.log(draggable.attr('id') + ' is ' + droppable.attr('id'));
var $this = $(this);
ui.draggable.position({
my: "center",
at: "center",
of: $this,
using: function(pos) {
$(this).animate(pos, 200, "linear");
}
});
ui.draggable.addClass('dropped');
ui.draggable.data('droppedin', $(this));
$(this).droppable('disable');
setTimeout(function() {
var dragID = ui.draggable;
if (!$(".ui-droppable").not(".ui-droppable-disabled").length) {
alert(draggable.attr('id'));
}
}, 400);
},
});
$(".square").draggable({
stack: ".square",
revert: function(event, ui) {
//overwrite original position
$(this).data("ui-draggable").originalPosition = {
width: 50,
height: 50
}
//return boolean
return !event;
},
drag: function(event, ui) {
var draggable = $(this).data("ui-draggable");
$.each(draggable.snapElements, function(index, element) {
ui = $.extend({}, ui, {
snapElement: $(element.item),
snapping: element.snapping
});
if (element.snapping) {
if (!element.snappingKnown) {
element.snappingKnown = true;
draggable._trigger("snapped", event, ui);
}
} else if (element.snappingKnown) {
element.snappingKnown = false;
draggable._trigger("snapped", event, ui);
}
});
if ($(this).data('droppedin')) {
$(this).data('droppedin').droppable('enable');
$(this).data('droppedin', null)
$(this).removeClass('dropped')
}
},
snap: ".holder",
snapMode: "inner",
snapTolerance: 8,
snapped: function(event, ui) {
var squareWidth = ui.snapElement.width();
var squareHeight = ui.snapElement.height();
ui.helper.css({
width: squareWidth,
height: squareHeight
});
}
});
Take a look at my solution:
Demo
First it assigns a data-current attribute to the droppable holder on every drop and sets it to the id of the draggable.
Then it itterates trough all the .holder elements and prints their data-current
Simple but works.
// On single drop
drop: function(event,ui){
...
droppable.attr('data-current', draggable.attr('id') );
}
//On all dropped
$('.holder').each(function(el){
console.log($(this).attr('data-current'));
});