Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / TreeNodeUI.html
diff --git a/docs/source/TreeNodeUI.html b/docs/source/TreeNodeUI.html
new file mode 100644 (file)
index 0000000..e1e86ed
--- /dev/null
@@ -0,0 +1,636 @@
+<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"><div id="cls-Ext.tree.TreeNodeUI"></div>/**\r
+ * @class Ext.tree.TreeNodeUI\r
+ * This class provides the default UI implementation for Ext TreeNodes.\r
+ * The TreeNode UI implementation is separate from the\r
+ * tree implementation, and allows customizing of the appearance of\r
+ * tree nodes.<br>\r
+ * <p>\r
+ * If you are customizing the Tree's user interface, you\r
+ * may need to extend this class, but you should never need to instantiate this class.<br>\r
+ * <p>\r
+ * This class provides access to the user interface components of an Ext TreeNode, through\r
+ * {@link Ext.tree.TreeNode#getUI}\r
+ */\r
+Ext.tree.TreeNodeUI = function(node){\r
+    this.node = node;\r
+    this.rendered = false;\r
+    this.animating = false;\r
+    this.wasLeaf = true;\r
+    this.ecc = 'x-tree-ec-icon x-tree-elbow';\r
+    this.emptyIcon = Ext.BLANK_IMAGE_URL;\r
+};\r
+\r
+Ext.tree.TreeNodeUI.prototype = {\r
+    // private\r
+    removeChild : function(node){\r
+        if(this.rendered){\r
+            this.ctNode.removeChild(node.ui.getEl());\r
+        } \r
+    },\r
+\r
+    // private\r
+    beforeLoad : function(){\r
+         this.addClass("x-tree-node-loading");\r
+    },\r
+\r
+    // private\r
+    afterLoad : function(){\r
+         this.removeClass("x-tree-node-loading");\r
+    },\r
+\r
+    // private\r
+    onTextChange : function(node, text, oldText){\r
+        if(this.rendered){\r
+            this.textNode.innerHTML = text;\r
+        }\r
+    },\r
+\r
+    // private\r
+    onDisableChange : function(node, state){\r
+        this.disabled = state;\r
+               if (this.checkbox) {\r
+                       this.checkbox.disabled = state;\r
+               }        \r
+        if(state){\r
+            this.addClass("x-tree-node-disabled");\r
+        }else{\r
+            this.removeClass("x-tree-node-disabled");\r
+        } \r
+    },\r
+\r
+    // private\r
+    onSelectedChange : function(state){\r
+        if(state){\r
+            this.focus();\r
+            this.addClass("x-tree-selected");\r
+        }else{\r
+            //this.blur();\r
+            this.removeClass("x-tree-selected");\r
+        }\r
+    },\r
+\r
+    // private\r
+    onMove : function(tree, node, oldParent, newParent, index, refNode){\r
+        this.childIndent = null;\r
+        if(this.rendered){\r
+            var targetNode = newParent.ui.getContainer();\r
+            if(!targetNode){//target not rendered\r
+                this.holder = document.createElement("div");\r
+                this.holder.appendChild(this.wrap);\r
+                return;\r
+            }\r
+            var insertBefore = refNode ? refNode.ui.getEl() : null;\r
+            if(insertBefore){\r
+                targetNode.insertBefore(this.wrap, insertBefore);\r
+            }else{\r
+                targetNode.appendChild(this.wrap);\r
+            }\r
+            this.node.renderIndent(true, oldParent != newParent);\r
+        }\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-addClass"></div>/**\r
+ * Adds one or more CSS classes to the node's UI element.\r
+ * Duplicate classes are automatically filtered out.\r
+ * @param {String/Array} className The CSS class to add, or an array of classes\r
+ */\r
+    addClass : function(cls){\r
+        if(this.elNode){\r
+            Ext.fly(this.elNode).addClass(cls);\r
+        }\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-removeClass"></div>/**\r
+ * Removes one or more CSS classes from the node's UI element.\r
+ * @param {String/Array} className The CSS class to remove, or an array of classes\r
+ */\r
+    removeClass : function(cls){\r
+        if(this.elNode){\r
+            Ext.fly(this.elNode).removeClass(cls);  \r
+        }\r
+    },\r
+\r
+    // private\r
+    remove : function(){\r
+        if(this.rendered){\r
+            this.holder = document.createElement("div");\r
+            this.holder.appendChild(this.wrap);\r
+        }  \r
+    },\r
+\r
+    // private\r
+    fireEvent : function(){\r
+        return this.node.fireEvent.apply(this.node, arguments);  \r
+    },\r
+\r
+    // private\r
+    initEvents : function(){\r
+        this.node.on("move", this.onMove, this);\r
+\r
+        if(this.node.disabled){\r
+            this.addClass("x-tree-node-disabled");\r
+                       if (this.checkbox) {\r
+                               this.checkbox.disabled = true;\r
+                       }            \r
+        }\r
+        if(this.node.hidden){\r
+            this.hide();\r
+        }\r
+        var ot = this.node.getOwnerTree();\r
+        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;\r
+        if(dd && (!this.node.isRoot || ot.rootVisible)){\r
+            Ext.dd.Registry.register(this.elNode, {\r
+                node: this.node,\r
+                handles: this.getDDHandles(),\r
+                isHandle: false\r
+            });\r
+        }\r
+    },\r
+\r
+    // private\r
+    getDDHandles : function(){\r
+        return [this.iconNode, this.textNode, this.elNode];\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-hide"></div>/**\r
+ * Hides this node.\r
+ */\r
+    hide : function(){\r
+        this.node.hidden = true;\r
+        if(this.wrap){\r
+            this.wrap.style.display = "none";\r
+        }\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-show"></div>/**\r
+ * Shows this node.\r
+ */\r
+    show : function(){\r
+        this.node.hidden = false;\r
+        if(this.wrap){\r
+            this.wrap.style.display = "";\r
+        } \r
+    },\r
+\r
+    // private\r
+    onContextMenu : function(e){\r
+        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {\r
+            e.preventDefault();\r
+            this.focus();\r
+            this.fireEvent("contextmenu", this.node, e);\r
+        }\r
+    },\r
+\r
+    // private\r
+    onClick : function(e){\r
+        if(this.dropping){\r
+            e.stopEvent();\r
+            return;\r
+        }\r
+        if(this.fireEvent("beforeclick", this.node, e) !== false){\r
+            var a = e.getTarget('a');\r
+            if(!this.disabled && this.node.attributes.href && a){\r
+                this.fireEvent("click", this.node, e);\r
+                return;\r
+            }else if(a && e.ctrlKey){\r
+                e.stopEvent();\r
+            }\r
+            e.preventDefault();\r
+            if(this.disabled){\r
+                return;\r
+            }\r
+\r
+            if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){\r
+                this.node.toggle();\r
+            }\r
+\r
+            this.fireEvent("click", this.node, e);\r
+        }else{\r
+            e.stopEvent();\r
+        }\r
+    },\r
+\r
+    // private\r
+    onDblClick : function(e){\r
+        e.preventDefault();\r
+        if(this.disabled){\r
+            return;\r
+        }\r
+        if(this.checkbox){\r
+            this.toggleCheck();\r
+        }\r
+        if(!this.animating && this.node.isExpandable()){\r
+            this.node.toggle();\r
+        }\r
+        this.fireEvent("dblclick", this.node, e);\r
+    },\r
+\r
+    onOver : function(e){\r
+        this.addClass('x-tree-node-over');\r
+    },\r
+\r
+    onOut : function(e){\r
+        this.removeClass('x-tree-node-over');\r
+    },\r
+\r
+    // private\r
+    onCheckChange : function(){\r
+        var checked = this.checkbox.checked;\r
+               // fix for IE6\r
+               this.checkbox.defaultChecked = checked;         \r
+        this.node.attributes.checked = checked;\r
+        this.fireEvent('checkchange', this.node, checked);\r
+    },\r
+\r
+    // private\r
+    ecClick : function(e){\r
+        if(!this.animating && this.node.isExpandable()){\r
+            this.node.toggle();\r
+        }\r
+    },\r
+\r
+    // private\r
+    startDrop : function(){\r
+        this.dropping = true;\r
+    },\r
+    \r
+    // delayed drop so the click event doesn't get fired on a drop\r
+    endDrop : function(){ \r
+       setTimeout(function(){\r
+           this.dropping = false;\r
+       }.createDelegate(this), 50); \r
+    },\r
+\r
+    // private\r
+    expand : function(){\r
+        this.updateExpandIcon();\r
+        this.ctNode.style.display = "";\r
+    },\r
+\r
+    // private\r
+    focus : function(){\r
+        if(!this.node.preventHScroll){\r
+            try{this.anchor.focus();\r
+            }catch(e){}\r
+        }else{\r
+            try{\r
+                var noscroll = this.node.getOwnerTree().getTreeEl().dom;\r
+                var l = noscroll.scrollLeft;\r
+                this.anchor.focus();\r
+                noscroll.scrollLeft = l;\r
+            }catch(e){}\r
+        }\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-toggleCheck"></div>/**\r
+ * Sets the checked status of the tree node to the passed value, or, if no value was passed,\r
+ * toggles the checked status. If the node was rendered with no checkbox, this has no effect.\r
+ * @param {Boolean} (optional) The new checked status.\r
+ */\r
+    toggleCheck : function(value){\r
+        var cb = this.checkbox;\r
+        if(cb){\r
+            cb.checked = (value === undefined ? !cb.checked : value);\r
+            this.onCheckChange();\r
+        }\r
+    },\r
+\r
+    // private\r
+    blur : function(){\r
+        try{\r
+            this.anchor.blur();\r
+        }catch(e){} \r
+    },\r
+\r
+    // private\r
+    animExpand : function(callback){\r
+        var ct = Ext.get(this.ctNode);\r
+        ct.stopFx();\r
+        if(!this.node.isExpandable()){\r
+            this.updateExpandIcon();\r
+            this.ctNode.style.display = "";\r
+            Ext.callback(callback);\r
+            return;\r
+        }\r
+        this.animating = true;\r
+        this.updateExpandIcon();\r
+        \r
+        ct.slideIn('t', {\r
+           callback : function(){\r
+               this.animating = false;\r
+               Ext.callback(callback);\r
+            },\r
+            scope: this,\r
+            duration: this.node.ownerTree.duration || .25\r
+        });\r
+    },\r
+\r
+    // private\r
+    highlight : function(){\r
+        var tree = this.node.getOwnerTree();\r
+        Ext.fly(this.wrap).highlight(\r
+            tree.hlColor || "C3DAF9",\r
+            {endColor: tree.hlBaseColor}\r
+        );\r
+    },\r
+\r
+    // private\r
+    collapse : function(){\r
+        this.updateExpandIcon();\r
+        this.ctNode.style.display = "none";\r
+    },\r
+\r
+    // private\r
+    animCollapse : function(callback){\r
+        var ct = Ext.get(this.ctNode);\r
+        ct.enableDisplayMode('block');\r
+        ct.stopFx();\r
+\r
+        this.animating = true;\r
+        this.updateExpandIcon();\r
+\r
+        ct.slideOut('t', {\r
+            callback : function(){\r
+               this.animating = false;\r
+               Ext.callback(callback);\r
+            },\r
+            scope: this,\r
+            duration: this.node.ownerTree.duration || .25\r
+        });\r
+    },\r
+\r
+    // private\r
+    getContainer : function(){\r
+        return this.ctNode;  \r
+    },\r
+\r
+    // private\r
+    getEl : function(){\r
+        return this.wrap;  \r
+    },\r
+\r
+    // private\r
+    appendDDGhost : function(ghostNode){\r
+        ghostNode.appendChild(this.elNode.cloneNode(true));\r
+    },\r
+\r
+    // private\r
+    getDDRepairXY : function(){\r
+        return Ext.lib.Dom.getXY(this.iconNode);\r
+    },\r
+\r
+    // private\r
+    onRender : function(){\r
+        this.render();    \r
+    },\r
+\r
+    // private\r
+    render : function(bulkRender){\r
+        var n = this.node, a = n.attributes;\r
+        var targetNode = n.parentNode ? \r
+              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;\r
+        \r
+        if(!this.rendered){\r
+            this.rendered = true;\r
+\r
+            this.renderElements(n, a, targetNode, bulkRender);\r
+\r
+            if(a.qtip){\r
+               if(this.textNode.setAttributeNS){\r
+                   this.textNode.setAttributeNS("ext", "qtip", a.qtip);\r
+                   if(a.qtipTitle){\r
+                       this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);\r
+                   }\r
+               }else{\r
+                   this.textNode.setAttribute("ext:qtip", a.qtip);\r
+                   if(a.qtipTitle){\r
+                       this.textNode.setAttribute("ext:qtitle", a.qtipTitle);\r
+                   }\r
+               } \r
+            }else if(a.qtipCfg){\r
+                a.qtipCfg.target = Ext.id(this.textNode);\r
+                Ext.QuickTips.register(a.qtipCfg);\r
+            }\r
+            this.initEvents();\r
+            if(!this.node.expanded){\r
+                this.updateExpandIcon(true);\r
+            }\r
+        }else{\r
+            if(bulkRender === true) {\r
+                targetNode.appendChild(this.wrap);\r
+            }\r
+        }\r
+    },\r
+\r
+    // private\r
+    renderElements : function(n, a, targetNode, bulkRender){\r
+        // add some indent caching, this helps performance when rendering a large tree\r
+        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';\r
+\r
+        var cb = typeof a.checked == 'boolean';\r
+\r
+        var href = a.href ? a.href : Ext.isGecko ? "" : "#";\r
+        var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',\r
+            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",\r
+            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',\r
+            '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',\r
+            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',\r
+            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',\r
+             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",\r
+            '<ul class="x-tree-node-ct" style="display:none;"></ul>',\r
+            "</li>"].join('');\r
+\r
+        var nel;\r
+        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){\r
+            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);\r
+        }else{\r
+            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);\r
+        }\r
+        \r
+        this.elNode = this.wrap.childNodes[0];\r
+        this.ctNode = this.wrap.childNodes[1];\r
+        var cs = this.elNode.childNodes;\r
+        this.indentNode = cs[0];\r
+        this.ecNode = cs[1];\r
+        this.iconNode = cs[2];\r
+        var index = 3;\r
+        if(cb){\r
+            this.checkbox = cs[3];\r
+                       // fix for IE6\r
+                       this.checkbox.defaultChecked = this.checkbox.checked;                                           \r
+            index++;\r
+        }\r
+        this.anchor = cs[index];\r
+        this.textNode = cs[index].firstChild;\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-getAnchor"></div>/**\r
+ * Returns the &lt;a> element that provides focus for the node's UI.\r
+ * @return {HtmlElement} The DOM anchor element.\r
+ */\r
+    getAnchor : function(){\r
+        return this.anchor;\r
+    },\r
+    \r
+<div id="method-Ext.tree.TreeNodeUI-getTextEl"></div>/**\r
+ * Returns the text node.\r
+ * @return {HtmlNode} The DOM text node.\r
+ */\r
+    getTextEl : function(){\r
+        return this.textNode;\r
+    },\r
+    \r
+<div id="method-Ext.tree.TreeNodeUI-getIconEl"></div>/**\r
+ * Returns the icon &lt;img> element.\r
+ * @return {HtmlElement} The DOM image element.\r
+ */\r
+    getIconEl : function(){\r
+        return this.iconNode;\r
+    },\r
+\r
+<div id="method-Ext.tree.TreeNodeUI-isChecked"></div>/**\r
+ * Returns the checked status of the node. If the node was rendered with no\r
+ * checkbox, it returns false.\r
+ * @return {Boolean} The checked flag.\r
+ */\r
+    isChecked : function(){\r
+        return this.checkbox ? this.checkbox.checked : false; \r
+    },\r
+\r
+    // private\r
+    updateExpandIcon : function(){\r
+        if(this.rendered){\r
+            var n = this.node, c1, c2;\r
+            var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";\r
+            var hasChild = n.hasChildNodes();\r
+            if(hasChild || n.attributes.expandable){\r
+                if(n.expanded){\r
+                    cls += "-minus";\r
+                    c1 = "x-tree-node-collapsed";\r
+                    c2 = "x-tree-node-expanded";\r
+                }else{\r
+                    cls += "-plus";\r
+                    c1 = "x-tree-node-expanded";\r
+                    c2 = "x-tree-node-collapsed";\r
+                }\r
+                if(this.wasLeaf){\r
+                    this.removeClass("x-tree-node-leaf");\r
+                    this.wasLeaf = false;\r
+                }\r
+                if(this.c1 != c1 || this.c2 != c2){\r
+                    Ext.fly(this.elNode).replaceClass(c1, c2);\r
+                    this.c1 = c1; this.c2 = c2;\r
+                }\r
+            }else{\r
+                if(!this.wasLeaf){\r
+                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");\r
+                    delete this.c1;\r
+                    delete this.c2;\r
+                    this.wasLeaf = true;\r
+                }\r
+            }\r
+            var ecc = "x-tree-ec-icon "+cls;\r
+            if(this.ecc != ecc){\r
+                this.ecNode.className = ecc;\r
+                this.ecc = ecc;\r
+            }\r
+        }\r
+    },\r
+    \r
+    // private\r
+    onIdChange: function(id){\r
+        if(this.rendered){\r
+            this.elNode.setAttribute('ext:tree-node-id', id);\r
+        }\r
+    },\r
+\r
+    // private\r
+    getChildIndent : function(){\r
+        if(!this.childIndent){\r
+            var buf = [];\r
+            var p = this.node;\r
+            while(p){\r
+                if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){\r
+                    if(!p.isLast()) {\r
+                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');\r
+                    } else {\r
+                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');\r
+                    }\r
+                }\r
+                p = p.parentNode;\r
+            }\r
+            this.childIndent = buf.join("");\r
+        }\r
+        return this.childIndent;\r
+    },\r
+\r
+    // private\r
+    renderIndent : function(){\r
+        if(this.rendered){\r
+            var indent = "";\r
+            var p = this.node.parentNode;\r
+            if(p){\r
+                indent = p.ui.getChildIndent();\r
+            }\r
+            if(this.indentMarkup != indent){ // don't rerender if not required\r
+                this.indentNode.innerHTML = indent;\r
+                this.indentMarkup = indent;\r
+            }\r
+            this.updateExpandIcon();\r
+        }\r
+    },\r
+\r
+    destroy : function(){\r
+        if(this.elNode){\r
+            Ext.dd.Registry.unregister(this.elNode.id);\r
+        }\r
+        delete this.elNode;\r
+        delete this.ctNode;\r
+        delete this.indentNode;\r
+        delete this.ecNode;\r
+        delete this.iconNode;\r
+        delete this.checkbox;\r
+        delete this.anchor;\r
+        delete this.textNode;\r
+        \r
+        if (this.holder){\r
+             delete this.wrap;\r
+             Ext.removeNode(this.holder);\r
+             delete this.holder;\r
+        }else{\r
+            Ext.removeNode(this.wrap);\r
+            delete this.wrap;\r
+        }\r
+    }\r
+};\r
+\r
+<div id="cls-Ext.tree.RootTreeNodeUI"></div>/**\r
+ * @class Ext.tree.RootTreeNodeUI\r
+ * This class provides the default UI implementation for <b>root</b> Ext TreeNodes.\r
+ * The RootTreeNode UI implementation allows customizing the appearance of the root tree node.<br>\r
+ * <p>\r
+ * If you are customizing the Tree's user interface, you\r
+ * may need to extend this class, but you should never need to instantiate this class.<br>\r
+ */\r
+Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {\r
+    // private\r
+    render : function(){\r
+        if(!this.rendered){\r
+            var targetNode = this.node.ownerTree.innerCt.dom;\r
+            this.node.expanded = true;\r
+            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';\r
+            this.wrap = this.ctNode = targetNode.firstChild;\r
+        }\r
+    },\r
+    collapse : Ext.emptyFn,\r
+    expand : Ext.emptyFn\r
+});</pre>    \r
+</body>\r
+</html>
\ No newline at end of file