/* * Based on: * Ext JS Library 1.1.1 * Copyright(c) 2006-2007, Ext JS, LLC. * * Originally Released Under LGPL - original licence link has changed is not relivant. * * Fork - LGPL * <script type="text/javascript"> */ /** * @class Roo.tree.TreeNodeUI * @constructor * @param {Object} node The node to render * The TreeNode UI implementation is separate from the * tree implementation. Unless you are customizing the tree UI, * you should never have to use this directly. */ Roo.tree.TreeNodeUI = function(node){ this.node = node; this.rendered = false; this.animating = false; this.emptyIcon = Roo.BLANK_IMAGE_URL; }; Roo.tree.TreeNodeUI.prototype = { removeChild : function(node){ if(this.rendered){ this.ctNode.removeChild(node.ui.getEl()); } }, beforeLoad : function(){ this.addClass("x-tree-node-loading"); }, afterLoad : function(){ this.removeClass("x-tree-node-loading"); }, onTextChange : function(node, text, oldText){ if(this.rendered){ this.textNode.innerHTML = text; } }, onDisableChange : function(node, state){ this.disabled = state; if(state){ this.addClass("x-tree-node-disabled"); }else{ this.removeClass("x-tree-node-disabled"); } }, onSelectedChange : function(state){ if(state){ this.focus(); this.addClass("x-tree-selected"); }else{ //this.blur(); this.removeClass("x-tree-selected"); } }, 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); } }, addClass : function(cls){ if(this.elNode){ Roo.fly(this.elNode).addClass(cls); } }, removeClass : function(cls){ if(this.elNode){ Roo.fly(this.elNode).removeClass(cls); } }, remove : function(){ if(this.rendered){ this.holder = document.createElement("div"); this.holder.appendChild(this.wrap); } }, fireEvent : function(){ return this.node.fireEvent.apply(this.node, arguments); }, initEvents : function(){ this.node.on("move", this.onMove, this); var E = Roo.EventManager; var a = this.anchor; var el = Roo.fly(a, '_treeui'); if(Roo.isOpera){ // opera render bug ignores the CSS el.setStyle("text-decoration", "none"); } el.on("click", this.onClick, this); el.on("dblclick", this.onDblClick, this); if(this.checkbox){ Roo.EventManager.on(this.checkbox, Roo.isIE ? 'click' : 'change', this.onCheckChange, this); } el.on("contextmenu", this.onContextMenu, this); var icon = Roo.fly(this.iconNode); icon.on("click", this.onClick, this); icon.on("dblclick", this.onDblClick, this); icon.on("contextmenu", this.onContextMenu, this); E.on(this.ecNode, "click", this.ecClick, this, true); if(this.node.disabled){ this.addClass("x-tree-node-disabled"); } if(this.node.hidden){ this.addClass("x-tree-node-disabled"); } var ot = this.node.getOwnerTree(); var dd = ot ? (ot.enableDD || ot.enableDrag || ot.enableDrop) : false; if(dd && (!this.node.isRoot || ot.rootVisible)){ Roo.dd.Registry.register(this.elNode, { node: this.node, handles: this.getDDHandles(), isHandle: false }); } }, getDDHandles : function(){ return [this.iconNode, this.textNode]; }, hide : function(){ if(this.rendered){ this.wrap.style.display = "none"; } }, show : function(){ if(this.rendered){ this.wrap.style.display = ""; } }, onContextMenu : function(e){ if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) { e.preventDefault(); this.focus(); this.fireEvent("contextmenu", this.node, e); } }, onClick : function(e){ if(this.dropping){ e.stopEvent(); return; } if(this.fireEvent("beforeclick", this.node, e) !== false){ if(!this.disabled && this.node.attributes.href){ this.fireEvent("click", this.node, e); return; } 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(); } }, 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); }, onCheckChange : function(){ var checked = this.checkbox.checked; this.node.attributes.checked = checked; this.fireEvent('checkchange', this.node, checked); }, ecClick : function(e){ if(!this.animating && this.node.hasChildNodes()){ this.node.toggle(); } }, 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); }, expand : function(){ this.updateExpandIcon(); this.ctNode.style.display = ""; }, focus : function(){ if(!this.node.preventHScroll){ try{this.anchor.focus(); }catch(e){} }else if(!Roo.isIE){ try{ var noscroll = this.node.getOwnerTree().getTreeEl().dom; var l = noscroll.scrollLeft; this.anchor.focus(); noscroll.scrollLeft = l; }catch(e){} } }, toggleCheck : function(value){ var cb = this.checkbox; if(cb){ cb.checked = (value === undefined ? !cb.checked : value); } }, blur : function(){ try{ this.anchor.blur(); }catch(e){} }, animExpand : function(callback){ var ct = Roo.get(this.ctNode); ct.stopFx(); if(!this.node.hasChildNodes()){ this.updateExpandIcon(); this.ctNode.style.display = ""; Roo.callback(callback); return; } this.animating = true; this.updateExpandIcon(); ct.slideIn('t', { callback : function(){ this.animating = false; Roo.callback(callback); }, scope: this, duration: this.node.ownerTree.duration || .25 }); }, highlight : function(){ var tree = this.node.getOwnerTree(); Roo.fly(this.wrap).highlight( tree.hlColor || "C3DAF9", {endColor: tree.hlBaseColor} ); }, collapse : function(){ this.updateExpandIcon(); this.ctNode.style.display = "none"; }, animCollapse : function(callback){ var ct = Roo.get(this.ctNode); ct.enableDisplayMode('block'); ct.stopFx(); this.animating = true; this.updateExpandIcon(); ct.slideOut('t', { callback : function(){ this.animating = false; Roo.callback(callback); }, scope: this, duration: this.node.ownerTree.duration || .25 }); }, getContainer : function(){ return this.ctNode; }, getEl : function(){ return this.wrap; }, appendDDGhost : function(ghostNode){ ghostNode.appendChild(this.elNode.cloneNode(true)); }, getDDRepairXY : function(){ return Roo.lib.Dom.getXY(this.iconNode); }, onRender : function(){ this.render(); }, 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 = Roo.id(this.textNode); Roo.QuickTips.register(a.qtipCfg); } this.initEvents(); if(!this.node.expanded){ this.updateExpandIcon(); } }else{ if(bulkRender === true) { targetNode.appendChild(this.wrap); } } }, 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 t = n.getOwnerTree(); var txt = t && t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text); if (typeof(n.attributes.html) != 'undefined') { txt = n.attributes.html; } var tip = t && t.rendererTip ? t.rendererTip(n.attributes) : txt; var cb = typeof a.checked == 'boolean'; var href = a.href ? a.href : Roo.isGecko ? "" : "#"; var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', a.cls,'">', '<span class="x-tree-node-indent">',this.indentMarkup,"</span>", '<img src="', this.emptyIcon, '" class="x-tree-ec-icon" />', '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />', cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : ' />')) : '', '<a hidefocus="on" href="',href,'" tabIndex="1" ', a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on" qtip="' , tip ,'">',txt,"</span></a></div>", '<ul class="x-tree-node-ct" style="display:none;"></ul>', "</li>"]; if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){ this.wrap = Roo.DomHelper.insertHtml("beforeBegin", n.nextSibling.ui.getEl(), buf.join("")); }else{ this.wrap = Roo.DomHelper.insertHtml("beforeEnd", targetNode, buf.join("")); } this.elNode = this.wrap.childNodes[0]; this.ctNode = this.wrap.childNodes[1]; var cs = this.elNode.childNodes; this.indentNode = cs[0]; this.ecNode = cs[1]; this.iconNode = cs[2]; var index = 3; if(cb){ this.checkbox = cs[3]; index++; } this.anchor = cs[index]; this.textNode = cs[index].firstChild; }, getAnchor : function(){ return this.anchor; }, getTextEl : function(){ return this.textNode; }, getIconEl : function(){ return this.iconNode; }, isChecked : function(){ return this.checkbox ? this.checkbox.checked : false; }, updateExpandIcon : function(){ if(this.rendered){ var n = this.node, c1, c2; var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow"; var hasChild = n.hasChildNodes(); if(hasChild){ if(n.expanded){ cls += "-minus"; c1 = "x-tree-node-collapsed"; c2 = "x-tree-node-expanded"; }else{ cls += "-plus"; c1 = "x-tree-node-expanded"; c2 = "x-tree-node-collapsed"; } if(this.wasLeaf){ this.removeClass("x-tree-node-leaf"); this.wasLeaf = false; } if(this.c1 != c1 || this.c2 != c2){ Roo.fly(this.elNode).replaceClass(c1, c2); this.c1 = c1; this.c2 = c2; } }else{ // this changes non-leafs into leafs if they have no children. // it's not very rational behaviour.. if(!this.wasLeaf && this.node.leaf){ Roo.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf"); delete this.c1; delete this.c2; this.wasLeaf = true; } } var ecc = "x-tree-ec-icon "+cls; if(this.ecc != ecc){ this.ecNode.className = ecc; this.ecc = ecc; } } }, getChildIndent : function(){ if(!this.childIndent){ var buf = []; var p = this.node; while(p){ if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){ if(!p.isLast()) { buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />'); } else { buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />'); } } p = p.parentNode; } this.childIndent = buf.join(""); } return this.childIndent; }, renderIndent : function(){ if(this.rendered){ var indent = ""; var p = this.node.parentNode; if(p){ indent = p.ui.getChildIndent(); } if(this.indentMarkup != indent){ // don't rerender if not required this.indentNode.innerHTML = indent; this.indentMarkup = indent; } this.updateExpandIcon(); } } }; Roo.tree.RootTreeNodeUI = function(){ Roo.tree.RootTreeNodeUI.superclass.constructor.apply(this, arguments); }; Roo.extend(Roo.tree.RootTreeNodeUI, Roo.tree.TreeNodeUI, { render : function(){ if(!this.rendered){ var targetNode = this.node.ownerTree.innerCt.dom; this.node.expanded = true; targetNode.innerHTML = '<div class="x-tree-root-node"></div>'; this.wrap = this.ctNode = targetNode.firstChild; } }, collapse : function(){ }, expand : function(){ } });