Author: dr
Date: Tue Dec 18 10:16:45 2007
New Revision: 7019

Log:
- Add first draft of tree/yui article.

Added:
    docs/articles/2007-12-20-tree-yui.txt   (with props)
    docs/articles/files/article-2007-12-20-tree-yui.tar.gz   (with props)
    docs/articles/images/2007-12-20-menu1.png   (with props)
    docs/articles/images/2007-12-20-menu2.png   (with props)
    docs/articles/images/2007-12-20-menu3.png   (with props)
    docs/articles/images/2007-12-20-sprite.gif   (with props)

Added: docs/articles/2007-12-20-tree-yui.txt
==============================================================================
--- docs/articles/2007-12-20-tree-yui.txt (added)
+++ docs/articles/2007-12-20-tree-yui.txt [iso-8859-1] Tue Dec 18 10:16:45 2007
@@ -1,0 +1,682 @@
+======================================
+The Tree component and YUI integration
+======================================
+
+:Author: Derick Rethans
+:Date: 2007-12-20 10:39
+
+.. contents:: Table of Contents
+
+With the 2007.2 of eZ Components comes a new component: Tree_. This component
+allows you to create, manipulate and query tree structures in many ways.
+Besides this basic functionality the component also allows you to render the
+tree structure in different ways, with different visualisers. The
+ezcTreeVisitorPlainText_ class creates a simple representation of the tree
+structure, that can be used to display the structure on a console, and the
+ezcTreeVisitorGraphViz_ class creates GraphViz_ compatible output to generate
+an image representing your tree structure. A tree is often a good
+representation of the structure of a website as well, and therefore generating
+a menu out of it for your website is not such a strange idea. There are many
+different ways of doing so, but one of the nicer widgets is `YUI's`_ `menu
+widget`_. The Tree component also contains a YUI menu visualizer to easy
+creating menus for your website. The menu you see on http://ezcomponents.org/
+is also based on the Tree component combined with the YUI menu widget for
+example. This article demonstrates on how you can use the Tree component
+together with YUI to create a menu tool bar.
+
+.. _Tree: /docs/tutorials/Tree
+.. _ezcTreeVisitorPlainText: /s/ezcTreeVisitorPlainText
+.. _ezcTreeVisitorGraphViz: /s/ezcTreeVisitorGraphViz
+.. _GraphViz: http://www.graphviz.org/
+.. _`YUI's`: http://developer.yahoo.com/yui/
+.. _`menu widget`: http://developer.yahoo.com/yui/menu/
+
+YUI Introduction
+================
+
+The *Yahoo User Interface library* contains many widgets, and even many
+different kinds of menus. The Tree component's YUI visualization visitor
+(ezcTreeVisitorYUI_) deals with the "Website Top Nav With Submenus Built From
+Markup" menu only - at least for now. An example__ of this can be found on the
+YUI `menu widget`_ documentation site. The YUI widgets depend on a specific
+set of JavaScript files, that you can either copy to your local server or
+request directly from the Yahoo website. YUI also comes with a predefined
+stylesheet that **has** to be used as well, while it still allows re-styling
+with CSS. There is a guide on "skinning__" available on the YUI website, 
although
+it is a bit limited in what it explains. There is also all sorts of options
+available that change the behavior of the menu slightly.
+
+.. _ezcTreeVisitorYUI: /s/ezcTreeVisitorYUI
+__ http://developer.yahoo.com/yui/examples/menu/topnavfrommarkup_source.html
+__ http://developer.yahoo.com/yui/menu/#skinref
+
+
+The Menu
+========
+
+The menu that we will be using in this article is the same one as we
+use on the `eZ Components`_ website. It currently consists of a two
+dimensional menu. The top-level describes the section (Overview,
+Documentation, Download, Community, Support, Resources, Search and About), and
+the level underneath different pages (such as under Documentation:
+Installation Guide, Tutorials and API Reference).
+
+.. _`eZ Components`: http://ezcomponents.org/
+
+There are several ways of storing a tree structure with the Tree component.
+You can either use an `XML file`__ as tree definition, or one of the three
+database__ tree backends. As we will not have to manipulate the tree structure
+in our application, we will simply be using the ezcTreeXml class for tree
+storage in this article.
+
+__ /s/ezcTreeXml
+__ /s/ezcTreeDb
+
+Defining the structure
+----------------------
+
+Because we are using an XML file for the tree definition, it is important to
+know the allowed structure of the XML. Our tutorial__ already describes the
+format with a Relax-NG schema, but that can be somewhat hard to read. Below
+you will find a Relax-NG-Compressed schema::
+
+    default namespace = "http://components.ez.no/Tree";
+    namespace etd = "http://components.ez.no/Tree/data";
+
+    start =
+      element tree {
+        attribute prefix { xsd:ID }?,
+        node?
+      }
+    node =
+      element node {
+        attribute id { xsd:ID },
+        element etd:data { text }?,
+        node*
+      }
+
+With normal words, this schema means:
+
+#. The root node is the "tree" element, as defined by the "start" definition
+#. The "tree" element can have an optional attribute called "prefix"
+#. The "tree" element can have an optional "node" definition
+#. The "node" definition says that the "node" element requires the attribute 
"id"
+#. The "node" element can have an optional "data" element from the namespace 
"etd"
+#. The "node" element can have zero to many "node" elements as children
+
+__ /s/Tree
+
+As we're first looking at the structure only, we'll leave out the data parts
+for now. A part of the structure of our site as XML file looks like the
+following::
+
+    <?xml version="1.0" encoding="utf-8"?>
+    <!DOCTYPE tree PUBLIC "" "">
+    <tree xmlns="http://components.ez.no/Tree"; 
xmlns:etd="http://components.ez.no/Tree/data";>
+        <node id="root">
+            <node id="overview">
+                <node id="requirements"></node>
+                <node id="license"></node>
+                <node id="roadmap"></node>
+            </node>
+            <node id="docs">
+                <node id="install"></node>
+                <node id="tutorials"></node>
+                <node id="api"></node>
+            </node>
+            <node id="resources">
+                <node id="news"></node>
+                <node id="articles"></node>
+                <node id="presentations"></node>
+            </node>
+            <node id="search">
+            </node>
+        </node>
+    </tree>
+
+We can load the tree structure with the following code::
+
+    <?php
+    ini_set( 'include_path', '/home/derick/dev/ezcomponents/trunk:.' );
+    require 'Base/src/ezc_bootstrap.php';
+
+    // load the tree
+    $tree = new ezcTreeXml( 'tree.xml', new ezcTreeXmlInternalDataStore() );
+
+Fetching data then goes with::
+
+    // show the data in one of the nodes
+    $docs = $tree->fetchNodeById( 'docs' );
+    echo $docs->data, "\n";
+    ?>
+
+As we don't *have* any data associated with the tree yet, the last line will
+actually throw an exception now::
+
+    ezcTreeDataStoreMissingDataException: The data store does not have data 
stored
+    for the node with ID 'docs'. in
+    /home/derick/dev/ezcomponents/trunk/Tree/src/stores/xml_internal.php on 
line 80
+
+Adding data
+-----------
+
+The default XML-based data store that comes with the Tree component is
+accessed through the ezcTreeXmlInternalDataStore__ class. This data store
+stores the data as elements of the nodes, like::
+
+    <node id="search">
+        <etd:data>Search page</etd:data>
+    </node>
+
+However, for our website that is not enough, as we also need to know what type
+of document belongs to the node. In our case, that can be a PHP script, or a
+rendered reStructuredText__ file. For the eZ Components website we solve this
+by using a database store (ezcTreeDbDataStore__) as this can store the data in
+multiple columns of the same database table. However, in this tutorial we will
+be extending the ezcTreeXmlInternalDataStore class instead to allow for
+multiple "fields" of data. 
+
+__ /s/ezcTreeXmlInternalDataStore
+__ http://docutils.sourceforge.net/rst.html
+__ /s/ezcTreeDbDataStore
+
+Extending the data store
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To extend the data store, we simply create a class that inherits the
+ezcTreeXmlInternalDataStore class. Then we can use this while loading the
+tree::
+
+    <?php
+    ini_set( 'include_path', '/home/derick/dev/ezcomponents/trunk:.' );
+    require 'Base/src/ezc_bootstrap.php';
+
+    class ezcaTreeXmlDataStore extends ezcTreeXmlInternalDataStore
+    {
+    }
+
+    // load the tree
+    $tree = new ezcTreeXml( 'tree.xml', new ezcaTreeXmlDataStore() );
+
+As you can see from the example above, we created the ezcaTreeXmlDataStore
+class. Please note that the prefix of this class is not "ezc", but "ezca". We
+encourage that all classes *not* part of the eZ Components do *not* use the
+"ezc" prefix to prevent naming clashes. In this case we use "ezca", which
+stands for "eZ Components Article". When we run this example, nothing really
+has changed because we didn't reimplement the methods of the data store yet -
+i.e. the same exception is thrown when we want to load the data for a node
+with::
+
+    // show the data in one of the nodes
+    $docs = $tree->fetchNodeById( 'docs' );
+    echo $docs->data, "\n";
+    ?>
+
+The interface ezcTreeDataStore__ describes the methods that need to be
+implemented for each data store. 
+Because the data is embedded with XML data stores, we do not have to
+reimplement the deleteDataForAllNodes() and deleteDataForNodes() methods.
+They do not have any function because the data is already deleted as soon as a
+node is removed from the three. It
+still leaves three other methods to reimplement that deal with fetching
+and storing data. The method for storing data is actually only needed when the
+tree is manipulated by the script as well - we're not doing that so we won't
+reimplement this either. One of the two left over methods is now
+fetchDataForNodes(). This method simply loops over a ezcTreeNodeList__ and
+runs fetchDataForNode() for each of the nodes in the list. We can therefore
+get away by just reimplementing this one method.
+
+__ /s/ezcTreeDataStore
+__ /s/ezcTreeNodeList
+
+Instead of trying to parse complex XML structures, we're going to cheat a
+little bit. We will just store both bits of information (type of page and 
name) in
+the same text element, separated by a semicolon (:). Below is an example of
+how a node with its data attached then looks like::
+
+    <node id="resources">
+        <etd:data>rst:Resources</etd:data>
+    </node>
+    <node id="search">
+        <etd:data>php:Search</etd:data>
+    </node>
+
+The implementation of the fetchDataForNode() method is copied from the
+original file. The 2nd last line used to read::
+
+    $node->data = $dataElem->firstChild->data;
+
+In the reimplementation it looks like::
+
+    $node->data = split( ':', $dataElem->firstChild->data );
+
+Here is the script again, with the reimplemented method in place and the
+last line changed to allow dumping an array::
+
+    <?php
+    ini_set( 'include_path', '/home/derick/dev/ezcomponents/trunk:.' );
+    require 'Base/src/ezc_bootstrap.php';
+
+    class ezcaTreeXmlDataStore extends ezcTreeXmlInternalDataStore
+    {
+        /**
+         * Retrieves the data for the node $node from the data store and 
assigns it
+         * to the node's 'data' property.
+         *
+         * @param ezcTreeNode $node
+         */
+        public function fetchDataForNode( ezcTreeNode $node )
+        {
+            $id = $node->id;
+            $elem = $this->dom->getElementById( "{$node->tree->prefix}{$id}" );
+            $dataElem = $elem->getElementsByTagNameNS( 
'http://components.ez.no/Tree/data', 'data' )->item( 0 );
+            if ( $dataElem === null )
+            {
+                throw new ezcTreeDataStoreMissingDataException( $node->id );
+            }
+            $node->data = split( ':', $dataElem->firstChild->data );
+            $node->dataFetched = true;
+        }
+    }
+
+    // load the tree
+    $tree = new ezcTreeXml( 'tree.xml', new ezcaTreeXmlDataStore() );
+
+    // show the data in one of the nodes
+    $docs = $tree->fetchNodeById( 'docs' );
+    var_dump( $docs->data );
+    ?>
+
+Of course, for this to work, we also need to modify the tree.xml file as well,
+to include data for the node in question::
+
+    ...
+    <node id="docs">
+        <etd:data>rst:Documentation</etd:data>
+        ...
+    </node>
+    ...
+
+The output of the script is now::
+
+    array(2) {
+      [0]=>
+      string(3) "rst"
+      [1]=>
+      string(13) "Documentation"
+    }
+
+The full example can be found in the archive with examples with the filename
+``extend1.php``.
+
+Example renderings
+------------------
+
+To render the tree as a visually appeasing structure, there are a few
+classes. They implement the visitor pattern and can be used to walk over a
+tree and generate pretty output. The ezcTreeVisitorPlainText__ visitor renders
+a tree for a console based output. It also works fine for this tutorial. In
+the following example we use this visitor class to generate our output. We
+modify the above script and replace the "show the data in one of the nodes"
+part with::
+
+    // display the tree
+    $visitor = new ezcTreeVisitorPlainText();
+    $tree->accept( $visitor );
+    echo (string) $visitor;
+    ?>
+
+This produces the following output::
+
+    root
+    ├─overview
+    │ ├─requirements
+    │ ├─license
+    │ └─roadmap
+    ├─docs
+    │ ├─install
+    │ ├─tutorials
+    │ └─api
+    ├─resources
+    │ ├─news
+    │ ├─articles
+    │ └─presentations
+    └─search
+
+This example's source code can be found in the archive with examples with the
+filename ``visitor1.php``.
+
+Unfortunately, it does not seem to use the pretty names for all the nodes. In
+order to solve that, we need to subclass the ezcTreeVisitorPlainText__ class.
+We override the visit() method of this class as follows::
+
+    class ezcaTreeVisitorPlainText extends ezcTreeVisitorPlainText
+    {
+        public function visit( ezcTreeVisitable $visitable )
+        {
+            if ( $visitable instanceof ezcTreeNode )
+            {
+                if ( $this->root === null )
+                {
+                    $this->root = $visitable->data[1];
+                }
+
+                $parent = $visitable->fetchParent();
+                if ( $parent )
+                {
+                    $this->edges[$parent->data[1]][] = $visitable->data[1];
+                }
+            }
+            return true;
+        }
+    }
+
+The original class had instead of the ``->data[1]`` bits ``->id``.
+When we modify the original script to use to new inherited visitor,
+ezcaTreeVisitorPlainText, the output turns into the more pleasent display
+below::
+
+    Homepage
+    ├─Overview
+    │ ├─PHP Requirements
+    │ ├─License
+    │ └─Roadmap
+    ├─Documentation
+    │ ├─Installation Guide
+    │ ├─Tutorials
+    │ └─API Reference
+    ├─Resources
+    │ ├─News Archive
+    │ ├─Articles and Publications
+    │ └─Presentation Slides
+    └─Search
+
+The full example can be found in the archive with examples with the filename
+``extend2.php``.
+
+__ /s/ezcTreeVisitorPlainText
+__ /s/ezcTreeVisitorPlainText
+
+
+Adding the menu to the site
+===========================
+
+The YUI visitor works quite similar to the plain text visitor. Before we get
+there however, we need to integrate the YUI library into the website. 
+
+Adding the YUI bits
+-------------------
+
+First of all, you need to include the correct JavaScript. We run them directly
+from the Yahoo servers, but of course you can also just put them locally. The
+lines below should be placed in the "head" section of your HTML file::
+
+    <!-- Dependencies -->
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/yahoo-dom-event/yahoo-dom-event.js";></script>
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/container/container_core-min.js";></script>
+    <!-- Source File -->
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/menu/menu-min.js";></script>
+
+In the same "head" section you should also place the default CSS style sheets
+for the YUI menu::
+
+    <link rel="stylesheet" type="text/css" 
href="http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css"/>
+
+The two snippets above only make YUI accessible to you, but they do not
+actually do anything until you add some JavaScript to attach the YUI menu
+classes/JavaScript to the menu.
+
+Rendering the menu
+------------------
+
+The PHP code to generate the menu in the way YUI wants, is again very simple.
+We just use the ezcTreeVisiterYUI__ class instead of the
+ezcTreeVisitorPlainText class that we used before::
+
+    // display the tree
+    $visitor = new ezcTreeVisitorYUI( 'menu' );
+    $tree->accept( $visitor );
+    echo (string) $visitor;
+    ?>
+
+There is one other change, and that is the argument to ezcTreeVisitorYUI's
+constructor. This is the XHTML ID that is set on the top-level element that is
+used for rendering the menu. You will need to use the same ID when attaching
+the YUI JavaScript to the menu. 
+
+__ /s/ezcTreeVisiterYUI
+
+However, there is one other thing that we need to fix first. By default data
+stores return only a string, but we've modified the data store to return an
+array. Because of this the script will now output lots of warnings like::
+
+    Warning: htmlspecialchars() expects parameter 1 to be string, array given
+    in /home/derick/dev/ezcomponents/trunk/Tree/src/visitors/yui.php on line 
101
+
+In order to work around this, we need to extend the visitor class and override
+the formatData() method. We do that with the following code::
+
+    class ezcaTreeVisitorYUI extends ezcTreeVisitorYUI
+    {
+        protected function formatData( $data, $highlight )
+        {
+            $data = $data[1];
+            $data = htmlspecialchars( $data );
+            return $data;
+        }
+    }
+
+    // display the tree
+    $visitor = new ezcaTreeVisitorYUI( 'menu' );
+    $tree->accept( $visitor );
+    echo (string) $visitor;
+    ?>
+
+The script now outputs the XHTML content that the YUI JavaScript wants for
+rendering the menu. You can find this script in the archive with examples with
+the filename ``yui2.php``.
+
+To apply the YUI library and style sheets, we need to put one more thing in
+the head section of the website. This code attaches the YUI menu to the XHTML
+tag with the ID that we used before ("menu"). In the code below this "menu" ID
+returns in two places::
+
+    <script type="text/javascript">
+    YAHOO.util.Event.onContentReady('menu', function () {
+        var oMenu = new YAHOO.widget.MenuBar('menu', { autosubmenudisplay: 
true, showdelay: 200 });
+
+        oMenu.render();
+    });
+    </script>
+
+When we tie everything together, we end up with the following code to render
+the menu YUI style::
+
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+    <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+    <head>
+    <link rel="stylesheet" type="text/css" 
href="http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css"/>
+
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/yahoo-dom-event/yahoo-dom-event.js";></script>
 
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/container/container_core-min.js";></script>
 
+    <script type="text/javascript" 
src="http://yui.yahooapis.com/2.3.1/build/menu/menu-min.js";></script> 
+
+    <script type="text/javascript">
+    YAHOO.util.Event.onContentReady('overview', function () {
+        var oMenu = new YAHOO.widget.MenuBar("menu", { autosubmenudisplay: 
true, showdelay: 200 });
+
+        oMenu.render();
+    });
+    </script>
+    </head>
+    <body  class="yui-skin-sam">
+    <?php
+    ini_set( 'include_path', '/home/derick/dev/ezcomponents/trunk:.' );
+    require 'Base/src/ezc_bootstrap.php';
+
+    class ezcaTreeXmlDataStore extends ezcTreeXmlInternalDataStore
+    {
+        public function fetchDataForNode( ezcTreeNode $node )
+        {
+            $id = $node->id;
+            $elem = $this->dom->getElementById( "{$node->tree->prefix}{$id}" );
+            $dataElem = $elem->getElementsByTagNameNS( 
'http://components.ez.no/Tree/data', 'data' )->item( 0 );
+            if ( $dataElem === null )
+            {
+                throw new ezcTreeDataStoreMissingDataException( $node->id );
+            }
+            $node->data = split( ':', $dataElem->firstChild->data );
+            $node->dataFetched = true;
+        }
+    }
+
+    // load the tree
+    $tree = new ezcTreeXml( 'tree.xml', new ezcaTreeXmlDataStore() );
+
+    class ezcaTreeVisitorYUI extends ezcTreeVisitorYUI
+    {
+        protected function formatData( $data, $highlight )
+        {
+            $data = $data[1];
+            $data = htmlspecialchars( $data );
+            return $data;
+        }
+    }
+
+    // display the tree
+    $visitor = new ezcaTreeVisitorYUI( 'menu' );
+    $tree->accept( $visitor );
+    echo (string) $visitor;
+    ?>
+    </body>
+    </html>
+
+When rendered in the browser, it looks like:
+
+.. image:: ../../images/articles/2007-12-20-menu1.png
+
+
+Styling
+-------
+
+Styling the menu is done with CSS. The YUI widget's default CSS all use the
+*yui-skin-sam* "name space". Overriding just specific classes of YUI widgets
+is therefore quite easy. There are however a *lot* of different elements that
+needs restyling - so some advanced CSS skills might be required to get it how
+you want it to look. An excellent tool to assist you with this, is FireBug__.
+
+__ http://www.getfirebug.com/
+
+As an example, we're going to style the menu bar in the "eZ Components"
+colour: indigo. The first step is to change the border around the menu, and
+the background of the menu.
+We do that by overriding the following CSS::
+
+    .yui-skin-sam .yuimenubar {
+        border: 1px solid #55517b;
+        background: #55517b;
+    }
+
+    .yui-skin-sam .yuimenubaritemlabel {
+        border-color: #55517b;
+    }
+
+    .yui-skin-sam .yuimenu .bd {
+        background: #55517b;
+    }
+
+As the text is no longer readable, we change the text colour to white, and
+also change the font to a non-serif font::
+
+       .yui-skin-sam .yuimenubaritemlabel,
+       .yui-skin-sam .yuimenuitemlabel
+       {
+               font-family: sans-serif;
+               color: white;
+       }
+
+By now, the menu looks like:
+
+.. image:: ../../images/articles/2007-12-20-menu2.png
+
+Two things are left now. First of all, we need to change the background and
+text colour of selected items. This we simply can do with the following CSS::
+
+       .yui-skin-sam .yuimenubaritem a.selected {
+               background: #ffffff;
+               color: #55517b;
+       }
+
+The second thing is that we need to change the colour of the arrow on the
+right side of each menu to white for non-selected menu items. YUI uses a
+special trick for rendering images in their widgets. Instead of having a
+little image file for each element, they instead use a "sprite" file
+containing **all** the elements. From this they just cut out the part they
+need. Some information about this techinique can be found here__. As we want
+to change the arrow images, I created my own "sprite" to be used for those two
+elements. The sprite file is here__.
+
+The sprite file defines two arrows, that we are placing with CSS on the
+correct position::
+
+       .yui-skin-sam .yuimenubarnav .yuimenubaritemlabel .submenuindicator {
+               background-position:5px -21px;
+               height:8px;
+               left:auto;
+               margin-top:-3px;
+               right:8px;
+               text-indent:8px;
+               top:50%;
+               width:16px;
+       }   
+
+       .yui-skin-sam .yuimenuitemlabel .submenuindicator,
+       .yui-skin-sam .yuimenuitemlabel .checkedindicator,
+       .yui-skin-sam .yuimenubaritemlabel .submenuindicator {
+               background:transparent url(2007-12-20-sprite.gif) no-repeat 
scroll 0%;
+               overflow:hidden;
+               position:absolute;
+       }
+
+       .yui-skin-sam .yuimenubarnav a.selected .submenuindicator {
+               background:transparent url(2007-12-20-sprite.gif) repeat-x 
scroll 5px -5px;
+       }
+
+
+__ http://mattberseth.com/blog/2007/09/using_css_image_sprites_with_t.html
+__ ../../images/articles/2007-12-20-sprite.gif
+
+
+The end result of all the CSS tweaking looks like:
+
+.. image:: ../../images/articles/2007-12-20-menu3.png
+
+All the CSS overrides from above, can be found in the "ezc.css" file in the
+examples download. We still need to hook it into the HTML file though, which
+we do by adding the following line **after** the already existing stylesheet
+line for the default YUI styles::
+
+       <link rel="stylesheet" type="text/css" href="ezc.css"/>
+
+Conclusion
+==========
+
+In this article we showed how to integrate the Tree component with the Yahoo!
+UI Library's menu widget by generating the XHTML content that the YUI widget
+expects. From there on we explored on how the menu widget can be styled
+according to your wishes. There is plenty of other things that can be
+configured as well with the YUI menu, but that falls out of the scope of this
+article. See the `YUI documentation`__ for more information.
+
+__ http://developer.yahoo.com/yui/menu
+
+Resources
+=========
+
+* `Tree component documentation`__
+* `Yahoo! User Interface Library Menu`__
+* `CSS sprites explanation`__
+
+__ /s/Tree
+__ http://developer.yahoo.com/yui/menu
+__ http://mattberseth.com/blog/2007/09/using_css_image_sprites_with_t.html

Propchange: docs/articles/2007-12-20-tree-yui.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: docs/articles/files/article-2007-12-20-tree-yui.tar.gz
==============================================================================
Binary file - no diff available.

Propchange: docs/articles/files/article-2007-12-20-tree-yui.tar.gz
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: docs/articles/images/2007-12-20-menu1.png
==============================================================================
Binary file - no diff available.

Propchange: docs/articles/images/2007-12-20-menu1.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: docs/articles/images/2007-12-20-menu2.png
==============================================================================
Binary file - no diff available.

Propchange: docs/articles/images/2007-12-20-menu2.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: docs/articles/images/2007-12-20-menu3.png
==============================================================================
Binary file - no diff available.

Propchange: docs/articles/images/2007-12-20-menu3.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: docs/articles/images/2007-12-20-sprite.gif
==============================================================================
Binary file - no diff available.

Propchange: docs/articles/images/2007-12-20-sprite.gif
------------------------------------------------------------------------------
    svn:mime-type = image/gif


-- 
svn-components mailing list
svn-components@lists.ez.no
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to