Drag&Drop in jQuery on Table Cells - jquery-ui

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

Related

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

Drag a sortable item to the right

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

Clone draggable element jQuery UI

I have a page with a draggable element which I want to drop into a droppable section of the page. However, when I click on the draggable div I actually want to spawn a clone and drag that into the droppable environment instead (leaving the original behind). In essence I'm trying to create a series of prefabs in a left hand tool-box. When I click on them to drag them into the drawing I just want to spawn a clone of that type of div. is this possible in JavaScript?
Yes it is possible.. Here is an example
HTML
<div class="draggable" style="position:absolute;">
<p>Draggable</p>
</div>
<br />
<br />
<div id="droppable">
<p>Drop here</p>
</div>
CSS
.draggable {
width:65px;
border: 1px solid blue;
}
#droppable {
border:1px solid green;
width:300px;
height:100px;
}
jQuery/Javascript
var dropped = false;
$( ".draggable" ).draggable();
$( "body" ).on( ".draggable dragstart",
function( event, ui ) {
dropped = false;
console.log('1');
ui.helper.before(ui.helper.clone().draggable());
}
);
$( "body" ).on( ".drggable dragstop",
function( event, ui ) {
if(dropped)
ui.helper.draggable('destroy');
else
ui.helper.remove();
}
);
$('#droppable').droppable({
accept: '.draggable',
drop: function(event, ui ) {
dropped = true;
}
});
Example
Fiddle

How to restore a removed ui.item?

My element styling depends on the element order. Since jQuery UI keeps the original item while dragging a helper hidden, the hidden element breaks the styling. I can remove the ui.item upon starting the drag event. Though, how can I restore the element after it was removed?
http://jsfiddle.net/MnSRd/8/
HTML
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
CSS
ul { height: 50px; }
li { float: left; width: 50px; height: inherit; background: #ccc; margin: 0 10px 0 0; }
li.placeholder { background: #f00; }
li:nth-child(1):before { content: '1'; }
li:nth-child(2):before { content: '2'; }
li:nth-child(3):before { content: '3'; }
li:nth-child(4):before { content: '4'; }
li:nth-child(5):before { content: '5'; }
JavaScript
$('ul').sortable({
helper: 'clone',
placeholder: 'placeholder',
start: function (e, ui) {
console.log(ui.item.remove()); // temporary remove
},
beforeStop: function (e, ui) {
// how to bring the item back?
}
});
You can first hide() the item and then show() it again. remove() completely removes it from the DOM so you cannot restore it unless you clone() it and then you attach it back or simply use jQuery detach() Updated fiddle.
$('ul').sortable({
helper: 'clone',
placeholder: 'placeholder',
start: function (e, ui) {
ui.item.hide(); // temporary remove
},
beforeStop: function (e, ui) {
ui.item.show();
}
});
After reading the comments I believe that what you want from the sortable is to use helper: 'original' which is the default helper instead of helper: 'clone'.
While this might not be an answer to everyone, it will likely solve any similar issues.
$('ul').sortable({
helper: 'clone',
placeholder: 'placeholder',
start: function (e, ui) {
ui.item.appendTo(ui.item.parent());
}
});
http://jsfiddle.net/MnSRd/11/
Instead of removing the UI element, I am appending it to the end of the parent container. Thus it does not have any effect on the element styling.

JQuery drag, drop and sort

I have a table with left and right col. Inside the cols, some small tables (as elements) from PHP loop.
I would like to make possible to drag and drop the elements from left to right cols AND also change the sort inside the col itself. Very hard for me !
Here's my code :
HTML part (left col but the right one is the same)
<style>
.deplace{
cursor:move;
}
</style>
<table width="100%" border="0" cellpadding="0" cellspacing="0"><tr>
<td id="leftMenu" valign="top" style="width:180px;height:800px;border:1px solid black">
<?php
while($rowg = mysql_fetch_assoc($sqlg)){
echo '<table width="100%" cellpadding="5" cellspacing="2"
style="background-color:#CCC;border: 1px solid black;height:100px"
class="deplace" id="left_'.$rowg['id'].'" modulename="'.modif_nom($rowg['module']).'" sourceid="'.$rowg['id'].'">
echo '<tr><td" align="center" style="width:100%">'.$rowg['module'].'</td></tr>';
echo '</table>';
}
?>
</td></tr></table>
And the JS code :
<script language="javascript" type="text/javascript">
$(document).ready(function() { //
$('#leftMenu').Sortable({
//revert: true,
accept: 'deplace',
axis : 'vertically',
onchange: function(event, ui) {
serial = $.SortSerialize('leftMenu');
$.ajax ( {
url : "xhr.php?source=leftMenu",
type : "get",
data : serial.hash,
success: function(data){alert(data);}
});
}
});
$('#rightMenu').Sortable({
//revert: true,
accept: 'deplace',
axis : 'vertically',
onchange: function(event, ui) {
serial = $.SortSerialize('rightMenu');
$.ajax ( {
url : "xhr.php?source=rightMenu",
type : "get",
data : serial.hash,
success: function(data){alert(data);}
});
}
});
//only the functions to move the tables from left to right
$('#rightMenu').draggable({
revert:false,
helper:'original',
});
$('#leftMenu').droppable({
over:function(event, ui){
alert('dropped');
}
});
});
</script>
So, like that, it seems there's a conflict between the functions. If I only let the sortable functions, it's OK but I can't do anything in the receiver col and I would like to send a request to PHP to update a mysql table.
Thanks a lot for your help !
There are a few issues with your code:
Sortable is lower-case
SortSerialize does not exist, I think you mean sortable("serialize")
$('#rightMenu').draggable should be changed to $('#rightMenu').children().draggable because you want to drag the elements inside the menu
Have a look at the jQuery UI Sortable doc too.

Resources