Now we are going to change the event listener for MOUSE_UP, and add it to the stage instead of to the movie clip instances. However, we have to be careful with this event listener, because it will stay in effect until we turn it off, and it will fire even if we are not dragging anything. For example, we might be clicking on something else entirely. In a larger program, this event would even fire in other sections of the program, if we don't remove it when we're done with it. Therefore, the thing to do is to (very cleverly) add this event listener inside the handler function for the MOUSE_DOWN event, and then turn it off again in the handler for the MOUSE_UP event. That way listening for this event is only in effect when we are dragging.
Another problem, though, is that by adding the event listener to the stage, now we lose our reference (inside the handler function) to the clip being dragged! The event.currentTarget variable refers to the object that the listener was added to, which is now the stage, and not the clip being dragged. But we still need a way to tell the clip to stop dragging. Somehow!
One answer to this dilemma that I have come up with is to create a variable called currentClip. We declare it with the var keyword outside of any functions, so that it can be available inside all of the functions. We will use this variable instead of the former local variable named clip. In contrast to clip, currentClip will have a wider scope. When we refer to currentClip inside of the functions, we never use the var keyword on it, as that would create a completely different local variable with the same name, which would get thrown away at the end of the function, totally defeating our purpose. What a difference the var keyword makes! It establishes the scope of the variable.
Anyway, the idea of using a currentClip variable is simple! Whenever a movie clip gets the MOUSE_DOWN event, it gets assigned to this variable. In effect, it becomes the currentClip. Then, when the stage gets the MOUSE_UP event, we can just tell the currentClip to stop dragging. When we then mouse down on another clip to start dragging it, then it becomes the currentClip and not the first one anymore! So quite obviously, all of our movie clip instances can just take turns "being" the currentClip, and telling currentClip to stop dragging can mean, "whichever one you are." Like, "HEY YOU! Stop dragging!"
The currentClip can be a different movie clip at different times, just like thePresident can be a different man at different times!
This kind of dynamic programming is possible because variable names are really just pointers to the real objects in memory, and so they can be assigned and re-assigned dynamically. Once the variable name is assigned to a real object, the object can then be manipulated at will. Anyway, here is the new code that does all that:
var dragArray:Array = [square, circle, triangle];
var currentClip:MovieClip;
for(var i:int = 0; i < dragArray.length; i++) {
dragArray[i].buttonMode = true;
dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, item_onMouseDown);
}
function item_onMouseDown(event:MouseEvent):void {
currentClip = MovieClip(event.currentTarget);
addChild(currentClip); //bring to the front
currentClip.startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, stage_onMouseUp);
}
function stage_onMouseUp(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, stage_onMouseUp);
currentClip.stopDrag();
}
Here is how the swf now behaves:
Now the objects don't stick to the mouse cursor anymore! But now we have a different problem. The objects drop when we release the mouse, even if the mouse cursor is outside of the window. Consequently, the objects drop outside the window, too, and, if they are too far from the edge, there is no way to get them back. However, we are now on the right track, and we'll solve that problem too, on the next page.