/*
* Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
*
* http://extjs.com/license
*/
/**
* @class Ext.tree.TreeNodeUI This class provides the default UI implementation
* for Ext TreeNodes. The TreeNode UI implementation is separate from the
* tree implementation, and allows customizing of the appearance of tree
* nodes.
*
* If you are customizing the Tree's user interface, you may need to
* extend this class, but you should never need to instantiate this
* class.
*
* This class provides access to the user interface components of an Ext * TreeNode, through {@link Ext.tree.TreeNode#getUI} */ Ext.tree.TreeNodeUI = function(node) { this.node = node; this.rendered = false; this.animating = false; this.wasLeaf = true; this.ecc = 'x-tree-ec-icon x-tree-elbow'; this.emptyIcon = Ext.BLANK_IMAGE_URL; }; Ext.tree.TreeNodeUI.prototype = { // private removeChild : function(node) { if (this.rendered) { this.ctNode.removeChild(node.ui.getEl()); } }, // private beforeLoad : function() { this.addClass("x-tree-node-loading"); }, // private afterLoad : function() { this.removeClass("x-tree-node-loading"); }, // private onTextChange : function(node, text, oldText) { if (this.rendered) { this.textNode.innerHTML = text; } }, // private onDisableChange : function(node, state) { this.disabled = state; if (state) { this.addClass("x-tree-node-disabled"); } else { this.removeClass("x-tree-node-disabled"); } }, // private onSelectedChange : function(state) { if (state) { this.focus(); this.addClass("x-tree-selected"); } else { // this.blur(); this.removeClass("x-tree-selected"); } }, // private onMove : function(tree, node, oldParent, newParent, index, refNode) { this.childIndent = null; if (this.rendered) { var targetNode = newParent.ui.getContainer(); if (!targetNode) {// target not rendered this.holder = document.createElement("div"); this.holder.appendChild(this.wrap); return; } var insertBefore = refNode ? refNode.ui.getEl() : null; if (insertBefore) { targetNode.insertBefore(this.wrap, insertBefore); } else { targetNode.appendChild(this.wrap); } this.node.renderIndent(true); } }, /** * Adds one or more CSS classes to the node's UI element. Duplicate classes * are automatically filtered out. * * @param {String/Array} * className The CSS class to add, or an array of classes */ addClass : function(cls) { if (this.elNode) { Ext.fly(this.elNode).addClass(cls); } }, /** * Removes one or more CSS classes from the node's UI element. * * @param {String/Array} * className The CSS class to remove, or an array of classes */ removeClass : function(cls) { if (this.elNode) { Ext.fly(this.elNode).removeClass(cls); } }, // private remove : function() { if (this.rendered) { this.holder = document.createElement("div"); this.holder.appendChild(this.wrap); } }, // private fireEvent : function() { return this.node.fireEvent.apply(this.node, arguments); }, // private initEvents : function() { this.node.on("move", this.onMove, this); if (this.node.disabled) { this.addClass("x-tree-node-disabled"); } if (this.node.hidden) { this.hide(); } var ot = this.node.getOwnerTree(); var dd = ot.enableDD || ot.enableDrag || ot.enableDrop; if (dd && (!this.node.isRoot || ot.rootVisible)) { Ext.dd.Registry.register(this.elNode, { node : this.node, handles : this.getDDHandles(), isHandle : false }); } }, // private getDDHandles : function() { return [this.iconNode, this.textNode, this.elNode]; }, /** * Hides this node. */ hide : function() { this.node.hidden = true; if (this.wrap) { this.wrap.style.display = "none"; } }, /** * Shows this node. */ show : function() { this.node.hidden = false; if (this.wrap) { this.wrap.style.display = ""; } }, // private onContextMenu : function(e) { if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) { e.preventDefault(); this.focus(); this.fireEvent("contextmenu", this.node, e); } }, // private onClick : function(e) { if (this.dropping) { e.stopEvent(); return; } if (this.fireEvent("beforeclick", this.node, e) !== false) { var a = e.getTarget('a'); if (!this.disabled && this.node.attributes.href && a) { this.fireEvent("click", this.node, e); return; } else if (a && e.ctrlKey) { e.stopEvent(); } e.preventDefault(); if (this.disabled) { return; } if (this.node.attributes.singleClickExpand && !this.animating && this.node.hasChildNodes()) { this.node.toggle(); } this.fireEvent("click", this.node, e); } else { e.stopEvent(); } }, // private onDblClick : function(e) { e.preventDefault(); if (this.disabled) { return; } if (this.checkbox) { this.toggleCheck(); } if (!this.animating && this.node.hasChildNodes()) { this.node.toggle(); } this.fireEvent("dblclick", this.node, e); }, onOver : function(e) { this.addClass('x-tree-node-over'); }, onOut : function(e) { this.removeClass('x-tree-node-over'); }, // private onCheckChange : function() { var checked = this.checkbox.checked; this.node.attributes.checked = checked; this.fireEvent('checkchange', this.node, checked); }, // private ecClick : function(e) { if (!this.animating && (this.node.hasChildNodes() || this.node.attributes.expandable)) { this.node.toggle(); } }, // private startDrop : function() { this.dropping = true; }, // delayed drop so the click event doesn't get fired on a drop endDrop : function() { setTimeout(function() { this.dropping = false; }.createDelegate(this), 50); }, // private expand : function() { this.updateExpandIcon(); this.ctNode.style.display = ""; }, // private focus : function() { if (!this.node.preventHScroll) { try { this.anchor.focus(); } catch (e) { } } else if (!Ext.isIE) { try { var noscroll = this.node.getOwnerTree().getTreeEl().dom; var l = noscroll.scrollLeft; this.anchor.focus(); noscroll.scrollLeft = l; } catch (e) { } } }, /** * Sets the checked status of the tree node to the passed value, or, if no * value was passed, toggles the checked status. If the node was rendered * with no checkbox, this has no effect. * * @param {Boolean} * (optional) The new checked status. */ toggleCheck : function(value) { var cb = this.checkbox; if (cb) { cb.checked = (value === undefined ? !cb.checked : value); } }, // private blur : function() { try { this.anchor.blur(); } catch (e) { } }, // private animExpand : function(callback) { var ct = Ext.get(this.ctNode); ct.stopFx(); if (!this.node.hasChildNodes()) { this.updateExpandIcon(); this.ctNode.style.display = ""; Ext.callback(callback); return; } this.animating = true; this.updateExpandIcon(); ct.slideIn('t', { callback : function() { this.animating = false; Ext.callback(callback); }, scope : this, duration : this.node.ownerTree.duration || .25 }); }, // private highlight : function() { var tree = this.node.getOwnerTree(); Ext.fly(this.wrap).highlight(tree.hlColor || "C3DAF9", { endColor : tree.hlBaseColor }); }, // private collapse : function() { this.updateExpandIcon(); this.ctNode.style.display = "none"; }, // private animCollapse : function(callback) { var ct = Ext.get(this.ctNode); ct.enableDisplayMode('block'); ct.stopFx(); this.animating = true; this.updateExpandIcon(); ct.slideOut('t', { callback : function() { this.animating = false; Ext.callback(callback); }, scope : this, duration : this.node.ownerTree.duration || .25 }); }, // private getContainer : function() { return this.ctNode; }, // private getEl : function() { return this.wrap; }, // private appendDDGhost : function(ghostNode) { ghostNode.appendChild(this.elNode.cloneNode(true)); }, // private getDDRepairXY : function() { return Ext.lib.Dom.getXY(this.iconNode); }, // private onRender : function() { this.render(); }, // private render : function(bulkRender) { var n = this.node, a = n.attributes; var targetNode = n.parentNode ? n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom; if (!this.rendered) { this.rendered = true; this.renderElements(n, a, targetNode, bulkRender); if (a.qtip) { if (this.textNode.setAttributeNS) { this.textNode.setAttributeNS("ext", "qtip", a.qtip); if (a.qtipTitle) { this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle); } } else { this.textNode.setAttribute("ext:qtip", a.qtip); if (a.qtipTitle) { this.textNode.setAttribute("ext:qtitle", a.qtipTitle); } } } else if (a.qtipCfg) { a.qtipCfg.target = Ext.id(this.textNode); Ext.QuickTips.register(a.qtipCfg); } this.initEvents(); if (!this.node.expanded) { this.updateExpandIcon(true); } } else { if (bulkRender === true) { targetNode.appendChild(this.wrap); } } }, // private renderElements : function(n, a, targetNode, bulkRender) { // add some indent caching, this helps performance when rendering a // large tree this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : ''; var cb = typeof a.checked == 'boolean'; var href = a.href ? a.href : Ext.isGecko ? "" : "#"; var buf = [ '
* If you are customizing the Tree's user interface, you may need to
* extend this class, but you should never need to instantiate this
* class.
*/
Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
// private
render : function() {
if (!this.rendered) {
var targetNode = this.node.ownerTree.innerCt.dom;
this.node.expanded = true;
targetNode.innerHTML = '