Rss Feed
Tweeter button
Facebook button
Technorati button
Reddit button
Myspace button
Linkedin button
Webonews button
Delicious button
Digg button
Flickr button
Stumbleupon button
Newsvine button
Youtube button

Slick Flex Tree control

Actionscript, Flex Add comments

Following on from the recent post about automatically closing the open branches of the Tree control when you open a new branch; this is a slicker implementation that does the same thing but allows you to keep the animation. Currently the Flex control falls over if you try and animate multiple branches opening or closing.

Get Adobe Flash player

The main thing to point out here is that this example also works if you click the Tree disclosure icon (the little triangle) as well as the item. Most of the examples out there in the blogosphere that show you how to click on items to open branches forget that the disclosure button will open/close the branch and ignore the itemClick handler you’ve setup.

I listen for the itemOpening and itemClick events and pass on to a method called handleSelectedItem. This method then checks the depth of the selected item like so.

  1. var d:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(selectedItem)).listData).depth;

This looks crazy but you need to grab the itemRenderer’s listData property to find the depth of the object. It’s quite convoluted but you can grab the renderer with the Tree’s itemToItemRenderer method, cast it to the default TreeItemRenderer class and cast the listData property to the default TreeListData class to get the depth property off that … phew!

We need the depth because I only want to work with the root level branches which is level 1 in the case of a Tree. I then cycle through the Tree’s dataprovider which gives me the items in my XMLListCollection. These will correspond to the root level items as they are XML nodes with all of the children nodes (branches) in them. I can then look for siblings to the selected item using the getRoot method and close any open siblings.

  1. if(tree.isItemOpen(i) && i!=selectedItem && idepth==1 && isSibling)
  2.                   {
  3.                    tree.addEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  4.                    tree.expandItem(i,false,true,true); // CLOSE SIBLING
  5.                    openInstantly = false;
  6.                   }

I create an eventListener to listen for when the open root level branch is closed and because there will ever only be one branch closing I can use animation. The openInstantly Boolean prevents the selectedItem from opening … yet. When the closed item has finished I run a short Timer delay to make sure the animation listeners are all cleared and then open the selected item.

Here’s the Application class:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application
  3.  
  4.  xmlns:mx="http://www.adobe.com/2006/mxml"
  5.  layout="absolute"
  6.  width="200"
  7.  height="300"
  8.  >
  9.  
  10.  <mx:Script>
  11.  
  12.   <![CDATA[
  13.  
  14.   import mx.controls.treeClasses.TreeItemRenderer;
  15.   import org.osflash.thunderbolt.Logger;
  16.   import com.criticalmass.gucci.homepage.renderers.CustomTreeItemRenderer;
  17.   import mx.controls.listClasses.IListItemRenderer;
  18.   import mx.controls.treeClasses.TreeListData;
  19.  
  20.   import mx.collections.XMLListCollection;
  21.   import mx.events.TreeEvent;
  22.   import mx.controls.Tree;
  23.   import mx.events.ListEvent;
  24.  
  25.   private var dpx:XML = <nav>
  26.    
  27.    <node label="Womens">
  28.     <node label="Flora by Gucci" url="assets/swf/movies/flora.swf" />
  29.     <node label="Gucci by Gucci" url="assets/swf/movies/gucci.swf" />
  30.     <node label="Classics" url="assets/swf/movies/classics.swf" >
  31.      <node label="Classic 1" url="http://gucci.com/class/classic1.html" />
  32.      <node label="Classic 2" url="http://gucci.com/class/classic1.html" />
  33.      <node label="Classic 3" url="http://gucci.com/class/classic1.html" />
  34.     </node>
  35.    </node>
  36.    
  37.    <node label="Mens">
  38.     <node label="Pour Homme" url="assets/swf/movies/ph.swf" >
  39.      <node label="Pour Homme 1" url="http://gucci.com/ph/classic1.html" />
  40.      <node label="Pour Homme 2" url="http://gucci.com/ph/classic2.html" />
  41.     </node>
  42.    </node>
  43.    
  44.    <node label="Boys">
  45.     <node label="Pour Homme" url="assets/swf/movies/ph.swf" >
  46.      <node label="Pour Homme 1" url="http://gucci.com/ph/classic1.html" />
  47.      <node label="Pour Homme 2" url="http://gucci.com/ph/classic2.html" />
  48.     </node>
  49.    </node>
  50.    
  51.   </nav>;
  52.  
  53.   private var dp:XMLListCollection = new XMLListCollection(dpx.children());
  54.  
  55.   private var selectedItem:Object;
  56.  
  57.   private var timeDelay:Timer;
  58.  
  59.   //-----------------------------------------------------------------------------------
  60.   private function treeItemOpening(e:TreeEvent):void
  61.   {
  62.    if(!tree.isItemOpen(e.item))
  63.    {
  64.     selectedItem = e.item;
  65.     handleSelectedItem();
  66.    }
  67.   }
  68.   //-----------------------------------------------------------------------------------
  69.   private function treeItemClick(e:ListEvent):void
  70.   {
  71.                selectedItem = Tree(e.currentTarget).selectedItem;
  72.    handleSelectedItem();
  73.            }
  74.            
  75.            //-----------------------------------------------------------------------------------
  76.   private function handleSelectedItem():void
  77.   {
  78.    
  79.    var openItems:Array = tree.openItems as Array;
  80.             var openInstantly:Boolean = true;
  81.    
  82.                var d:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(selectedItem)).listData).depth;
  83.                
  84.                if(tree.dataDescriptor.isBranch(selectedItem))
  85.                {
  86.                 for each (var i:Object in tree.dataProvider)
  87.                 {
  88.                  var idepth:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(i)).listData).depth;
  89.      var isSibling:Boolean = XML(getRoot(i)).@label != XML(getRoot(selectedItem)).@label;        
  90.                  if(tree.isItemOpen(i) && i!=selectedItem && idepth==1 && isSibling)
  91.                  {
  92.                   tree.addEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  93.                   tree.expandItem(i,false,true,true); // CLOSE SIBLING
  94.                   openInstantly = false;
  95.                  }
  96.                 }
  97.                
  98.                 if(openInstantly) tree.expandItem(selectedItem,!tree.isItemOpen(selectedItem),true,false);
  99.                }
  100.                else
  101.                {
  102.                 // Clicked on an item -- DO STUFF!
  103.                }
  104.   }
  105.  
  106.   //-----------------------------------------------------------------------------------
  107.            /*
  108.             Function for accessing the Root item of the Tree
  109.            */
  110.            private function getRoot(childObj:Object):Object
  111.            {
  112.             var parentObj:Object = tree.getParentItem(childObj);
  113.             if(parentObj != null) return getRoot(parentObj);
  114.             else return childObj;
  115.            }
  116.  
  117.   //-----------------------------------------------------------------------------------
  118.   /*
  119.    Item closed handler
  120.   */
  121.   private function itemClosed(e:TreeEvent):void
  122.   {
  123.    tree.removeEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  124.    
  125.    timeDelay = new Timer(200,1);
  126.    timeDelay.addEventListener(TimerEvent.TIMER_COMPLETE,openSelectedItem);
  127.    timeDelay.start();
  128.   }
  129.   //-----------------------------------------------------------------------------------
  130.   private function openSelectedItem(e:TimerEvent):void
  131.   {
  132.    timeDelay.removeEventListener(TimerEvent.TIMER_COMPLETE,openSelectedItem);
  133.    if(selectedItem) tree.expandItem(selectedItem,true,true,false);
  134.   }
  135.  ]]>
  136.  </mx:Script>
  137.  
  138.  <mx:Tree
  139.  
  140.   id="tree"
  141.   width="200"
  142.   height="300"
  143.   dataProvider="{dp}"
  144.   labelField="@label"
  145.   itemClick="treeItemClick(event)"
  146.   itemOpening="treeItemOpening(event)"
  147.   />
  148.  
  149. </mx:Application>
Digg!
blog comments powered by Disqus
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in