ActionScript 2.0 – MovieClip “Bring to Front”
To me this seems like a basic problem in many Flash-based interfaces. I think Adobe did too, which is why in AS3 they completely revamped their approach to layering display objects.
This leaves those of us stuck back in AS2.0-land (because some customers insist they want their Flash published as FlashPlayer 8! ) scratching our heads. Kirupa, Senocular and other worthies have come up with an interesting technique which keeps a “top-layer” counter, increments it by 2 every time you want to swap depths. While this works perfectly well, there’s something about the technique that, to me (no offense guys: you’re genii), seems like quick-and-dirty (with the emphasis on dirty) code. At some point, I reason, one just HAS to hit that upper layer limit. I’m sure it’s like layer 65538 or something, but still – since you’re using SwapDepths() anyway, why can’t you just find that currently top MovieClip and swap the one you want with it. That way you’re never increasing the top layer count and away you go.
So here’s my take on a bringToFront function. (Note: this is an update to the previous version with some substantial improvements).
Here I’ve added the bringToFront function to the MovieClip prototype, so that you can use it with any movieclip as if it were a native method, like this: myMC.bringToFront();
/*
USAGE:
myMC.bringToFront();
myMC.bringToFront({protect:[myMC2, myMC3]});
The second form allows you to protect certain movieclips from having
their stacking order affected. This is useful if you have some movieclips
you want to stay in front of everything else. You pass the actual
movieclip objects, not a string of the movieclip name.
*/
MovieClip.prototype.bringToFront = function(optionsObj:Object):Void{
// define an array to hold a snapshot of the display list
var displayList:Array = new Array();
// traverse the current parent object's children
for (var i:String in this._parent){
// and only capture movieclips (not other properties) whose depth is greater than
// the movieclip we're bringing to the front.
// the _parent == this._parent is there to get around a strange bug I encountered
// where we were digging into children's descendants. don't know why.
if (typeof (this._parent[i]) == "movieclip"
&& this._parent[i]._parent == this._parent
&& this._parent[i].getDepth() > this.getDepth()){
var includeItem:Boolean = true;
// check to make sure this item is not one of the "protected" items
for (var j:Number = 0; j < optionsObj.protect.length; j++){
if (this._parent[i] == optionsObj.protect[j]){
includeItem = false;
break;
}
}
// store it in the array.
if (includeItem) displayList.push(this._parent[i]);
}
}
// for (x in y) usually traverses the object backwards, so here we're
// iterating over displayList in reverse, and just swapping the
// original object's depth all the way up the list. Can't really think
// of a more efficient way of doing this.
for (var i:Number = displayList.length-1; i>=0; i--){
this.swapDepths(displayList[i]);
}
}
