| home / programming / javascript / mk / column2 / 1 | [previous][next] |
|
|
||||||||||||
You will notice that this basis of this code is mostly taken from our previous examples. Put them all together and you can drag items freely.
When we click on an item we're storing another variable, mouseOffset. mouseOffset simply contains information on where we clicked our item. If we have a 20x20px image and click in the middle, mouseOffset should be: {x:10, y:10}. If we clicked the top-left of our image, mouseOffset should be: {x:0, y:0}. We use this information to later position the item under our mouse in the same way that we clicked on it. If we didn't store this your item would always be in exactly the same position relative to the mouse regardless of where you clicked on the item.
Our mouseOffset function uses another function, getPosition. getPosition's purpose is to return the coordinates of an item relative to the document. If we simply try to read item.offsetLeft or item.style.left we will get the item's position relative to its parent, not the document. Everything else in our script is relative to the document so this must be as well.
To accomplish this task getPosition starts with the element we pass it and loops through each parent of that item adding its left and top positions to a running total. By doing this we manage to get a top and left total for the item we want.
Once we have this information and we move the mouse, the mouseMove function takes over. First we make sure our item style.position is absolute. Next we move our item to wheverever the mouse is minus the offset that we recorded earlier. When the mouse is released dragObject is set to null and our mouseMove function no longer does anything.
Our previous example serves its purpose well, just dragging an item around and leaving it wherever you drop it. Often we have other purposes in mind when we drop the item, however. We could be dragging it to a trash can for instance, or we might want it to snap to a specific area on our page.
Unfortunately we run into a fairly major issue here. Since the item we're dragging is always directly under our mouse it's impossible to fire a mouseover, mousedown, mouseup or any other mouse action on any other item on our page. If you drag an item onto a trashcan your mouse is still on top of that item, not the trashcan.
How do we get around this? There are several possible solutions. As mentioned earlier the purpose of our mouseOffset was so that the item would always be properly positioned under the mouse. If you ignore this and always make the item positioned to the bottom-right of the mouse, your cursor will not be hindered by the item you are dragging and we no longer have a problem. This, however, simply doesn't look that good. We generally want to keep the item under the mouse for aesthetic reasons.
Another option is to simply not move the item you are dragging. You can change the cursor to show your user that you are dragging an item, but leave the item in place until you drop it somewhere. This also solves our issue but has the same issue as our previous solution: aesthetics.
Our final solution doesn't affect either the item you are dragging or the item you are dropping onto. Unfortunately it's more difficult to accomplish than either of the previous two solutions to our problem. What we are going to do is get a list of all our drop targets. When the mouse is released we manually check the position of our mouse against the position of each of our targets to see if the mouse was released over one of those targets. If it was then we know we just dropped an item onto our target.
/*
All code from the previous example is needed with the exception
of the mouseUp function which is replaced below
*/
var dropTargets = [];
function addDropTarget(dropTarget){
dropTargets.push(dropTarget);
}
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
for(var i=0; i<dropTargets.length; i++){
var curTarget = dropTargets[i];
var targPos = getPosition(curTarget);
var targWidth = parseInt(curTarget.offsetWidth);
var targHeight = parseInt(curTarget.offsetHeight);
if(
(mousePos.x > targPos.x) &&
(mousePos.x < (targPos.x + targWidth)) &&
(mousePos.y > targPos.y) &&
(mousePos.y < (targPos.y + targHeight))){
// dragObject was dropped onto curTarget!
}
}
dragObject = null;
}
When the mouse is released in this example we start to loop through each of our possible Drop Targets. If the mouse cursor is over our target we know that we have a drop event. To check this we make sure that our cursor is to the right of the left side of our target (mousePos.x > targetPos.x) and that the cursor is to the left of the right side of our target (mousePos.x < (targPos.x + targWidth)). We do the same thing for the y-coordinates. If all of these return true than our cursor is inside of the boundaries of our target.
Finally we have all the pieces we need to create a fully function Drag/Drop script. The one thing we are going to throw in here is DOM manipulation. If you are not completely familiar with this please read my JavaScript Primer on DOM Manipulation.
The following code takes any "Container" or "Containers" and makes it possible to drag each item in those containers. It's the code behind the 2nd demo in this article. This code can be used to reorder lists, to position "Nav Windows" on the left and right of your page, or for any other number of functions you can think of.
We are going to step through the "Pseudo-code" but leave it to the reader to look through the actual code, which is thoroughly commented.
| home / programming / javascript / mk / column2 / 1 | [previous][next] |
| ||||||||||||||||||||
Created: March 27, 2003
URL: http://webreference.com/programming/javascript/mk/column2