Flash MX Components: FTree Example Loading External XML
NEW: Get the recursive version of this example that supports
indefinit folder levels from bgx:components!!
/* ===========
* Description
* ===========
* An instance of the FTree component is already placed on the stage,
* as well as textfileds and movieclips for description, icon display
* and load button. The FTree instance is called "bgTree".
*
* The tree data comes from explorer.xml. Once it is loaded it gets
* bound to the tree via the buildTree() function. For each node a
* new object (NodeData) is created and used as the tree node data.
*
* When a node is selected, the object is retrieved via bgTreeCall() and
* the display updated using the defined methods for
the NodeData object.
*
* To correspond with usual tree behaviour, double-click will load samples
* and open/close folders. The state of opened/closed folders gets saved
* locally using a Shared Object to restore the tree when viewed next time.
*
* You may also want to check out the example with custom expanders.
*
* © Bernhard Gaul, 2002
* ===========
*/
//initialise display
var nodeDescription = "";
var dTitle = "Loading...";
loadButton._visible = false;
var fileInfo =
"";
with (iconClip)
{
gotoAndStop(1);
}
//paramaters to check for double-click
var lastClick =
0;
var lastSelected;
var dClick = false;
//define shared object for storage of tree
status
bg_so = SharedObject.getLocal("bgTree");
//initialise tree
var t = _level0.bgTree;
var rootNode;
t.setNodeExpansionHandler("saveBranches", _root);
t.setChangeHandler("bgTreeCall", _root);
//current data
depository for selected tree node
//also accessed
by the load button
//which calls _level0.cD.loadSample();
var cD;
//load
XML
treeXML = new
XML();
treeXML.onLoad = buildTree;
treeXML.load("explorer.xml");
//build the tree after XML is loaded
function buildTree()
{
getRoot();
//set
rootnode
thisObject = new
NodeData(rootNode);
t.setRootNode(new FTreeNode(thisObject.label,
thisObject));
//loop through
children
folderArray = rootNode.childNodes;
folderNode = rootNode.firstChild;
var z = 0;
while (z<folderArray.length) {
thisObject = new
NodeData(folderNode);
t.addNode(t.getRootNode(),
new FTreeNode(thisObject.label,
thisObject));
//loop through
grantchildren
sampleArray = folderNode.childNodes;
sampleNode =
folderNode.firstChild;
var x =
0;
while
(x<sampleArray.length)
{
thisObject = new
NodeData(sampleNode);
t.addNode(t.getNodeAt(t.getRootNode(), z), new
FTreeNode(thisObject.label,
thisObject));
sampleNode =
sampleNode.nextSibling;
x++;
}
folderNode
= folderNode.nextSibling;
z++;
}
//restore the tree to last saved
state
setBranches();
dTitle = "Description";
nodeDescription = "Use the tree to browse through the examples.";
}
//check if the firstChild is indeed the root, otherwise
//skip over comments and DTD declarations...
//this was necessary with
Flash 5, sems OK with MX
//but leave it in for the moment
function getRoot() {
rootNode =
treeXML.firstChild;
rootName =
rootNode.nodeName;
var x =
0;
var
y = treeXML.childNodes;
while (x<y.length) {
if (rootName == "myRoot")
{
break;
}
rootNode
= rootNode.nextSibling;
rootName =
rootNode.nodeName;
x++;
}
}
//NodeData Class constructor
//creates the NodeData
object based on the
//XML node submitted
//called from buildTree()
function NodeData(sNode) {
this.type = sNode.nodeName;
this.label = sNode.attributes["label"];
this.description = sNode.attributes["description"];
if (this.type == "sample")
{
this.sampleUrl =
sNode.attributes["URL"];
this.fileinfo = sNode.attributes["fileInf"];
this.icon = sNode.attributes["icon"];
this.target = sNode.attributes["target"];
}
//create boolean value for hasURL
property
this.hasUrl =
((this.type == "sample") && (this.sampleUrl.length
> 0));
}
//Method for NodeData:
loadSample()
NodeData.prototype.loadSample = function() {
getURL(this.sampleUrl,this.target);
}
//Method for NodeData: update()
//this function is
called when a tree node gets clicked on
//unless it is a double-click on a
folder, which is
//treated beforehand
NodeData.prototype.update = function() {
//unlike for branches response to double-click for
leaves
//has to be handled considering the current data as
it
//shall only be executed if the object does have a
URL
if (dClick)
{
if (this.hasURL) this.loadSample();//load sample on
double-click
return;//display was already
updated on first click
}
loadButton._visible = this.hasURL;
nodeDescription = this.description;
fileInfo = this.fileinfo;
with (iconClip) {
gotoAndStop((this.icon.length>0) ?
this.icon : 1);
}
}
//handle tree node selections
function bgTreeCall(component) {
//identify selected node
var s = component.getSelectedNode();
//check for
double-click
checkDblClick(s);
//toggle folder state on double-click
if (s.isBranch()
&& dClick) {
toggleOpen = ((s.isOpen()) ? false :
true);
s.setIsOpen(toggleOpen);
t.refresh();
saveBranches();
}
else {
//get new data on first
click
if
(!dClick) cD = s.getData();
//process
data
cD.update();
}
}
//restore tree to last saved state
function setBranches() {
fL = this.bg_so.data.folderList;
rO = this.bg_so.data.rootOpen;
if (fL == undefined) {
//define default state
t.getRootNode().setIsOpen(true);
} else {
t.getRootNode().setIsOpen(rO);
for(j=0; j<fL.length;
j++){
nextNode = t.getNodeAt(t.getRootNode(),
j);
nextNode.setIsOpen(fL[j]);
}
}
t.refresh();
}
//get tree status when a branch is
opened/closed
function saveBranches()
{
rOpen = t.getRootNode().isOpen();
bOpen = new Array();
bArray = t.getRootNode().getChildNodes();
for (j=0; j<bArray.length; j++) {
bOpen.push(bArray[j].isOpen());
}
//by defining these parameters as properties of the shared
//object they get automatically saved if the file gets
closed
this.bg_so.data.folderList = bOpen;
this.bg_so.data.rootOpen
= rOpen;
}
//check if a tree node was double-clicked
//set dClick to true if it was
function checkDblClick(s) {
var clickTime = getTimer();
dClick = ((clickTime-lastClick<300) && (lastSelected
== s));
lastClick = clickTime;
lastSelected = s;
}
function loadButtonCall() {
cD.loadSample();
}