PDA

View Full Version : Drag and Drop tables


hapyfishrmn
05-18-2009, 07:12 PM
Hello,
I am trying to do drag and drop an individual row within a table. I have looked around the web and already got a working example (in IE) but not in Firefox. I wanted to know if anyone can see what I might be doing wrong.

NOTE
Known issue: Dragging an item to the end of the list causes an error.

Thank you in advance for looking


Hap.





<html>
<script language="javascript">

var CurrentElement;
var root;
var offsets = new Array();

function reCalcOffsets ()
{
var wstring = "row";

var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
offsets[i] = elems[i].offsetTop;
}
}

function whereAmI(elem)
{
var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
if (elems[i] == elem)
{
return i;
}
}
}

//------------------------------------------------------
// INIT
//------------------------------------------------------
function DragInit (id)
{
var RowElement = document.getElementById(id);
var oRoot = null;
var minX = 0;
var maxX = 0;
var minY = null;
var maxY = null;
var bSwapHorzRef;
var bSwapVertRef;
var fXMapper;
var fYMapper;

RowElement.onmousedown = DragStart;

if (bSwapHorzRef)
{RowElement.hmode = false;}
else
{RowElement.hmode = true;}
if (bSwapVertRef)
{RowElement.vmode = false;}
else
{RowElement.vmode = true;}

if ((oRoot)
&& oRoot != null)
{RowElement.root = oRoot;}
else
{RowElement.root = RowElement;}

if (RowElement.hmode && isNaN(parseInt(RowElement.root.style.left)))
{RowElement.root.style.left = "0px";}
if (RowElement.vmode && isNaN(parseInt(RowElement.root.style.top)))
{RowElement.root.style.top = "0px";}
if (!RowElement.hmode && isNaN(parseInt(RowElement.root.style.right)))
{RowElement.root.style.right = "0px";}
if (!RowElement.vmode && isNaN(parseInt(RowElement.root.style.bottom)))
{RowElement.root.style.bottom = "0px";}

if (typeof minX != 'undefined')
{RowElement.minX = minX;}
else
{RowElement.minX = null;}
if (typeof minY != 'undefined')
{RowElement.minY = minY;}
else
{RowElement.minY = null;}
if (typeof maxX != 'undefined')
{RowElement.maxX = maxX;}
else
{RowElement.maxX = null;}
if (typeof maxY != 'undefined')
{RowElement.maxY = maxY;}
else
{RowElement.maxY = null;}

if (fXMapper)
{RowElement.xMapper = fXMapper;}
else
{RowElement.xMapper = null;}
if (fYMapper)
{RowElement.yMapper = fYMapper;}
else
{RowElement.yMapper = null;}

RowElement.root.onDragStart = new Function();
RowElement.root.onDragEnd = new Function();
RowElement.root.onDrag = new Function();

RowElement.onDrag = Drag;
RowElement.onDragEnd = DragEnd;

reCalcOffsets();
}

//------------------------------------------------------
// Drag - END
//------------------------------------------------------
function DragEnd(x,y,myElem)
{
//Found not to be necessary
myElem.style["top"] = "0px";
}

//------------------------------------------------------
// Drag - Dragging
//------------------------------------------------------
function Drag(x,y,myElem)
{
y = myElem.offsetTop;

reCalcOffsets()
var pos = whereAmI(myElem);
var elems = root.getElementsByTagName("tr");

if (pos != parseInt(elems.length)-1 && y > offsets[pos + 1])
{
root.removeChild(myElem);
root.insertBefore(myElem, elems[pos+1]);
myElem.style["top"] = "0px";
}

if (pos != 0 && y < offsets[pos - 1])
{
root.removeChild(myElem);
root.insertBefore(myElem, elems[pos-1]);
myElem.style["top"] = "0px";
}
}

//------------------------------------------------------
// START
//------------------------------------------------------
function DragStart (e)
{
var o = this;
CurrentElement = this;

e = FixE(e);
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
o.root.onDragStart(x, y);

o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;

if (o.hmode)
{
if (o.minX != null)
o.minMouseX = e.clientX - x + o.minX;
if (o.maxX != null)
o.maxMouseX = o.minMouseX + o.maxX - o.minX;
}
else
{
if (o.minX != null)
o.maxMouseX = -o.minX + e.clientX + x;
if (o.maxX != null)
o.minMouseX = -o.maxX + e.clientX + x;
}

if (o.vmode)
{
if (o.minY != null)
o.minMouseY = e.clientY - y + o.minY;
if (o.maxY != null)
o.maxMouseY = o.minMouseY + o.maxY - o.minY;
}
else
{
if (o.minY != null)
o.maxMouseY = -o.minY + e.clientY + y;
if (o.maxY != null)
o.minMouseY = -o.maxY + e.clientY + y;
}
document.onmousemove = DragMovement;
document.onmouseup = DragRelease;

return false;
}

//------------------------------------------------------
// DRAG - Movement
//------------------------------------------------------
function DragMovement(e)
{
e = FixE(e);
var o = CurrentElement;

var ey = e.clientY;
var ex = e.clientX;
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
var nx, ny;

if (o.minX != null)
{
if (o.hmode)
{ex = Math.max(ex, o.minMouseX);}
else
{ex = Math.min(ex, o.maxMouseX);}
}
if (o.maxX != null)
{
if (o.hmode)
{ex = Math.min(ex, o.maxMouseX);}
else
{ex = Math.max(ex, o.minMouseX);}
}
if (o.minY != null)
{
if (o.vmode)
{ey = Math.max(ey, o.minMouseY);}
else
{ey = Math.min(ey, o.maxMouseY);}
}
if (o.maxY != null)
{
if (o.vmode)
{ey = Math.min(ey, o.maxMouseY);}
else
{ey = Math.max(ey, o.minMouseY);}
}

nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

if (o.xMapper)
{nx = o.xMapper(y);}
else if (o.yMapper)
{ny = o.yMapper(x);}

if (o.hmode)
{CurrentElement.root.style["left"] = nx + "px";}
else
{CurrentElement.root.style["right"] = nx + "px";}
if (o.vmode)
{CurrentElement.root.style["top"] = ny + "px";}
else
{CurrentElement.root.style["bottom"] = ny + "px";}

CurrentElement.lastMouseX = ex;
CurrentElement.lastMouseY = ey;

CurrentElement.root.onDrag(nx, ny, CurrentElement.root);


return false;
}

//------------------------------------------------------
// Drag - Release
//------------------------------------------------------
function DragRelease ()
{
document.onmousemove = null;
document.onmouseup = null;


if (CurrentElement.hmode)
{CurrentElement.root.style["left"];}
else
{CurrentElement.root.style["right"];}
x = parseInt(CurrentElement.root.style)

if (CurrentElement.vmode)
{CurrentElement.root.style["top"];}
else
{CurrentElement.root.style["bottom"];}
y = parseInt(CurrentElement.root.style)

CurrentElement.root.onDragEnd(x,y,CurrentElement.root);

CurrentElement = null;
}

//------------------------------------------------------
// FIX E
//------------------------------------------------------
function FixE(e)
{
if (typeof e == 'undefined')
{e = window.event;}
if (typeof e.layerX == 'undefined')
{e.layerX = e.offsetX;}
if (typeof e.layerY == 'undefined')
{e.layerY = e.offsetY;}
return e;
}

//------------------------------------------------------
// ON LOAD
//------------------------------------------------------
function doOnLoad()
{
root = document.getElementById("root");
DragInit("row0");
DragInit("row1");
DragInit("row2");
DragInit("row3");
DragInit("row4");
}
</script>

<body onLoad="doOnLoad()">
<form>
<table>
<tbody id="root">
<tr id="row0" style="position:relative; border: solid 1px" ondrag="javascript:DragStart(this)">
<td>ROW 0</td>
</tr>
<tr id="row1" style="position:relative; border: solid 1px" ondrag="javascript:DragStart(this)">
<td>ROW 1</td>
</tr>
<tr id="row2" style="position:relative; border: solid 1px" ondrag="javascript:DragStart(this)">
<td>ROW 2</td>
</tr>
<tr id="row3" style="position:relative; border: solid 1px" ondrag="javascript:DragStart(this)">
<td>ROW 3</td>
</tr>
<tr id="row4" style="position:relative; border: solid 1px" ondrag="javascript:DragStart(this)">
<td>ROW 4</td>
</tr>
</tbody>
</table>
</form>
</body>
</HTML>

abduraooft
05-19-2009, 09:27 AM
http://www.codingforums.com/showthread.php?t=156507 may help

hapyfishrmn
05-19-2009, 04:24 PM
Hello again,
I thought that I would post a condense version of the code to help alleviate any confusion in the code. In the process of doing this I seem to have found the issue but do not know how to solve it. When I am attempting to drag a row the CurrentElement.style.top changes to the mouse's Y location. But the offsetTop of the element does not change at all.

Any ideas?


Hap


<html>
<script language="javascript">

var CurrentElement;
var root;
var offsets = new Array();

function reCalcOffsets ()
{
var wstring = "row";

var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
offsets[i] = elems[i].offsetTop;
}
}

function whatPosition(elem)
{
var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
if (elems[i] == elem)
{
return i;
}
}
}
//------------------------------------------------------
// FIX E
//------------------------------------------------------
function FixE(e)
{
if (typeof e == 'undefined')
{
e = window.event;
}
return e;
}

//------------------------------------------------------
// INIT
//------------------------------------------------------
function DragInit (id)
{
var RowElement = document.getElementById(id);

RowElement.onmousedown = DragStart;
RowElement.style.top = "0px";

reCalcOffsets();
}

//------------------------------------------------------
// START
//------------------------------------------------------
function DragStart (e)
{
CurrentElement = this;
CurrentElement.style.zIndex = 1;

var e = FixE(e);

CurrentElement.lastMouseY = e.clientY;

document.onmousemove = Dragging;
document.onmouseup = DragEnd;

return false;
}

//------------------------------------------------------
// DRAG - Movement
//------------------------------------------------------
function Dragging(e)
{
var e = FixE(e);
var ey = e.clientY;
var NewY;
var pos = whatPosition(CurrentElement);
var elems = root.getElementsByTagName("tr");

NewY = parseInt(CurrentElement.style.top) + ((ey - CurrentElement.lastMouseY));
CurrentElement.style.top = NewY + "px";
CurrentElement.lastMouseY = ey;

if (pos != parseInt(elems.length)-1 && CurrentElement.offsetTop > offsets[pos + 1])
{
root.removeChild(CurrentElement);
if (pos + 1 != elems.length)
{
root.insertBefore(CurrentElement, elems[pos+1]);
}
else
{
root.insertBefore(CurrentElement);
}
CurrentElement.style.top = "0px";
}

if (pos != 0 && CurrentElement.offsetTop < offsets[pos - 1])
{
root.removeChild(CurrentElement);
root.insertBefore(CurrentElement, elems[pos-1]);
CurrentElement.style.top = "0px";
}
}

//------------------------------------------------------
// Drag - End
//------------------------------------------------------
function DragEnd ()
{
document.onmousemove = null;
document.onmouseup = null;

CurrentElement.style.top = "0px";
CurrentElement.style.zIndex = 0;
CurrentElement = null;
}

//------------------------------------------------------
// ON LOAD
//------------------------------------------------------
function doOnLoad()
{
root = document.getElementById("root");
DragInit("row0");
DragInit("row1");
DragInit("row2");
DragInit("row3");
DragInit("row4");
}
</script>

<body onLoad="doOnLoad()">
<form>
<table>
<tbody id="root">
<tr id="row0" style="position:relative; border: solid 1px">
<td>ROW 0</td>
</tr>
<tr id="row1" style="position:relative; border: solid 1px">
<td>ROW 1</td>
</tr>
<tr id="row2" style="position:relative; border: solid 1px">
<td>ROW 2</td>
</tr>
<tr id="row3" style="position:relative; border: solid 1px">
<td>ROW 3</td>
</tr>
<tr id="row4" style="position:relative; border: solid 1px">
<td>ROW 4</td>
</tr>
</tbody>
</table>
</form>
</body>
</HTML>

hapyfishrmn
05-19-2009, 08:38 PM
RESOLVED

For anyone that wants to solve a similar issue, Firefox required the <tr> 's style position to be absolute.



<html>
<script language="javascript">

var CurrentElement;
var root;
var offsets = new Array();

function reCalcOffsets ()
{
var wstring = "row";

var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
offsets[i] = elems[i].offsetTop;
}
}

function whatPosition(elem)
{
var elems = root.getElementsByTagName("tr");
for (var i = 0; i < elems.length; i++)
{
if (elems[i] == elem)
{
return i;
}
}
}
//------------------------------------------------------
// FIX E
//------------------------------------------------------
function FixE(e)
{
if (typeof e == 'undefined')
{
e = window.event;
}
return e;
}

//------------------------------------------------------
// INIT
//------------------------------------------------------
function DragInit (id)
{
var RowElement = document.getElementById(id);

RowElement.onmousedown = DragStart;
RowElement.style.top = "0px";

reCalcOffsets();
}

//------------------------------------------------------
// START
//------------------------------------------------------
function DragStart (e)
{
CurrentElement = this;
CurrentElement.style.zIndex = 1;
if (navigator.appName == "Netscape")
{
CurrentElement.style.position = "absolute";
}

var e = FixE(e);

CurrentElement.lastMouseY = e.clientY;

document.onmousemove = Dragging;
document.onmouseup = DragEnd;

return false;
}

//------------------------------------------------------
// DRAG - Movement
//------------------------------------------------------
function Dragging(e)
{
var e = FixE(e);
var ey = e.clientY;
var NewY;
var pos = whatPosition(CurrentElement);
var elems = root.getElementsByTagName("tr");

NewY = parseInt(CurrentElement.style.top) + ((ey - CurrentElement.lastMouseY));
CurrentElement.style.top = NewY + "px";
CurrentElement.lastMouseY = ey;

if (pos != parseInt(elems.length)-1 && CurrentElement.offsetTop > offsets[pos + 1])
{
root.removeChild(CurrentElement);
if (pos + 1 != elems.length)
{
root.insertBefore(CurrentElement, elems[pos+1]);
}
else
{
root.insertBefore(CurrentElement);
}
if (navigator.appName != "Netscape")
{
CurrentElement.style.top = "0px";
}
}

if (pos != 0 && CurrentElement.offsetTop < offsets[pos - 1])
{
root.removeChild(CurrentElement);
root.insertBefore(CurrentElement, elems[pos-1]);
CurrentElement.style.top = "0px";
}
}

//------------------------------------------------------
// Drag - End
//------------------------------------------------------
function DragEnd ()
{
document.onmousemove = null;
document.onmouseup = null;

if (navigator.appName == "Netscape")
{
CurrentElement.style.position = "relative";
}
CurrentElement.style.top = "0px";
CurrentElement.style.zIndex = 0;
CurrentElement = null;
}

//------------------------------------------------------
// ON LOAD
//------------------------------------------------------
function doOnLoad()
{
root = document.getElementById("root");
DragInit("row0");
DragInit("row1");
DragInit("row2");
DragInit("row3");
DragInit("row4");
}
</script>

<body onLoad="doOnLoad()">
<form>
<table>
<tbody id="root" >
<tr id="row0" style="position:relative; border: solid 1px">
<td>ROW 0</td>
</tr>
<tr id="row1" style="position:relative; border: solid 1px">
<td>ROW 1</td>
</tr>
<tr id="row2" style="position:relative; border: solid 1px">
<td>ROW 2</td>
</tr>
<tr id="row3" style="position:relative; border: solid 1px">
<td>ROW 3</td>
</tr>
<tr id="row4" style="position:relative; border: solid 1px">
<td>ROW 4</td>
</tr>
</tbody>
</table>
</form>
</body>
</HTML>

TinyScript
05-20-2009, 03:41 AM
cool, I tried to figure it out, but the old has-to-have-a-position-attribute problem never even dawned on me. Nice! I like this script very much. Thanks for posting it.