Introduction
I was playing around with the Microsoft AJAX Reorderlist
control and I wanted to be able to drag items between the 2 Reorderlist
s. I realized this wasn't going to happen any time soon unless I wrote it myself in JavaScript.
Background
To create this kind of functionality, I decided to use a container div
with div
s inside representing the items to reorder. I used DOM to maneuver the div
s appropriately based on jscript mouse dragging events (ondragstart
, ondrag
, ondragover
, ondrop
). I checked the Y-axis position of the mouse cursor inside the container div
against all of its child div
s' Y-axis positions (plus half the child's height) to determine where the dragged div
should go. If the mouse cursor position is outside of a container div
when ondrop
is fired, the child div
's original placement is restored. Currently, it only works for IE because I haven't looked into FF mouse dragging events yet.
Using the Code
Just copy and paste this into an HTML file to run it.
<head>
<script type="text/javascript">
var divFollow, divPreview, divDrag, divMove, divParent, divBefore,
divAfter, mouseX, mouseY, halfY, isInDiv;
function debug(s)
{
document.getElementById("debug").innerHTML=s;
}
function getMouseX(e)
{
return e.pageX
|| ( e.clientX+(document.documentElement.scrollLeft
|| document.body.scrollLeft));
}
function getMouseY(e)
{
return e.pageY
|| (e.clientY+(document.documentElement.scrollTop
|| document.body.scrollTop));
}
function childDragStart(obj,e)
{
divDrag=obj;
divBefore=null;
divAfter=null;
divBefore=divDrag.previousSibling;
divAfter=divDrag.nextSibling;
}
function childDrag(obj,e)
{
mouseX=getMouseX(e);
mouseY=getMouseY(e);
divFollow.innerHTML=obj.innerHTML;
halfY=divFollow.offsetHeight/2;
divFollow.style.left=mouseX+15;
divFollow.style.top=mouseY-halfY;
if((mouseY>divParent.offsetTop+divParent.offsetHeight)
||(mouseX>divParent.offsetLeft+divParent.offsetWidth)
||(mouseY<divParent.offsetTop)
||(mouseX<divParent.offsetLeft)) isInDiv=false;
else isInDiv=true;
for(var i=0;divParent.childNodes[i];i++)
{
node=divParent.childNodes[i];
if(mouseY-divParent.offsetTop < (node.offsetHeight/2)+node.offsetTop)
{
divParent.insertBefore(divPreview,divParent.childNodes[i]);
return;
}
}
divParent.appendChild(divPreview);
}
function parentDragOver(obj,e)
{
divParent=obj;
}
function parentDrop(obj,e)
{
var p=document.getElementById("divPreview");
var n;
if(divDrag && isInDiv)
{
if(p)
{
divParent.insertBefore(divDrag,p);
divParent.removeChild(p);
divDrag=null;
}
}
else if(divDrag)
{
n=divDrag.parentNode;
if(divAfter) n.insertBefore(divDrag,divAfter);
else n.appendChild(divDrag);
divDrag=null;
if(p) divParent.removeChild(p);
}
divFollow.style.left=-1000;
divFollow.style.top=-1000;
divDrag=null;
}
function initReorderlists(page)
{
eventpage=page; divDrag=null;
divFollow=document.createElement("div");
divFollow.style.border="1px solid black";
divFollow.style.color="black";
divFollow.style.fontWeight="bold"
divFollow.backgound="transparent";
divFollow.id="divFollow";
divFollow.style.position="absolute";
divFollow.style.left=-1000;
divFollow.style.top=-1000;
document.body.appendChild(divFollow);
divPreview=document.createElement("div");
divPreview.innerHTML=" ";
divPreview.style.color="red";
divPreview.backgound="transparent";
divPreview.id="divPreview";
divPreview.style.border="1px dotted black";
}
</script>
</head>
<body onload="initReorderlists()">
<div ondragover="parentDragOver(this,event)"
ondragend="parentDrop(this,event)" id="div1"
style="border:1px solid black;width:300px">
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div1 child1</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div1 child2</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div1 child3</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div1 child4</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div1 child5</div>
</div>
<div ondragover="parentDragOver(this,event)"
ondragend="parentDrop(this,event)" id="div2"
style="border:1px solid black;width:300px">
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div2 child1</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div2 child2</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div2 child3</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div2 child4</div>
<div><img ondrag="childDrag(this.parentNode,event);"
ondragstart="childDragStart(this.parentNode,event);"
src="drag.gif"/>div2 child5</div>
</div>
<div id="debug"></div>
</body>
History
- 22 August, 2007 -- Rewritten to use
ondrag*
events instead of onmouse*
events
- 17 August, 2007 -- Original version posted