This snippet takes xml and builds a multi-tiered navigation based on how nodes are nested etc…:
So that something like this:
[XML]
var menu:XML=
;
[/XML]
Turns into an expandable and collapsible menu that looks like this:
Here is the timeline code:
var menu:XML=<nav>
<element label="one">
<element label="a" />
<element label="b" />
<element label="c" />
</element>
<element label="two">
<element label="three">
<element label="aa" >
<element label="zevan" />
</element>
<element label="bb" />
<element label="cc" />
</element>
</element>
</nav>;
var elements:Array = new Array();
setupMenu();
function setupMenu():void {
parse(menu);
// hide child elements
for (var i:int = 0; i<elements.length; i++) {
var mc:MovieClip = elements[i];
if (mc.parents != 1) {
removeChild(mc);
}
}
arrangeY();
}
function parse(m:XML):void {
for each (var d:XML in m.children()) {
makeBtn(d, numParents(d));
parse(d);
}
}
function makeBtn(d:XML, offsetX:int):void {
var btn:MovieClip = new MovieClip();
btn.x = offsetX * 20;
btn.y = numChildren * 20;
btn.data = d;
btn.parents = offsetX;
btn.value = d.@label;
var txt:TextField = new TextField();
txt.text = d.@label;
txt.selectable = false;
txt.border = true;
txt.width = 100;
txt.mouseEnabled = false;
txt.height = 19;
btn.addChild(txt);
btn.buttonMode= true;
addChild(btn);
// store references to btn
elements.push(btn);
elements[d.parent().@label+"_"+d.@label] = btn
btn.addEventListener(MouseEvent.CLICK, onClick);
}
function onClick(evt:MouseEvent):void {
showHide(MovieClip(evt.currentTarget));
arrangeY();
trace(evt.currentTarget.value);
}
function showHide(btn:MovieClip, forceHide:Boolean=false):void {
for each (var d:XML in btn.data.children()) {
var mc:MovieClip = elements[btn.data.@label+"_"+d.@label];
if (contains(mc)) {
removeChild(mc);
showHide(mc, true);
} else if (forceHide == false) {
addChild(mc);
}
}
}
function arrangeY():void {
var inc:Number = 0;
for (var i:int = 0; i<elements.length; i++) {
if (contains(elements[i])) {
elements[i].y = inc * 20;
inc++;
}
}
}
function numParents(e:XML):int {
var num:int = 0;
while (e.parent()!= null) {
num++;
e = e.parent();
}
return num;
}
This is one of those snippets I’ve had laying around but never got around to posting. Next time I need to do a multi-tiered nav I’ll wrap it up into a nice class (the wondeful class was done just by using my script that auto-converts timeline code to doc class code).
How about adding some animation to it? That’s the icing on the cake! Keep up the awesome snippets!
i may post a revised version of it tomorrow… with some animation… would be easy enough to do with tweenlite….