/*! * Ext JS Library 3.3.1 * Copyright(c) 2006-2010 Sencha Inc. * [email protected] * http://www.sencha.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 = Ext.extend(Object, { constructor : function(node){ Ext.apply(this, { node: node, rendered: false, animating: false, wasLeaf: true, ecc: 'x-tree-ec-icon x-tree-elbow', emptyIcon: Ext.BLANK_IMAGE_URL }); }, // 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 onIconClsChange : function(node, cls, oldCls){ if(this.rendered){ Ext.fly(this.iconNode).replaceClass(oldCls, cls); } }, // private onIconChange : function(node, icon){ if(this.rendered){ //'', var empty = Ext.isEmpty(icon); this.iconNode.src = empty ? this.emptyIcon : icon; Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon'); } }, // private onTipChange : function(node, tip, title){ if(this.rendered){ var hasTitle = Ext.isDefined(title); if(this.textNode.setAttributeNS){ this.textNode.setAttributeNS("ext", "qtip", tip); if(hasTitle){ this.textNode.setAttributeNS("ext", "qtitle", title); } }else{ this.textNode.setAttribute("ext:qtip", tip); if(hasTitle){ this.textNode.setAttribute("ext:qtitle", title); } } } }, // private onHrefChange : function(node, href, target){ if(this.rendered){ this.anchor.href = this.getHref(href); if(Ext.isDefined(target)){ this.anchor.target = target; } } }, // private onClsChange : function(node, cls, oldCls){ if(this.rendered){ Ext.fly(this.elNode).replaceClass(oldCls, cls); } }, // private onDisableChange : function(node, state){ this.disabled = state; if (this.checkbox) { this.checkbox.disabled = state; } this[state ? 'addClass' : '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, oldParent != newParent); } },
/** * 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.onDisableChange(this.node, true); } 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.isExpandable()){ this.node.toggle(); } this.fireEvent("click", this.node, e); }else{ e.stopEvent(); } }, // private onDblClick : function(e){ e.preventDefault(); if(this.disabled){ return; } if(this.fireEvent("beforedblclick", this.node, e) !== false){ if(this.checkbox){ this.toggleCheck(); } if(!this.animating && this.node.isExpandable()){ 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; // fix for IE6 this.checkbox.defaultChecked = checked; this.node.attributes.checked = checked; this.fireEvent('checkchange', this.node, checked); }, // private ecClick : function(e){ if(!this.animating && this.node.isExpandable()){ 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{ 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} value (optional) The new checked status. */ toggleCheck : function(value){ var cb = this.checkbox; if(cb){ cb.checked = (value === undefined ? !cb.checked : value); this.onCheckChange(); } }, // private blur : function(){ try{ this.anchor.blur(); }catch(e){} }, // private animExpand : function(callback){ var ct = Ext.get(this.ctNode); ct.stopFx(); if(!this.node.isExpandable()){ 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; }, /** * Returns the element which encapsulates this node. * @return {HtmlElement} The DOM element. The default implementation uses a<li>
. */ 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){ this.onTipChange(n, a.qtip, 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 = Ext.isBoolean(a.checked), nel, href = this.getHref(a.href), 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 = '