Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / TreeSelector.html
diff --git a/docs/source/TreeSelector.html b/docs/source/TreeSelector.html
new file mode 100644 (file)
index 0000000..225dc43
--- /dev/null
@@ -0,0 +1,291 @@
+<html>\r
+<head>\r
+  <title>The source code</title>\r
+    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
+</head>\r
+<body  onload="prettyPrint();">\r
+    <pre class="prettyprint lang-js">// custom menu item to contain Ext trees\r
+Ext.menu.TreeItem = Ext.extend(Ext.menu.Adapter, {\r
+       constructor : function(config){\r
+        Ext.menu.TreeItem.superclass.constructor.call(this, config.tree, config);\r
+        this.tree = this.component;\r
+        this.addEvents('selectionchange');\r
+\r
+        this.tree.on("render", function(tree){\r
+            tree.body.swallowEvent(['click','keydown', 'keypress', 'keyup']);\r
+        });\r
+\r
+        this.tree.getSelectionModel().on("selectionchange", this.onSelect, this);\r
+    },\r
+\r
+    onSelect : function(tree, sel){\r
+        this.fireEvent("select", this, sel, tree);\r
+    }\r
+});\r
+\r
+\r
+// custom menu containing a single tree\r
+Ext.menu.TreeMenu = Ext.extend(Ext.menu.Menu, {\r
+    cls:'x-tree-menu',\r
+       keyNav: true,\r
+       hideOnClick:false,\r
+    plain: true,\r
+\r
+    constructor : function(config){\r
+        Ext.menu.TreeMenu.superclass.constructor.call(this, config);\r
+        this.treeItem = new Ext.menu.TreeItem(config);\r
+        this.add(this.treeItem);\r
+\r
+        this.tree = this.treeItem.tree;\r
+        this.tree.on('click', this.onNodeClick, this);\r
+        this.relayEvents(this.treeItem, ["selectionchange"]);\r
+    },\r
+\r
+    // private\r
+    beforeDestroy : function() {\r
+        this.tree.destroy();\r
+    },\r
+       \r
+       onNodeClick : function(node, e){\r
+               if(!node.attributes.isFolder){\r
+                       this.treeItem.handleClick(e);\r
+               }\r
+       }\r
+});\r
+\r
+\r
+// custom form field for displaying a tree, similar to select or combo\r
+Ext.ux.TreeSelector = Ext.extend(Ext.form.TriggerField, {\r
+       initComponent : function(){\r
+               Ext.ux.TreeSelector.superclass.initComponent.call(this);\r
+               this.addEvents('selectionchange');\r
+\r
+               this.tree.getSelectionModel().on('selectionchange', this.onSelection, this);\r
+               this.tree.on({\r
+                       'expandnode': this.sync,\r
+                       'collapsenode' : this.sync,\r
+                       'append' : this.sync,\r
+                       'remove' : this.sync,\r
+                       'insert' : this.sync,\r
+                       scope: this\r
+               });\r
+               this.on('focus', this.onTriggerClick, this);\r
+    },\r
+\r
+       sync : function(){\r
+               if(this.menu && this.menu.isVisible()){\r
+                       if(this.tree.body.getHeight() > this.maxHeight){\r
+                               this.tree.body.setHeight(this.maxHeight);\r
+                               this.restricted = true;\r
+                       }else if(this.restricted && this.tree.body.dom.firstChild.offsetHeight < this.maxHeight){\r
+                               this.tree.body.setHeight('');\r
+                               this.restricted = false;\r
+                       }\r
+                       this.menu.el.sync();\r
+               }\r
+       },\r
+\r
+       onSelection : function(tree, node){\r
+               if(!node){\r
+                       this.setRawValue('');\r
+               }else{\r
+                       this.setRawValue(node.text);\r
+               }\r
+       },\r
+\r
+       initEvents : function(){\r
+               Ext.ux.TreeSelector.superclass.initEvents.call(this);\r
+               this.el.on('mousedown', this.onTriggerClick, this);\r
+               this.el.on("keydown", this.onKeyDown,  this);\r
+       },\r
+\r
+       onKeyDown : function(e){\r
+               if(e.getKey() == e.DOWN){\r
+                       this.onTriggerClick();\r
+               }\r
+       },\r
+\r
+    validateBlur : function(){\r
+        return !this.menu || !this.menu.isVisible();\r
+    },\r
+\r
+    getValue : function(){\r
+               var sm = this.tree.getSelectionModel();\r
+               var s = sm.getSelectedNode();\r
+        return s ? s.id : '';\r
+    },\r
+\r
+    setValue : function(id){\r
+               var n = this.tree.getNodeById(id);\r
+               if(n){\r
+                       n.select();\r
+               }else{\r
+                       this.tree.getSelectionModel().clearSelections();\r
+               }\r
+    },\r
+\r
+    // private\r
+    onDestroy : function(){\r
+        if(this.menu) {\r
+            this.menu.destroy();\r
+        }\r
+        if(this.wrap){\r
+            this.wrap.remove();\r
+        }\r
+        Ext.ux.TreeSelector.superclass.onDestroy.call(this);\r
+    },\r
+\r
+       // private\r
+    menuListeners : {\r
+        show : function(){ // retain focus styling\r
+            this.onFocus();\r
+        },\r
+        hide : function(){\r
+            this.focus.defer(10, this);\r
+            var ml = this.menuListeners;\r
+            this.menu.un("show", ml.show,  this);\r
+            this.menu.un("hide", ml.hide,  this);\r
+        }\r
+    },\r
+\r
+    onTriggerClick : function(){\r
+               if(this.disabled){\r
+            return;\r
+        }\r
+        this.menu.on(Ext.apply({}, this.menuListeners, {\r
+            scope:this\r
+        }));\r
+\r
+        this.menu.show(this.el, "tl-bl?");\r
+               this.sync();\r
+               var sm = this.tree.getSelectionModel();\r
+               var selected = sm.getSelectedNode();\r
+               if(selected){\r
+                       selected.ensureVisible();\r
+                       sm.activate.defer(250, sm, [selected]);\r
+               }\r
+    },\r
+\r
+    beforeBlur : function(){\r
+        //\r
+    },\r
+\r
+       onRender : function(){\r
+               Ext.ux.TreeSelector.superclass.onRender.apply(this, arguments);\r
+               this.menu = new Ext.menu.TreeMenu(Ext.apply(this.menuConfig || {}, {tree: this.tree}));\r
+               this.menu.render();\r
+\r
+               this.tree.body.addClass('x-tree-selector');\r
+       },\r
+\r
+       readOnly: true\r
+});\r
+\r
+/*\r
+ * Custom tree keyboard navigation that supports node navigation without selection\r
+ */\r
+Ext.tree.ActivationModel = Ext.extend(Ext.tree.DefaultSelectionModel, {\r
+       select : function(node){\r
+        return this.activate(Ext.tree.ActivationModel.superclass.select.call(this, node));\r
+    },\r
+    \r
+    activate : function(node){\r
+               if(!node){\r
+                       return;\r
+               }\r
+               if(this.activated != node) {\r
+                       if(this.activated){\r
+                               this.activated.ui.removeClass('x-tree-activated');\r
+                       }\r
+                       this.activated = node;\r
+                       node.ui.addClass('x-tree-activated');\r
+               }\r
+               node.ui.focus();\r
+               return node;    \r
+       },\r
+       \r
+       activatePrevious : function(){\r
+        var s = this.activated;\r
+        if(!s){\r
+            return null;\r
+        }\r
+        var ps = s.previousSibling;\r
+        if(ps){\r
+            if(!ps.isExpanded() || ps.childNodes.length < 1){\r
+                return this.activate(ps);\r
+            } else{\r
+                var lc = ps.lastChild;\r
+                while(lc && lc.isExpanded() && lc.childNodes.length > 0){\r
+                    lc = lc.lastChild;\r
+                }\r
+                return this.activate(lc);\r
+            }\r
+        } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){\r
+            return this.activate(s.parentNode);\r
+        }\r
+        return null;\r
+    },\r
+\r
+    activateNext : function(){\r
+        var s = this.activated;\r
+        if(!s){\r
+            return null;\r
+        }\r
+        if(s.firstChild && s.isExpanded()){\r
+             return this.activate(s.firstChild);\r
+         }else if(s.nextSibling){\r
+             return this.activate(s.nextSibling);\r
+         }else if(s.parentNode){\r
+            var newS = null;\r
+            s.parentNode.bubble(function(){\r
+                if(this.nextSibling){\r
+                    newS = this.getOwnerTree().selModel.activate(this.nextSibling);\r
+                    return false;\r
+                }\r
+            });\r
+            return newS;\r
+         }\r
+        return null;\r
+    },\r
+\r
+    onKeyDown : function(e){\r
+        var s = this.activated;\r
+        // undesirable, but required\r
+        var sm = this;\r
+        if(!s){\r
+            return;\r
+        }\r
+        var k = e.getKey();\r
+        switch(k){\r
+             case e.DOWN:\r
+                 e.stopEvent();\r
+                 this.activateNext();\r
+             break;\r
+             case e.UP:\r
+                 e.stopEvent();\r
+                 this.activatePrevious();\r
+             break;\r
+             case e.RIGHT:\r
+                 e.preventDefault();\r
+                 if(s.hasChildNodes()){\r
+                     if(!s.isExpanded()){\r
+                         s.expand();\r
+                     }else if(s.firstChild){\r
+                         this.activate(s.firstChild, e);\r
+                     }\r
+                 }\r
+             break;\r
+             case e.LEFT:\r
+                 e.preventDefault();\r
+                 if(s.hasChildNodes() && s.isExpanded()){\r
+                     s.collapse();\r
+                 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){\r
+                     this.activate(s.parentNode, e);\r
+                 }\r
+             break;\r
+        };\r
+    }\r
+});</pre>    \r
+</body>\r
+</html>
\ No newline at end of file