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
Related
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/
I need to drag one element and while dropping it should append a new html div container and appended html div container should be droppable (nested). I have attached fiddle file here. Can any one help on this?
$('.dragItem').draggable({
helper: 'clone',
connectToSortable: "#column2,#column2 div"
});
$('.dragItem').sortable({
containment: "parent"
});
$('#column2').sortable({
placeholder: "highlight"
});
$('#column2').droppable({
accept: '.dragItem',
drop: function(event, ui) {
var draggable = ui.draggable;
var droppable = $(this);
var drag = $('#column2').has(ui.draggable).length ? draggable : draggable.clone().draggable({});
drag.appendTo(column2);
drag.sortable({
placeholder: "highlight"
});
drag.droppable({
accept: ".dragItem",
drop: function (event, ui) {
var draggable = ui.draggable;
var droppable = $(this);
var drag = $('#column2').has(ui.draggable).length ? draggable : draggable.clone().draggable({});
}
})
drag.css({width:'', height: ''})
}
});`
Js Fiddle
I have a table and need to drag/drop cells containing data into blank cells. I'm able to drag and drop fine, but once a cell is dragged away, I need its "old" position to now become a droppable cell. Since the cell is dragged, I need something else to reference. I ended up wrapping each of the td elements in a div element, but all references return "undefined" on the inner cellDiv id (or return the outer tableDiv id). On the fiddle, I notice that the blue background is not appearing so I don't think the 'cellDiv' is doing much.
Next I am going to try swapping the td and cellDiv elements, but I decided to post the question first, as I've searched everywhere and cannot seem to find this specific problem addressed. Thanks for your help.
here is the problem in a jsfiddle: http://jsfiddle.net/tgsz34hx/3/
And the code:
<div id='tableDiv'>
<table>
<tr id='row1'>
<div class='cellDiv' id='r1c1'>
<td class='drop' id='col1'>Drop Here</td></div>
<div class='cellDiv' id='r1c2'>
<td class='nodrop' id='col2'>Drag Me</td></div>
</tr>
</table>
</div>
$(document).ready(function () {
var fromDiv;
$('.nodrop').draggable({
cursor: "move",
appendTo: "body",
revert: "invalid",
start: function (event, ui) {
var thisDiv = $(this).attr('id');
fromDiv = $(this).closest('.cellDiv').attr('id');
alert("thisDiv=" + thisDiv + ", fromDiv=" + fromDiv);
}
});
$('.drop').droppable({
accept: ".nodrop",
tolerance: "pointer",
snap: ".drop",
drop: function (event, ui) {
var parenttd = $(ui.draggable).closest('td').attr('id');
var parentdiv = $(ui.draggable).closest('.cellDiv').attr('id');
// alert("parenttd=" + parenttd + ", parentdiv=" + parentdiv);
$(this).removeClass('drop');
$(this).addClass('nodrop');
$(this).droppable('option', 'disabled', true);
}
});
});
#tableDiv {
background-color: grey;
}
#tableDiv td {
background-color: red;
}
#tableDiv div {
background-color: blue;
}
Is it possible to check if a sortable item has moved from left to right more than x pixels?
Here is a place to play:http://jsfiddle.net/qfgd9/4/
For instance if the user moves item1 more than 200px do something
if( drag > 200 ) {
alert( "something" );
}
JQUERY:
$( "#sortable" ).sortable({
});
HTML:
<div id="sortable">
<div>item1</div>
<div>item2</div>
<div>item3</div>
</div>
<div id="check"></div>
Try this: http://jsfiddle.net/lotusgodkk/GCu2D/262/
You can get the difference in left offset from ui object by using originalPosition and position . Hence by the difference in their values you can easily find the movement.
$(function () {
$("#sortable").sortable({
sort: function (event, ui) {
var move = (ui.position.left - ui.originalPosition.left);
$('#check').text(move);
if(move>200){
alert('moved beyond 200px'); //Do something.
}
}
});
});
i want to detect to see if an element was dragged out of container.
for example:
<div id="container">
<img src="xxx.png" />
</div>
if i am drag that img element out of the div. i will remove
the img element, but i do not know how to detect when the img is out of div.
i am use jquery drag and drop library.
There is an easy way to do this.
Set child to draggable
Set parent to droppable
Set a flag which if true on drag stop removes the element
Unset this flag in the parents on drop function
child dragged out of parent == child not dropped into parent
So when you move the child around in the parent nothing happens (removeMe flag is unset) and it moves back to original position.
If you drag the child outside of the parent the removeMe flag isn't unset and the drag stop method removes the child.
javascript
$("#draggable").draggable({
start: function(event, ui) {
// flag to indicate that we want to remove element on drag stop
ui.helper.removeMe = true;
},
stop: function(event, ui) {
// remove draggable if flag is still true
// which means it wasn't unset on drop into parent
// so dragging stopped outside of parent
if (ui.helper.removeMe) {
ui.helper.remove();
}
},
// move back if dropped into a droppable
revert: 'valid'
});
$("#droppable").droppable({
drop: function(event, ui) {
// unset removeMe flag as child is still inside parent
ui.helper.removeMe = false;
}
});
html
<div id="droppable">
<p id="draggable">Drag me!</p>
</div>
thank your provides a solution.
I have found an other solution without need an outer div for this problem.
I am use "distance" option to detect how long mouse has moved, then use
"stop" option to remove element.
$(".droppable").droppable({
drop: function(event, ui) {
var obj = $(ui.draggable).clone();
obj.draggable({
distance: 100,//used to measure how far my mouse moved.
helper: 'clone',
opacity : 0.35,
stop: function(event, ui) {
$(this).remove();//remove this element.
}
}
);//obj.draggable
}//drop
})
you need to add a div outside of your container
<div id="droppableDiv">
<div id="container">
<img src="xxx.png" />
</div>
</div>
and then make it droppable by adding a function similar to:
$("#droppableDiv").droppable ({
drop: function() { alert('dropped'); }
});
instead of the alert('dropped'); part you could add a little bit of code that removes the img element from the container div.
here is a example that does some other thing but makes use of droppable and draggable objects, maybe it can help you understand how it works!
hope this helps
-Fortes