Fix draggable position in multiple div - jquery-ui

in my code i want divs and draggables elements dynamically, my problem is that the draggable elements are moving along the bottom of the div when scrolling, and I need that when I drag them over the div they don't move when scrolling the page.
The code jsFiddle
$(".signatureImage").on("mousedown mouseup", function(e) {
}).draggable({
containment: ".documents",
cursor: "all-scroll",
scroll: false,
//helper: "clone",
grid: [5, 5],
zIndex: 1000,
drag: function(event,ui){
var offset = $(this).offset();
var xPos = offset.left;
var yPos = offset.top;
},
stop: function(e, ui) {
var finalxPos = ui.position.left;
var finalyPos = ui.position.top;
console.log('Stop: '+finalxPos + ' - '+finalyPos);
jQuery.post("ajaxs/",
{
finalxPos: finalxPos,
finalyPos: finalyPos,
}, function(data)
{});
}
}).each(function(i, item){
});
Drag the element inside the div and then use the scroll of the containerDocuments div, you will see that the draggable elements are moving along with the scroll

Consider the following example.
Fiddle: https://jsfiddle.net/Twisty/n5yrtou1/16/
JavaScript
$(function() {
$(".signatureImage").draggable({
containment: ".documents",
cursor: "all-scroll",
scroll: false,
grid: [5, 5],
zIndex: 1000,
stop: function(e, ui) {
var finalxPos = ui.position.left;
var finalyPos = ui.position.top;
console.log('Stop: ' + finalxPos + ' - ' + finalyPos);
}
});
$("#containerDocuments").droppable({
drop: function(e, ui) {
var el = ui.helper.detach();
el.css({
top: "",
left: "",
position: "absolute",
"z-index": 1000
}).appendTo(this).position({
my: "center",
at: "center",
of: e
});
}
});
});
Using Droppable, you can detach the Draggable element and attach it to your DIV. It is then a matter of positioning it. You can do this in many different ways, yet I opted to base it on the Event.
Initially, with your code, when you dragged it and stopped, it was given a Top & Left position based on the relative position to it's parent. When you drop it, the new position has to be relative to the new target element. You can do this with .offset(), yet it's complicated.
This allows the user to drag an element from the right onto the images, it attaches, and now when the user scrolls, the image scrolls with the rest of the DIV.
See More:
https://jqueryui.com/droppable/
https://jqueryui.com/position/

Related

How to destroy cloned elements if dropped in a droppable on first drop?

Spelling app. I have a bunch of letter tiles, user clicks a tile and drags it (a clone) down to spell a word. But they can currently drop them ONTO the tiles they're supposed to be choosing from (div "#tiles"). I have it set up so that if they drag them BACK there, they disappear, but I can't figure out how to destroy them on that initial drag.
putting $(ui.helper).remove(); and ui.remove(); together in my droppable : drop solves it, makes the cloned tile disappear. But it also destroys the functionality of the original tile (it's still visible but no longer draggable).
$(function() {
$('.tiles').draggable({
helper: "clone",
snap: true,
scroll: false,
containment: 'window',
snapTolerance: 30,
start: function(e, ui) {
ui.helper.addClass("clones");
}
});
$('.tiles').bind('dragstop', function(event, ui) {
$(this).after($(ui.helper).clone().draggable({
snap: true,
snapTolerance: 30,
scroll: false,
containment: 'window',
classes: {
"ui-draggable": "clones"
}
}));
});
$('#optionbar').droppable({
accept: ".tiles",
drop: function(event, ui) {
$(ui.helper).remove();
}
});
$('#tiles').droppable({
accept: ".tiles, .clones",
drop: function(event, ui) {
console.info("inside2");
$(ui.helper).remove();
// ui.remove(); //this makes it vanish (yay) but also kills it (oops)
}
});
});
On first drag the cloned tile isn't removed. If I pick up the same tile and drag it again, it is. I want them to be destroyed on FIRST drag if they are dropped inside #tiles, but I need my original unmoved tile to remain.

JQuery Sortable with dynamic DIV

I have a page that implements jQuery draggable, droppable, and sortable. It contains rows of div's, an "Add Line" button, and an image icon that can be dragged onto any div row that causes a modal window to display allowing an image to be placed onto the row. Everything works great...except:
I use jQuery sortable to allow the rows to be re-arranged. As dragging occurs (constrained to the y-axis), the div that the dragged div is being dragged over, and placed after if it is dropped, is colored gray. This works great, except when there are images in a DIV, causing the dragged DIV to have a much greater height than an empty div. It doesn't seem to track properly, as demomnstrated by how the rows turn to and from gray.
Here is some JQuery code:
$(".dropzone").droppable({
over: function(event,ui)
{
var ElementOver = $(event.target);
var DraggedElement = $(ui.draggable);
var IDofDraggedElement = DraggedElement.attr("id");
ElementOver.css("background-color","lightgray");
},
out: function(event,ui)
{
var ElementOver = $(event.target);
ElementOver.css("background-color","");
},
drop: function(event,ui)
{
DropObject(event,ui); //This handles Ajax activity
var ElementOver = $(event.target);
ElementOver.css("background-color","");
}
});
$("#lines").sortable({
handle: '.iconmove',
axis: 'y',
tolerance: 'pointer',
helper: 'clone'
});
and here is a sample of my HTML:
<div id="linecontainer" class="w3-card-4 w3-padding">
<div id="lines">
<cfoutput query="qFormLines" group="formlineid">
<div class="w3-row w3-padding" style="width:80%" id="line#formlineid#">
<div class="w3-col w3-center l1 m1 s1">
<img id="moveicon#formlineid#" class="iconmove" src="_images/updown24.png" title="Move Line" >
</div>
<div class="dropzone w3-padding w3-col w3-border l11 m11 s11" id="zone#formlineid#" >
<cfoutput>
<cfif imagefile NEQ "">
<img id="formitem#formitemid#" class="w3-border" src="_images/#imagefile#" >
</cfif>
</cfoutput>
</div>
</div>
</cfoutput>
</div>
</div>
Here is a fiddle I created, although it doesn't quite work the same as my local source code:
Fiddle
Although not ideal, just change the JQuery Droppable method's option - Tolerance from its default 'intersect' to 'touch'. It will allow you to see the effect whenever the draggable overlaps the droppable by any amount of touching:
$(".dropzone").droppable({
// Change the tolerance to 'touch'
tolerance: "touch",
over: function(event, ui) {
var ElementOver = $(event.target);
var DraggedElement = $(ui.draggable);
var IDofDraggedElement = DraggedElement.attr("id");
console.log(IDofDraggedElement);
//if (IDofDraggedElement.indexOf("imageicon") == 0) //MOVING A LINE
ElementOver.css("background-color", "lightgray");
},
out: function(event, ui) {
var ElementOver = $(event.target);
ElementOver.css("background-color", "");
},
drop: function(event, ui) {
var ElementOver = $(event.target);
ElementOver.css("background-color", "");
}
});
$("#lines").sortable({
handle: '.iconmove',
axis: 'y',
tolerance: 'pointer',
helper: 'clone'
});
The droppable's tolerance has four options:
"fit − Draggable covers the droppable element in full.
intersect − Draggable overlaps the droppable element at least 50% in both directions.
pointer − Mouse pointer overlaps the droppable element.
touch − Draggable overlaps the droppable any amount of touching."
Quote from https://www.tutorialspoint.com/jqueryui/jqueryui_droppable.htm

jquery ui drop not working with helper clone

I have a simple drag and drop using jquery ui. I want to clone the element and drop the clone at the cursor position.
$(function() {
$( "#draggable" ).draggable({
grid: [ 20, 20 ],
//helper: 'clone',
});
$("#dropzone-panel").droppable({
drop: function(event, ui) {
console.log("Drop Event Fired");
}
});
});
I can drag the element and when I drop it, it stays in the correct position.
But I don't want to move the original, I want to clone it, and then drop the clone in place.
I tried calling clone and adding an appendTo in the drop function, but this just appends it to the end of the #dropzone-panel, rather than leaving it in place.
Any idea what I need to do, to clone and drop at the cursor position?
I would setup the draggable with the helper option and then the droppable with the accept option. This might look like:
$(function() {
$(".draggable").draggable({
helper: 'clone',
grid: [ 20, 20 ],
appendTo: ".droppable"
});
$(".droppable").droppable({
accept: ".draggable",
drop: function(e, ui) {
var pos = ui.position;
var $obj = ui.helper.clone();
$obj.css({
position: 'absolute',
top: pos.top + "px",
left: pos.left + "px"
});
$obj.appendTo(".droppable");
}
});
});
You will want to make use of CSS to wrap your Droppable in a Div that has position: relative; to ensure that the absolute positioning of the appended element is maintained.

Change HTML when on start dragging with Jquery UI

I've been working on a drag and drop UI with jquery UI.
I have a bunch of elements like this, that are draggable:
<i class="fa fa-laptop fa-fw"></i> Server
I can drag and clone this onto a drop zone. But when I start dragging the original element, I want to change the HTML to be
<i class="fa fa-laptop fa-5"></i>
The current code looks like this, but should I be doing something in the start event handler to clone, and change the html of the cloned element?
function MakeDraggable(ele) {
ele.draggable({
grid: [20, 20 ],
//revert: "invalid",
helper: 'move'
});
}
$(function() {
// Make the .draggable class a Draggable
//
$( ".draggable" ).draggable({
grid: [ 20, 20 ],
helper: 'clone',
appendTo: '#dropzone-panel',
start: function(event, ui) {
console.log("Dragging me.....");
}
});
// Setup the dropzone
//
$("#dropzone-panel").droppable({
drop: function(event, ui) {
console.log("Drop Event Fired");
// Get the original element id
var id = ui.draggable.attr("id");
// If this element is a copy already
// then dont clone it.
//
if (id.indexOf("-copy-") >= 0) {
console.log("This is a copy");
} else {
// This is the orginal, so clone and create a new id
var number_of_clones = document.querySelectorAll('*[id^="'+id+"-copy-" +'"]').length;
console.log("found [" +number_of_clones +"] copies");
var pos = ui.position;
var $obj = ui.draggable.clone().attr("id", id+"-copy-"+number_of_clones);
$obj.css({
position: 'absolute',
top: pos.top + "px",
left: pos.left + "px"
});
$obj.appendTo("#dropzone-panel");
// Make the clone draggable
MakeDraggable($obj);
}
}
});

jquery draggable offsetting on first drop

Using JQuery UI draggable/droppable I am running into an issue where the draggable drop area is offset (normally to the left but inconsistent distance). The image can be directly over the drop area and fail and on next attempt, in exact same location, pass.
So, dragged item looks in correct spot over mouse but is incorrect when dropped... but only first attempt.
function dragAndDrop(draggedItem,dropZone,size)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
//var size = size;
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
},
drag:function(event, ui)
{
$(this).height(size);
$(this).width(size);
},
cursorAt:
{
left:(size/2),
top:(size/2)
}
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
}
});
}
sample image
* EDIT 1
Adding function call from edge animate *
draggable and droppable objects are just divs with class names.
yepnope({nope:['jquery-ui.js','cookbook.js'],complete:init});
function init(){
dragAndDrop(".item1",'.dz1',50);
dragAndDrop(".item2",'.dz2',50);
dragAndDrop(".item3",'.dz3',50);
dragAndDrop(".item4",'.dz4',50);
dragAndDrop(".item5",'.dz5',50);
dragAndDrop(".item6",'.dz6',50);
dragAndDrop(".item7",'.dz7',50);
dragAndDrop(".item8",'.dz8',50);
dragAndDrop(".item9",'.dz9',50);
}
* EDIT 2
fixed issue, introduced another *
by having the scale prior to adding the draggable, it now drops correctly. The new issue is the first item I touch of each type scales and relocates to pointer but the drops. It doesn't fail it just stops being dragged.
function dragAndDrop(draggedItem,dropZone,scaleHeight,scaleWidth)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
var currentMousePos = { x: -1, y: -1 };
draggedItem.mousedown(function(event){
currentMousePos.x = event.pageX - (scaleWidth/2);
currentMousePos.y = event.pageY - (scaleHeight/2);
$(this).height(scaleHeight);
$(this).width(scaleWidth);
$(this).offset({top: currentMousePos.y, left: currentMousePos.x});
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
}
})
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
//$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
},
tolerance: "touch"
});
}
** I FOUND IT **
Ok, so my first attempt was calculating the draggable as its original size. The second attempt was not dragging the first item of each type during first attempt. I believe it was stuck in mousedown event and not running the draggable. every time after that draggable was already applied so it worked.
The fix was to assign draggable to everything in the beginning but pull the scaling into a second function. It now scales the item, centers it on mouse, drags and drops.
function dragAndDrop(draggedItem,dropZone,scaleHeight,scaleWidth)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
var currentMousePos = { x: 0, y: 0};
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
}
})
draggedItem.mousedown(function(event){
currentMousePos.x = event.pageX - (scaleWidth/2);
currentMousePos.y = event.pageY - (scaleHeight/2);
$(this).height(scaleHeight);
$(this).width(scaleWidth);
$(this).offset({top: currentMousePos.y, left: currentMousePos.x});
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
//$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
},
tolerance: "touch"
});
}

Resources