bgx:components logo
© 2004 -2005
Bernhard Gaul



Bgx Xml Serialization Classes (Flash MX 2004) : Complex Tree and DataGrid example

Flash output

 

This example corresponds with the file TreeExample.fla that is supplied with the component. The following code loads the XML file sample.xml, parses it using the BgxDesObject class and then populates an instance of the Macromedia Tree component called bgxTree with the folder and page nodes of the XML.

It assigns click actions that display the label name and an active hyperlink in case of page nodes, a DataGrid with the list of child pages in case od folder nodes.

It further assigns double-click actions that expand/collapse folder nodes and load the associated page for page nodes.

Note: The Tree component allows very easy population of a tree by simply binding the XML directly to it, with XML elements containing label, data and isBranch attributes. Apart from the fact that it might not suit you to have those attributes in the XML or it would mean previous recursive parsing of the XML to add them, you cannot add complex data as treeNode data via a data attribute. The code below adds the node objects themselves as treeNode data. Therefore, if a node is clicked all data associated with that node is instantly available (see the line var newNode = treeNode.addTreeNode(nodeName,elementsArray[i]);)

Note also that within the setDisplay() function the nodeName property, added automatically if addNodeName is set to true, is used to determine whether a treeNode corresponds to an element of type folder (see  if (dataObject.nodeName == "folder")).

The following is only one way how a tree can be populated. It will depend on the actual structure of the XML data or other parameters, like what kind of interaction is needed, do determine the best route on a case by case basis.

[history]

//import the class
import bgx.BgxDesObject;
import mx.controls.Tree;

//hide DataGrid
dgPages._visible = false;

//global variable to hold deserialized sample data
var SampleData:Object;
initDisplay();

//load xml from external file
var sampleXML:XML = new XML();
sampleXML.ignoreWhite = true;
sampleXML.onLoad = parseSampleData;
sampleXML.load("sample.xml");

//parse sample data
function parseSampleData() {
    var rootNode:XMLNode = sampleXML.firstChild;
    SampleData = new BgxDesObject();
    SampleData.xmlNode = rootNode;
    SampleData.onParsed = populateTree;
    SampleData.parse();
}

function populateTree(includeRoot:Boolean)
{
    //Variation 1: add all pages and folders below the root node
    addTreeNodes(SampleData,bgxTree);
    //Variation 2: start with the site root and add all pages
    //and folders beneath it
    //var newNode = bgxTree.addTreeNode( SampleData.label, SampleData);
    //addTreeNodes(SampleData,newNode);

}

function addTreeNodes(elements:Object,treeNode:Tree)
{
    for (var element in elements)
    {
        //get the elements of the original XML, which are arrays within the parsed
        //SampleData and therefore of type "object"
        //also filter out "bgx_cln_comment" and "exampleNode"

        if (typeof elements[element] == "object" &&
            element != "bgx_cln_comment" &&
            element != "exampleNode")
        {
            //loop through the elements array to add each item as tree node
            var elementsArray = elements[element];
            for (var i = 0; i < elementsArray.length; i++)
            {
                //use the label property as nodeName
                var nodeName = elementsArray[i].label;

                if (element == "page")
                {
                    // add pages on top
                    var newNode = treeNode.addTreeNodeAt(0,nodeName,elementsArray[i]);
                }
                else
                {
                    //add the node to the tree, setting the whole object as its data
                    var newNode = treeNode.addTreeNode(nodeName,elementsArray[i]);
                }

                //make sure that folder nodes appear as branches, even if they
                //don't have further children in the XML

                var isBranch = (element == "folder");
                bgxTree.setIsBranch(newNode,isBranch);

                //recursive call to add child nodes
                addTreeNodes(elementsArray[i],newNode);
            }
        }
    }
}

function initDisplay()
{
    //assign tree change event to setDisplay()
    treeListenerObject = new Object();
    treeListenerObject.change = function(evtObject){
        setDisplay(bgxTree.selectedNode,evtObject.target.selectedItem.attributes.data);
    }
    bgxTree.addEventListener("change", treeListenerObject);

    //identify the attributes that shall appear in the DataGrid columns
    dgPages.columnNames= ["label", "URL"];
    //define some display parameters
    dgPages.getColumnAt(0).width = 170;
    dgPages.getColumnAt(1).width = 320;
    dgPages.getColumnAt(0).headerText = "Pages";
    dgPages.getColumnAt(1).headerText = "URL";

    //define an event listener that loads the page URL
    //when a row is double-clicked.

    var dgListener = new Object();
    dgListener.cellPress = function(event) {
        //you can use the itemIndex that is submitted by the event
        //to identify the page data within the SampleData Object

        var itemData = dgPages.dataProvider[event.itemIndex];
        if (checkDblClick(itemData)) getURL(itemData.URL,"_blank");
    };
    dgPages.addEventListener("cellPress", dgListener);
}

function setDisplay(treeNode,dataObject)
{
    //double-click action
    if (checkDblClick(dataObject))
    {
        //load pages if they have an URL
        if (typeof dataObject.URL != "undefined")
        {
            getURL(dataObject.URL,"_blank");
        }
        //toggle branches on double-click
        if (bgxTree.getIsBranch(treeNode)) bgxTree.setIsOpen(treeNode,!bgxTree.getIsOpen(treeNode));
    }
    //set display
    itemTitle.text = dataObject.label;
    //display pages in the DataGrid for folders
    if (dataObject.nodeName == "folder")
    {
        dgPages.dataProvider = dataObject.page;
        dgPages._visible = true;
        itemURL.text = "";
    }
    else
    {
        dgPages._visible = false;
    }
    //display the URL as Hyperlink for pages
    if (dataObject.nodeName != "page")
    {
        itemURL.text = "";
    }
    else
    {
        itemURL.htmlText = "<a href='" + dataObject.URL + "' target='_blank'><u>" + dataObject.URL + "</u></a>";
    }
}

//----Utility double-click
//global variables
var lastClick = 0;
var lastSelected;

//check if an object was double-clicked
function checkDblClick(pObj):Boolean
{
    var clickTime = getTimer();
    var dClick = ((clickTime-lastClick<400) && (lastSelected == pObj));
    lastClick = clickTime;
    lastSelected = pObj;
    return dClick;
}
//----End utility double-click

History

5 June 2004
Changed the datatype of treeNode in the line function addTreeNodes(elements:Object,treeNode:Tree) from XML to Tree (I couldn't find a type TreeNode for the Tree component). This also requires to add import mx.controls.Tree; at the top of the code.

Reason: This example works fine in both cases but I worked on other tree examples since that require the identification of a Treenode's parent. As the Tree component does not provide an interface for that I use the parentNode attribute (added by the BgxDesObject Class) of the object stored as data. If treeNode is typed as XML this does not return the parentNode the BgxDesObject Class created. Frankly the type should not have been XML in the first place.

4 January 2005
Changed code to list pages above folders. Thanks to James Jefferson for the suggestion.

For further information please contact info@bgxcomponents.com.

 

BGX Serialization Classes


View the documentation

 

Buy now