Flash MX Components: FTree Example Loading External XML

NEW: Get the recursive version of this example that supports
indefinit folder levels from bgx:components!!

download source

/* ===========
 * 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();
}

1