Part 5 - How to drag widgets
Dragging an object involves the following steps:- Detecting a mouse left-click on the object
- Detecting mouse movement while the mouse is still left-clicked
- Moving the object following the mouse
- Detecting that mouse is no longer left-clicked to stop dragging
First let's take a look at the HTML code:
<div id='widget1' class='widget' style='position: absolute; left: 150;top: 150; width: 250;'> <div style='cursor: move; width: 100%; height: 16; background-color: #CCCCFF; border-bottom: 1px solid #CACACA; '> <table style='font-family: arial; font-size: 8pt;' width=100% cellpadding=0 cellspacing=0 border=0> <tr> <td ALIGN=left id='titlebar' style='padding-left: 5px;'>Widget Title Bar</td> <td align=right style='padding-right: 5px;'> <a href='#' style='text-decoration:none;'><b>X</b></a></td> </tr> </table> </div> <div id='' style='padding: 5px; font-family: arial; font-size: 8pt; width: 100%'> Widget Body (this is where the widget content is going to be placed)</div> </div>
We create a widget on the screen, similar to the ones we used before. Note that in order to be able to freely position the widget anywhere on the screen, we must use the position:absolute CSS directive.
Now we can instruct the browser where to position the widget, and we use left: 150; top: 150; to position the widget 150 pixels from the left (x=150) and 150 pixels from the top (y=150).
Let's examine the Javascript code:
var x,y;
var tx, ty;
var isDrag=false;
var firefox=document.getElementById&&!document.all;
document.onmousemove=mouseMove;
document.onmousedown=selectMouse;
document.onmouseup=function(){
isDrag=false;
}
function selectMouse(e)
{
if (firefox){
//verify that user clicked the 'titlebar' element
var p=e.target;
if (p.attributes['id'] && p.attributes['id'].value=="titlebar"){
isDrag=true;
x=e.clientX;
y=e.clientY;
//get the widget coordinates from the root, 'widget1' element
tx=parseInt(document.getElementById('widget1').style.left);
ty=parseInt(document.getElementById('widget1').style.top);
}
}
else{ //IE
//verify that user clicked the 'titlebar' element
var p=event.srcElement;
if (p.attributes['id'] && p.attributes['id'].value=="titlebar"){
isDrag=true;
x=event.clientX;
y=event.clientY;
//get the widget coordinates from the root, 'widget1' element
tx=parseInt(document.getElementById('widget1').style.left);
ty=parseInt(document.getElementById('widget1').style.top);
}
}
}
function mouseMove(e)
{
if (isDrag) //only move the box if the user is dragging it
{
var box=document.getElementById("widget1");
if (firefox){
box.style.left = e.clientX + (tx - x);
box.style.top = e.clientY + (ty - y);
}
else{ //IE
box.style.left = event.clientX + (tx - x);
box.style.top = event.clientY + (ty - y);
}
}
}
isDrag will be true whenever the user is dragging the widget (that is whenever the user has clicked the mouse and has not released it yet).
Every time the mouse is moved we use the mouseMove function to handle the event, every time the mouse is clicked we use the selectMouse to handle the event and when the mouse is released, we simply set the isDrag to false (more about this soon).
x,y will hold the coordinates of the mouse when it is clicked, tx,ty will hold the coordinates of the widget when the mouse is clicked (x=left, y=top). This will allow us to calculate the offset of the mouse compared to the widget so the dragging is done correctly.
When the mouse is clicked the selectMouse function is called (document.onmousedown=selectMouse). The selectMouse function first verifies that the mouse was clicked inside the widget's title bar. In firefox this is done by accessing the target attribute of the event object (which holds a reference to the DOM element that was clicked) and then verifying that that element has an attribute id with the value 'titlebar'. In IE this is done by checking the srcElement attribute of the global event object and then going through the same process.
If the user did click the title bar we set the drag flag to true (isDrag=true) and record the mouse click coordinates in x,y. We then record the coordinates of the widget's widget1 DIV as well by parsing the left, top CSS attributes and saving them in the tx,ty variables.
When the mouse is moved we first check that our drag flag, isDrag, is set to true (meaning that the user is still pushing down on the left mouse button). If it is, we set the left & top CSS attributes of our widget DIV to the updated mouse coordinates by taking the current mouse coordinates and adding the delta between the mouse coordinates and the widget top left corner.
