Recursion, XML, and Flash Remoting for CFTree Components (Part 2)

In the previous entry, I showed how to make an XML document with a recursive function in a CFC. In this example, I show how to use the CFTree Form element of a CFForm to present the data as a Tree.

Behind the scenes

Setting up the Form.

I tend to use a low timeout value on the forms, without data preservation for development purposes. I also param th flash gateway here, to keep the AS a little tidier.

<cfparam name="request.gateway" default="http://<cfoutput>#cgi.HTTP_HOST#</cfoutput>/flashservices/gateway/">

<cfform name="myform" skin="haloblue" height="600" width="400" format="Flash" timeout="5" onload="setInit()" preservedata="no">

To make the call to the CFC and retrieve the XML document and connect it to the tree, I use actionscript. Thanks to the remoting and cfform tree examples at asfusion for the details on this!

I use event listeners here to make the connection when the form starts. Note the onload event handler in the CFform tag. In previous versions of CFMX 7, the way to get an action script to execute was to wrap it in cfsavecontent tags, and then dump the variable it was saved to into an onclick event handler for a button or another element. In later versions of CFMX7, you can make a cfformitem script type element (which is what I have done).

<cfformitem type="script">
function setInit()
{
setDefaultStyles();
treeLoader();
treeLoaderListener();   
}

Setting up some default styles for the tree :

function setDefaultStyles()
{
var categories = categories;
_global.styles.Tree.setStyle("backgroundColor", 0xFFFFFF);
_global.styles.Tree.setStyle("borderColor", 0xFFFFFF);
categories.setStyle("folderOpenIcon",folder_open.icon);
categories.setStyle("folderClosedIcon",folder_closed.icon);
categories.setStyle("defaultLeafIcon",leaf.icon);
categories.setStyle("disclosureOpenIcon", arrowDown.icon);
categories.setStyle("disclosureClosedIcon", arrow.icon);
}

Loading XML into the cftree using event Listeners :

function treeLoader()
{
vr categories = categories;
var createrListener = {};
createrListener.handleEvent = function(event){
var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection("<cfoutput>#request.gateway#</cfoutput>");
var myService:mx.remoting.NetServiceProxy;
var responseHandler = {};
responseHandler.getFolders_Result = function( results: Object ):Void {
categories.dataProvider = results;
categories.dispatchEvent({type: "custom"});
}
rsponseHandler.getFolders_Status = function( stat: Object ):Void {
alert("Error while calling cfc:" + stat.description);
)
myService = connection.getService("xmlCFCname", responseHandler );
myService.getFolders();
}
categories.addEventListener('creationComplete',createrListener);
}
The custom event listener that I made provides some functionality that I have not seen as an example anywhere yet. There are a lot of examples that show how to swap the icons, but in this example I have created an attribute in each of the XML nodes called "type". This is used the in the next function to swap out the Icon for each of the applicable nodes based on the type of node it is.

My "custom" event listener:

function treeLoaderListener()
{
var treeListenerListener = {};
treeListenerListener.handleEvent = function(event){
var categories = categories;
var i = 0;
var thisNode = categories.getNodeDisplayedAt(i);
var x = ""
while (thisNode != undefined){
categories.setIsOpen(thisNode,true);
x = categories.getNodeDisplayedAt(i).getProperty('type');
switch(x)
{
case "root node":
categories.setIcon(categories.getNodeDisplayedAt(i), _root.myhome.icon, _root.myhome.icon);
break;
case "page":
categories.setIcon(categories.getNodeDisplayedAt(i), _root.page.icon, _root.page.icon);
break;
};
i++;
thisNode=categories.getNodeDisplayedAt(i);
};
i=i-1;
x="";
thisNode=categories.getNodeDisplayedAt(i);
while (i != 0){
categories.setIsOpen(thisNode,false);
i=i-1;
thisNode=categories.getNodeDisplayedAt(i);
};
};
categories.addEventListener('custom',treeListenerListener);
}

And (finally) closing off the formitem tag :

</cfformitem>

The rest of the CFFORM:

<cftree name="categories" height="350" width="375" >
   <!--- an empty tree --->
   </cftree>
<cfinput type="text" label="Selected Item's Type :" name="display" bind="{categories.selectedNode.getProperty('type')}" disabled="true" style="borderStyle:none;disabledColor:##000000">
         
<cfinput type="text" label="Selected Item's ID :" name="display1" bind="{categories.selectedNode.getProperty('oID')}" disabled="true" style="borderStyle:none;disabledColor:##000000">
                  
                  
<cfinput type="Image" name="folder_open" src="icon_tree_folder_open.gif" visible="no">
<cfinput type="Image" name="folder_closed" src="icon_tree_folder_closed.gif" visible="no">
<cfinput type="Image" name="leaf" src="icon_page_gear.gif" visible="no">
<cfinput type="Image" name="arrow" src="icon_tree_expand.gif" visible="false" height="0" width="0">
<cfinput type="Image" name="arrowDown" src="icon_tree_contract.gif" visible="false" height="0" width="0">
<cfinput type="Image" name="myhome" src="house.png" visible="false" height="0" width="0">
<cfinput type="Image" name="page" src="icon_page_edit.gif" visible="false" height="0" width="0">
</cfform>

And example is here.

Also - thanks to Mark James at famfamfam.com for the icons :-)

Comments
wow cool! so effectively i can plug an xml document and get a tree going? is there any downloadable source available?

Thanks heaps!
# Posted By james | 5/11/07 8:00 PM
Hi James,

Check asfusion.com for downloadable source files - this is just a development website, and though I don't get a ton of hits I am somewhat limited as to what I want to post and not get hammered on for downloads....
# Posted By Cory | 5/11/07 9:27 PM