[Commits] r1309 - in sandbox/elemoine/playground/geoext: examples examples/resources examples/resources/img lib/GeoExt/widgets/tree tests/lib/GeoExt/widgets/tree

commits at geoext.org commits at geoext.org
Thu Aug 6 14:46:22 CEST 2009


Author: elemoine
Date: 2009-08-06 14:46:22 +0200 (Thu, 06 Aug 2009)
New Revision: 1309

Added:
   sandbox/elemoine/playground/geoext/examples/resources/
   sandbox/elemoine/playground/geoext/examples/resources/img/
   sandbox/elemoine/playground/geoext/examples/resources/img/delete.gif
   sandbox/elemoine/playground/geoext/examples/resources/img/info.png
   sandbox/elemoine/playground/geoext/examples/resources/img/move_down.png
   sandbox/elemoine/playground/geoext/examples/resources/img/move_up.png
   sandbox/elemoine/playground/geoext/examples/tree-tools.html
   sandbox/elemoine/playground/geoext/examples/tree-tools.js
Modified:
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
Log:
add "actions" and "component" support to layer node UI


Added: sandbox/elemoine/playground/geoext/examples/resources/img/delete.gif
===================================================================
(Binary files differ)


Property changes on: sandbox/elemoine/playground/geoext/examples/resources/img/delete.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/elemoine/playground/geoext/examples/resources/img/info.png
===================================================================
(Binary files differ)


Property changes on: sandbox/elemoine/playground/geoext/examples/resources/img/info.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/elemoine/playground/geoext/examples/resources/img/move_down.png
===================================================================
(Binary files differ)


Property changes on: sandbox/elemoine/playground/geoext/examples/resources/img/move_down.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/elemoine/playground/geoext/examples/resources/img/move_up.png
===================================================================
(Binary files differ)


Property changes on: sandbox/elemoine/playground/geoext/examples/resources/img/move_up.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/elemoine/playground/geoext/examples/tree-tools.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/tree-tools.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/tree-tools.html	2009-08-06 12:46:22 UTC (rev 1309)
@@ -0,0 +1,70 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>GeoExt Tree Components</title>
+        
+        <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+
+        <!--
+        <script type"text/javascript" src="../../ext/adapter/ext/ext-base.js"></script>
+        <script type"text/javascript" src="../../ext/ext-all-debug.js"></script>
+        <link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css"></script>
+        -->
+
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt.js"></script>
+
+        <script type="text/javascript" src="tree-tools.js"></script>
+
+        <style type="text/css">
+        .gx-tree-layer-actions{
+            float: right;
+        }
+        .gx-tree-layer-action {
+            background-position: center center;
+            background-repeat: no-repeat;
+            border: 0 none;
+            height: 16px;
+            margin: 0;
+            padding: 0;
+            vertical-align: top;
+            width: 16px;
+        }
+        .gx-tree-layer-actions .delete {
+            background: transparent url(resources/img/delete.gif);
+        }
+        .gx-tree-layer-actions .up {
+            background: transparent url(resources/img/move_up.png);
+        }
+        .gx-tree-layer-actions .down {
+            background: transparent url(resources/img/move_down.png);
+        }
+        .gx-tree-layer-actions .tbar {
+            background: transparent url(resources/img/info.png);
+        }
+        .gx-toolbar {
+            background: none;
+            border-style: none;
+        }
+        .x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .gx-tree-layer-icon {
+           width: 0px; !important;
+        }
+    </style>
+
+    </head>
+    <body>
+        <div id="desc">
+            <h1>GeoExt Tree Node UI</h1>
+
+            <p>This example shows how to add tools (actions) and components in
+            tree nodes. The tools added here allow moving the layers up and
+            down and deleting them. The component added for each node is a
+            toolbar including an opacity slider which acts on the node's
+            layer.</p>
+
+            <p>The js is not minified so it is readable. See
+            <a href="tree-tools.js">tree-tools.js</a>.</p>
+        </div>
+    </body>
+</html>

Added: sandbox/elemoine/playground/geoext/examples/tree-tools.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/tree-tools.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/tree-tools.js	2009-08-06 12:46:22 UTC (rev 1309)
@@ -0,0 +1,206 @@
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+Ext.namespace("GeoExt.examples");
+
+// this function creates a toolbar with a layer opacity
+// slider and an information button, it is used to
+// configure the layer node ui to add a toolbar
+// for each node in the layer tree
+GeoExt.examples.tbar = function(node, ct) {
+    return new Ext.Toolbar({
+        cls: "gx-toolbar",
+        buttons: [new GeoExt.LayerOpacitySlider({
+            layer: node.layer,
+            aggressive: true,
+            plugins: new GeoExt.LayerOpacitySliderTip(),
+            width: 100
+        })]
+    });
+};
+
+// this function takes action based on the "action"
+// parameter, it is used as a listener to layer
+// nodes' "action" events
+GeoExt.examples.act = function(node, action, evt) {
+    var layer = node.layer;
+    switch(action) {
+    case "down":
+        layer.map.raiseLayer(layer, -1);
+        break;
+    case "up":
+        layer.map.raiseLayer(layer, +1);
+        break;
+    case "delete":
+        layer.destroy();
+        break;
+    }
+};
+
+// a custom layer node UI class, for use with the second tree (see below).
+GeoExt.examples.CustomLayerNodeUI = Ext.extend(GeoExt.tree.LayerNodeUI, {
+    actions: [{
+        action: "delete",
+        qtip: "delete"
+    }, {
+        action: "up",
+        qtip: "move up"
+    }, {
+        action: "down",
+        qtip: "move down"
+    }],
+    component: GeoExt.examples.tbar
+});
+
+Ext.onReady(function() {
+    Ext.QuickTips.init();
+
+    // the map panel
+    var mapPanel = new GeoExt.MapPanel({
+        border: true,
+        region: "center",
+        center: [146.1569825, -41.6109735],
+        zoom: 6,
+        layers: [
+            new OpenLayers.Layer.WMS("Global Imagery",
+                "http://demo.opengeo.org/geoserver/wms", {
+                    layers: "bluemarble"
+                }, {
+                    buffer: 0,
+                    visibility: false
+                }),
+            new OpenLayers.Layer.WMS("Tasmania State Boundaries",
+                "http://demo.opengeo.org/geoserver/wms", {
+                    layers: "topp:tasmania_state_boundaries"
+                }, {
+                    buffer: 0
+               }),
+            new OpenLayers.Layer.WMS("Water",
+                "http://demo.opengeo.org/geoserver/wms", {
+                    layers: "topp:tasmania_water_bodies",
+                    transparent: true,
+                    format: "image/gif"
+                }, {
+                    isBaseLayer: false,
+                    buffer: 0
+                }),
+            new OpenLayers.Layer.WMS("Cities",
+                "http://demo.opengeo.org/geoserver/wms", {
+                    layers: "topp:tasmania_cities",
+                    transparent: true,
+                    format: "image/gif"
+                }, {
+                    isBaseLayer: false,
+                    buffer: 0
+                }),
+            new OpenLayers.Layer.WMS("Tasmania Roads",
+                "http://demo.opengeo.org/geoserver/wms", {
+                    layers: "topp:tasmania_roads",
+                    transparent: true,
+                    format: "image/gif"
+                }, {
+                    isBaseLayer: false,
+                    buffer: 0,
+                    // exclude this layer from layer container nodes
+                    displayInLayerSwitcher: false
+                })
+        ]
+    });
+
+    // the first layer tree panel. If this tree the node actions and
+    // component are set using the loader's "baseAttrs" property.
+    var tree1 = new Ext.tree.TreePanel({
+        border: true,
+        region: "center",
+        title: "Layer Tree 1",
+        split: true,
+        collapsible: true,
+        autoScroll: true,
+        loader: {
+            applyLoader: false
+        },
+        root: {
+            nodeType: "gx_layercontainer",
+            loader: {
+                baseAttrs: {
+                    actions: [{
+                        action: "delete",
+                        qtip: "delete"
+                    }, {
+                        action: "up",
+                        qtip: "move up"
+                    }, {
+                        action: "down",
+                        qtip: "move down"
+                    }],
+                    component: GeoExt.examples.tbar
+                }
+            }
+        },
+        rootVisible: false,
+        lines: false,
+        listeners: {
+            action: GeoExt.examples.act
+        }
+    });
+
+    // the second layer tree panel. In this tree the CustomLayerNodeUI
+    // class is used for each node of the layer container.
+    var tree2 = new Ext.tree.TreePanel({
+        border: true,
+        region: "south",
+        height: 300,
+        title: "Layer Tree 2",
+        split: true,
+        collapsible: true,
+        autoScroll: true,
+        loader: {
+            applyLoader: false
+        },
+        root: {
+            nodeType: "gx_layercontainer",
+            loader: {
+                uiProviders: {
+                    "ui": GeoExt.examples.CustomLayerNodeUI
+                },
+                baseAttrs: {
+                    uiProvider: "ui"
+                }
+            }
+        },
+        rootVisible: false,
+        lines: false,
+        listeners: {
+            action: GeoExt.examples.act
+        }
+    });
+
+    // the viewport
+    new Ext.Viewport({
+        layout: "fit",
+        hideBorders: true,
+        items: {
+            layout: "border",
+            deferredRender: false,
+            items: [
+                mapPanel, {
+                region: "west",
+                width: 250,
+                layout: "border",
+                items: [
+                    tree1,
+                    tree2
+                ]
+            }, {
+                region: "east",
+                contentEl: "desc",
+                width: 250
+            }]
+        }
+    });
+});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js	2009-08-05 15:35:51 UTC (rev 1308)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js	2009-08-06 12:46:22 UTC (rev 1309)
@@ -15,6 +15,18 @@
  */
 GeoExt.tree.LayerNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
     
+    /** private: constant[actionsCls]
+     */
+    actionsCls: "gx-tree-layer-actions",
+
+    /** private: constant[actionCls]
+     */
+    actionCls: "gx-tree-layer-action",
+
+    /** private: constant[componentCls]
+     */
+    componentCls: "gx-tree-layer-component",
+
     /** private: property[radio]
      *  ``Ext.Element``
      */
@@ -30,29 +42,72 @@
      *  :param bulkRender: ``Boolean``
      */
     render: function(bulkRender) {
-        var a = this.node.attributes;
-        if (a.checked === undefined) {
-            a.checked = this.node.layer.getVisibility();
+        var attr = this.node.attributes;
+        if (attr.checked === undefined) {
+            attr.checked = this.node.layer.getVisibility();
         }
+        var rendered = this.rendered;
         GeoExt.tree.LayerNodeUI.superclass.render.apply(this, arguments);
-        var cb = this.checkbox;
-        if (a.radioGroup && this.radio === null) {
-            this.radio = Ext.DomHelper.insertAfter(cb,
-                ['<input type="radio" class="gx-tree-layer-radio" name="',
-                a.radioGroup, '_radio"></input>'].join(""));
+        if (!rendered) {
+            var cb = this.checkbox;
+            if (attr.radioGroup && this.radio === null) {
+                this.radio = Ext.DomHelper.insertAfter(cb,
+                    ['<input type="radio" class="gx-tree-layer-radio" name="',
+                    attr.radioGroup, '_radio"></input>'].join(""));
+            }
+            if(attr.checkedGroup) {
+                // replace the checkbox with a radio button
+                var radio = Ext.DomHelper.insertAfter(cb,
+                    ['<input type="radio" name="', attr.checkedGroup,
+                    '_checkbox" class="', cb.className,
+                    cb.checked ? '" checked="checked"' : '',
+                    '"></input>'].join(""));
+                radio.defaultChecked = cb.defaultChecked;
+                Ext.get(cb).remove();
+                this.checkbox = radio;
+            }
+
+            this.enforceOneVisible();
+
+            var actions = attr.actions || this.actions;
+            if(actions && actions.length > 0) {
+                var html = ['<div class="', this.actionsCls, '">'];
+                for(var i=0,len=actions.length; i<len; i++) {
+                    var a = actions[i];
+                    html = html.concat([
+                        '<img id="'+this.node.id+'_'+a.action,
+                        '" ext:qtip="'+a.qtip,
+                        '" src="'+this.emptyIcon,
+                        '" class="'+this.actionCls+' '+a.action+'" />'
+                    ]);
+                }
+                html.concat(['</div>']);
+                Ext.DomHelper.insertFirst(this.elNode, html.join(""));
+            }
+
+            var component = attr.component || this.component;
+            if(component) {
+                var elt = Ext.DomHelper.append(this.elNode, [
+                    {"tag": "div"}
+                ]);
+                if(typeof component == "function") {
+                    component = component(this.node, elt);
+                } else if (typeof component == "object" &&
+                           typeof component.fn == "function") {
+                    component = component.fn.apply(
+                        component.scope, [this.node, elt]
+                    );
+                }
+                if(typeof component == "object" &&
+                   typeof component.xtype == "string") {
+                    component = Ext.ComponentMgr.create(component);
+                }
+                if(component instanceof Ext.Component) {
+                    component.render(elt);
+                    this.node.component = component;
+                }
+            }
         }
-        if(a.checkedGroup) {
-            // replace the checkbox with a radio button
-            var radio = Ext.DomHelper.insertAfter(cb,
-                ['<input type="radio" name="', a.checkedGroup,
-                '_checkbox" class="', cb.className,
-                cb.checked ? '" checked="checked"' : '',
-                '"></input>'].join(""));
-            radio.defaultChecked = cb.defaultChecked;
-            Ext.get(cb).remove();
-            this.checkbox = radio;
-        }
-        this.enforceOneVisible();
     },
     
     /** private: method[onClick]
@@ -63,6 +118,12 @@
             this.fireEvent("radiochange", this.node);
         } else if(e.getTarget('.x-tree-node-cb', 1)) {
             this.onCheckChange();
+        } else if(e.getTarget('.' + this.actionCls, 1)) {
+            var t = e.getTarget('.' + this.actionCls, 1);
+            var action = t.className.replace(this.actionCls + ' ', '');
+            if (this.fireEvent("action", this.node, action, e) === false) {
+                return;
+            }
         } else {
             GeoExt.tree.LayerNodeUI.superclass.onClick.apply(this, arguments);
         }

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-08-05 15:35:51 UTC (rev 1308)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-08-06 12:46:22 UTC (rev 1309)
@@ -186,7 +186,331 @@
             node.destroy();
             mapPanel.destroy();
         }
-        
+
+        function test_ui_node_action(t) {
+            t.plan(6);
+
+            // setup
+
+            var node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                actions: [{
+                    action: "foo-action",
+                    qtip: "foo-qtip"
+                }]
+            });
+            var tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            var ui = node.ui;
+            var elNode = Ext.fly(ui.elNode);
+
+            // test
+
+            t.ok(elNode.first().hasClass(ui.actionsCls),
+                 "the actions div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.first().first() &&
+                 elNode.first().first().hasClass(ui.actionCls) &&
+                 elNode.first().first().hasClass("foo-action"),
+                 "the action div is at correct location and " +
+                 "has correct classes");
+
+            // simulate click
+            var log = [];
+            node.on({
+                action: function(n, a, e) {
+                    log.push({n: n, a: a, e: e});
+                }
+            });
+            var e = {
+                getTarget: function(selector) {
+                    if (selector == "." + ui.actionCls) {
+                        return {
+                            className: ui.actionCls + " foo-action"
+                        };
+                    }
+                }
+            };
+            var oc = GeoExt.tree.LayerNodeUI.superclass.onClick;
+            GeoExt.tree.LayerNodeUI.superclass.onClick = function() {};
+            ui.onClick(e);
+            t.eq(log.length, 1,
+                 "click on action img triggers \"action\" event");
+            t.ok(log[0].n == node,
+                 "\"action\" listener given expected node");
+            t.eq(log[0].a, "foo-action",
+                 "\"action\" listener given expected action");
+            t.ok(log[0].e == e,
+                 "\"action\" listener given expected event");
+            GeoExt.tree.LayerNodeUI.superclass.onClick = oc;
+
+            // teardown
+
+            tree.destroy();
+        }
+
+        function test_ui_node_ui_action(t) {
+            t.plan(6);
+
+            // setup
+
+            var UI = Ext.extend(GeoExt.tree.LayerNodeUI, {
+                actions: [{
+                    action: "foo-action",
+                    qtip: "foo-qtip"
+                }]
+            });
+
+            var node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                uiProvider: UI
+            });
+            var tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            var ui = node.ui;
+            var elNode = Ext.fly(ui.elNode);
+
+            // test
+
+            t.ok(elNode.first().hasClass(ui.actionsCls),
+                 "the actions div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.first().first() &&
+                 elNode.first().first().hasClass(ui.actionCls) &&
+                 elNode.first().first().hasClass("foo-action"),
+                 "the action div is at correct location and " +
+                 "has correct classes");
+
+            // simulate click
+            var log = [];
+            node.on({
+                action: function(n, a, e) {
+                    log.push({n: n, a: a, e: e});
+                }
+            });
+            var e = {
+                getTarget: function(selector) {
+                    if (selector == "." + ui.actionCls) {
+                        return {
+                            className: ui.actionCls + " foo-action"
+                        };
+                    }
+                }
+            };
+            var oc = GeoExt.tree.LayerNodeUI.superclass.onClick;
+            GeoExt.tree.LayerNodeUI.superclass.onClick = function() {};
+            ui.onClick(e);
+            t.eq(log.length, 1,
+                 "click on action img triggers \"action\" event");
+            t.ok(log[0].n == node,
+                 "\"action\" listener given expected node");
+            t.eq(log[0].a, "foo-action",
+                 "\"action\" listener given expected action");
+            t.ok(log[0].e == e,
+                 "\"action\" listener given expected event");
+            GeoExt.tree.LayerNodeUI.superclass.onClick = oc;
+
+            // teardown
+
+            tree.destroy();
+        }
+
+        function test_ui_component_instance(t) {
+            t.plan(4);
+
+            // setup
+
+            var component = new Ext.Panel({
+                id: "foo-id",
+                cls: "foo-cls",
+                ctCls: "foo-ct-cls"
+            });
+            var node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                component: component
+            });
+            var tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            var ui = node.ui;
+            var elNode = Ext.fly(ui.elNode);
+
+            // test
+            t.ok(elNode.last().hasClass("foo-ct-cls"),
+                 "the container div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.last().child("#foo-id"),
+                 "the container div contains the panel div");
+            t.ok(elNode.last().child("#foo-id") &&
+                 elNode.last().child("#foo-id").hasClass("foo-cls"),
+                 "the panel div has a correct class");
+            t.ok(node.component === component,
+                 "the component is set in the node");
+
+            // teardown
+
+            tree.destroy();
+        }
+
+        function test_ui_component_config(t) {
+            t.plan(3);
+
+            // setup
+
+            var component = {
+                xtype: "panel",
+                cls: "foo-cls",
+                ctCls: "foo-ct-cls"
+            };
+            var node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                component: component
+            });
+            var tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            var ui = node.ui;
+            var elNode = Ext.fly(ui.elNode);
+
+            // test
+            t.ok(elNode.last().hasClass("foo-ct-cls"),
+                 "the container div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.last().child(".foo-cls") ,
+                 "the container div contains the panel div, " +
+                 "which has a correct class");
+            t.ok(node.component instanceof Ext.Panel,
+                 "the component is set in the node");
+
+            // teardown
+
+            tree.destroy();
+        }
+
+        function test_ui_component_function(t) {
+            t.plan(16);
+
+            // setup
+
+            var component, node, tree, ui, elNode, log;
+
+            // test
+
+            // with a function returning a panel config
+            log = [];
+            component = function(n, e) {
+                log.push({n: n, e: e});
+                return {
+                    xtype: "panel",
+                    cls: "foo-cls",
+                    ctCls: "foo-ct-cls"
+                };
+            };
+            node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                component: component
+            });
+            tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            ui = node.ui;
+            elNode = Ext.fly(ui.elNode);
+            t.eq(log.length, 1,
+                 "[1] factory function called once");
+            t.ok(log.length > 0 && log[0].n === node,
+                 "[1] factory function called with node");
+            t.ok(elNode.last().hasClass("foo-ct-cls"),
+                 "[1] the container div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.last().child(".foo-cls") ,
+                 "[1] the container div contains the panel div, " +
+                 "which has a correct class");
+            t.ok(node.component instanceof Ext.Panel,
+                 "[1] the component is set in the node");
+            tree.destroy();
+
+            // with a function returning a panel instance
+            log = [];
+            component = function(n, e) {
+                log.push({n: n, e: e});
+                return new Ext.Panel({
+                    cls: "foo-cls",
+                    ctCls: "foo-ct-cls"
+                });
+            };
+            node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                component: component
+            });
+            tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            ui = node.ui;
+            elNode = Ext.fly(ui.elNode);
+            t.eq(log.length, 1,
+                 "[2] factory function called once");
+            t.ok(log.length > 0 && log[0].n === node,
+                 "[2] factory function called with node");
+            t.ok(elNode.last().hasClass("foo-ct-cls"),
+                 "[2] the container div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.last().child(".foo-cls") ,
+                 "[2] the container div contains the panel div, " +
+                 "which has a correct class");
+            t.ok(node.component instanceof Ext.Panel,
+                 "[2] the component is set in the node");
+            tree.destroy();
+
+            // with an object with fn and scope properties
+            log = [];
+            var scope = {"some": "scope"};
+            component = {
+                fn: function(n, e) {
+                    log.push({n: n, e: e, s: this});
+                    return new Ext.Panel({
+                        cls: "foo-cls",
+                        ctCls: "foo-ct-cls"
+                    });
+                },
+                scope: scope
+            };
+            node = new GeoExt.tree.LayerNode({
+                layer: new OpenLayers.Layer(),
+                component: component
+            });
+            tree  = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node
+            });
+            ui = node.ui;
+            elNode = Ext.fly(ui.elNode);
+            t.eq(log.length, 1,
+                 "[3] factory function called once");
+            t.ok(log.length > 0 && log[0].n === node,
+                 "[3] factory function called with node");
+            t.ok(log.length > 0 && log[0].s === scope,
+                 "[3] factory function called with correct scope");
+            t.ok(elNode.last().hasClass("foo-ct-cls"),
+                 "[3] the container div is at correct location and " +
+                 "has a correct class");
+            t.ok(elNode.last().child(".foo-cls") ,
+                 "[3] the container div contains the panel div, " +
+                 "which has a correct class");
+            t.ok(node.component instanceof Ext.Panel,
+                 "[3] the component is set in the node");
+            tree.destroy();
+
+            // teardown
+        }
+    
         </script>
     </head>
     <body>



More information about the Commits mailing list