3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.2.0
11 * Copyright(c) 2006-2010 Ext JS, Inc.
13 * http://www.extjs.com/license
15 <div id="cls-Ext.tree.TreeNodeUI"></div>/**
16 * @class Ext.tree.TreeNodeUI
17 * This class provides the default UI implementation for Ext TreeNodes.
18 * The TreeNode UI implementation is separate from the
19 * tree implementation, and allows customizing of the appearance of
22 * If you are customizing the Tree's user interface, you
23 * may need to extend this class, but you should never need to instantiate this class.<br>
25 * This class provides access to the user interface components of an Ext TreeNode, through
26 * {@link Ext.tree.TreeNode#getUI}
28 Ext.tree.TreeNodeUI = function(node){
30 this.rendered = false;
31 this.animating = false;
33 this.ecc = 'x-tree-ec-icon x-tree-elbow';
34 this.emptyIcon = Ext.BLANK_IMAGE_URL;
37 Ext.tree.TreeNodeUI.prototype = {
39 removeChild : function(node){
41 this.ctNode.removeChild(node.ui.getEl());
46 beforeLoad : function(){
47 this.addClass("x-tree-node-loading");
51 afterLoad : function(){
52 this.removeClass("x-tree-node-loading");
56 onTextChange : function(node, text, oldText){
58 this.textNode.innerHTML = text;
63 onDisableChange : function(node, state){
64 this.disabled = state;
66 this.checkbox.disabled = state;
69 this.addClass("x-tree-node-disabled");
71 this.removeClass("x-tree-node-disabled");
76 onSelectedChange : function(state){
79 this.addClass("x-tree-selected");
82 this.removeClass("x-tree-selected");
87 onMove : function(tree, node, oldParent, newParent, index, refNode){
88 this.childIndent = null;
90 var targetNode = newParent.ui.getContainer();
91 if(!targetNode){//target not rendered
92 this.holder = document.createElement("div");
93 this.holder.appendChild(this.wrap);
96 var insertBefore = refNode ? refNode.ui.getEl() : null;
98 targetNode.insertBefore(this.wrap, insertBefore);
100 targetNode.appendChild(this.wrap);
102 this.node.renderIndent(true, oldParent != newParent);
106 <div id="method-Ext.tree.TreeNodeUI-addClass"></div>/**
107 * Adds one or more CSS classes to the node's UI element.
108 * Duplicate classes are automatically filtered out.
109 * @param {String/Array} className The CSS class to add, or an array of classes
111 addClass : function(cls){
113 Ext.fly(this.elNode).addClass(cls);
117 <div id="method-Ext.tree.TreeNodeUI-removeClass"></div>/**
118 * Removes one or more CSS classes from the node's UI element.
119 * @param {String/Array} className The CSS class to remove, or an array of classes
121 removeClass : function(cls){
123 Ext.fly(this.elNode).removeClass(cls);
130 this.holder = document.createElement("div");
131 this.holder.appendChild(this.wrap);
136 fireEvent : function(){
137 return this.node.fireEvent.apply(this.node, arguments);
141 initEvents : function(){
142 this.node.on("move", this.onMove, this);
144 if(this.node.disabled){
145 this.onDisableChange(this.node, true);
147 if(this.node.hidden){
150 var ot = this.node.getOwnerTree();
151 var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
152 if(dd && (!this.node.isRoot || ot.rootVisible)){
153 Ext.dd.Registry.register(this.elNode, {
155 handles: this.getDDHandles(),
162 getDDHandles : function(){
163 return [this.iconNode, this.textNode, this.elNode];
166 <div id="method-Ext.tree.TreeNodeUI-hide"></div>/**
170 this.node.hidden = true;
172 this.wrap.style.display = "none";
176 <div id="method-Ext.tree.TreeNodeUI-show"></div>/**
180 this.node.hidden = false;
182 this.wrap.style.display = "";
187 onContextMenu : function(e){
188 if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
191 this.fireEvent("contextmenu", this.node, e);
196 onClick : function(e){
201 if(this.fireEvent("beforeclick", this.node, e) !== false){
202 var a = e.getTarget('a');
203 if(!this.disabled && this.node.attributes.href && a){
204 this.fireEvent("click", this.node, e);
206 }else if(a && e.ctrlKey){
214 if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
218 this.fireEvent("click", this.node, e);
225 onDblClick : function(e){
230 if(this.fireEvent("beforedblclick", this.node, e) !== false){
234 if(!this.animating && this.node.isExpandable()){
237 this.fireEvent("dblclick", this.node, e);
241 onOver : function(e){
242 this.addClass('x-tree-node-over');
246 this.removeClass('x-tree-node-over');
250 onCheckChange : function(){
251 var checked = this.checkbox.checked;
253 this.checkbox.defaultChecked = checked;
254 this.node.attributes.checked = checked;
255 this.fireEvent('checkchange', this.node, checked);
259 ecClick : function(e){
260 if(!this.animating && this.node.isExpandable()){
266 startDrop : function(){
267 this.dropping = true;
270 // delayed drop so the click event doesn't get fired on a drop
271 endDrop : function(){
272 setTimeout(function(){
273 this.dropping = false;
274 }.createDelegate(this), 50);
279 this.updateExpandIcon();
280 this.ctNode.style.display = "";
285 if(!this.node.preventHScroll){
286 try{this.anchor.focus();
290 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
291 var l = noscroll.scrollLeft;
293 noscroll.scrollLeft = l;
298 <div id="method-Ext.tree.TreeNodeUI-toggleCheck"></div>/**
299 * Sets the checked status of the tree node to the passed value, or, if no value was passed,
300 * toggles the checked status. If the node was rendered with no checkbox, this has no effect.
301 * @param {Boolean} value (optional) The new checked status.
303 toggleCheck : function(value){
304 var cb = this.checkbox;
306 cb.checked = (value === undefined ? !cb.checked : value);
307 this.onCheckChange();
319 animExpand : function(callback){
320 var ct = Ext.get(this.ctNode);
322 if(!this.node.isExpandable()){
323 this.updateExpandIcon();
324 this.ctNode.style.display = "";
325 Ext.callback(callback);
328 this.animating = true;
329 this.updateExpandIcon();
332 callback : function(){
333 this.animating = false;
334 Ext.callback(callback);
337 duration: this.node.ownerTree.duration || .25
342 highlight : function(){
343 var tree = this.node.getOwnerTree();
344 Ext.fly(this.wrap).highlight(
345 tree.hlColor || "C3DAF9",
346 {endColor: tree.hlBaseColor}
351 collapse : function(){
352 this.updateExpandIcon();
353 this.ctNode.style.display = "none";
357 animCollapse : function(callback){
358 var ct = Ext.get(this.ctNode);
359 ct.enableDisplayMode('block');
362 this.animating = true;
363 this.updateExpandIcon();
366 callback : function(){
367 this.animating = false;
368 Ext.callback(callback);
371 duration: this.node.ownerTree.duration || .25
376 getContainer : function(){
380 <div id="method-Ext.tree.TreeNodeUI-getEl"></div>/**
381 * Returns the element which encapsulates this node.
382 * @return {HtmlElement} The DOM element. The default implementation uses a <code><li></code>.
389 appendDDGhost : function(ghostNode){
390 ghostNode.appendChild(this.elNode.cloneNode(true));
394 getDDRepairXY : function(){
395 return Ext.lib.Dom.getXY(this.iconNode);
399 onRender : function(){
404 render : function(bulkRender){
405 var n = this.node, a = n.attributes;
406 var targetNode = n.parentNode ?
407 n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
410 this.rendered = true;
412 this.renderElements(n, a, targetNode, bulkRender);
415 if(this.textNode.setAttributeNS){
416 this.textNode.setAttributeNS("ext", "qtip", a.qtip);
418 this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
421 this.textNode.setAttribute("ext:qtip", a.qtip);
423 this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
427 a.qtipCfg.target = Ext.id(this.textNode);
428 Ext.QuickTips.register(a.qtipCfg);
431 if(!this.node.expanded){
432 this.updateExpandIcon(true);
435 if(bulkRender === true) {
436 targetNode.appendChild(this.wrap);
442 renderElements : function(n, a, targetNode, bulkRender){
443 // add some indent caching, this helps performance when rendering a large tree
444 this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
446 var cb = Ext.isBoolean(a.checked),
448 href = a.href ? a.href : Ext.isGecko ? "" : "#",
449 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">',
450 '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
451 '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
452 '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
453 cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
454 '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
455 a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
456 '<ul class="x-tree-node-ct" style="display:none;"></ul>',
459 if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
460 this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
462 this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
465 this.elNode = this.wrap.childNodes[0];
466 this.ctNode = this.wrap.childNodes[1];
467 var cs = this.elNode.childNodes;
468 this.indentNode = cs[0];
470 this.iconNode = cs[2];
473 this.checkbox = cs[3];
475 this.checkbox.defaultChecked = this.checkbox.checked;
478 this.anchor = cs[index];
479 this.textNode = cs[index].firstChild;
482 <div id="method-Ext.tree.TreeNodeUI-getAnchor"></div>/**
483 * Returns the <a> element that provides focus for the node's UI.
484 * @return {HtmlElement} The DOM anchor element.
486 getAnchor : function(){
490 <div id="method-Ext.tree.TreeNodeUI-getTextEl"></div>/**
491 * Returns the text node.
492 * @return {HtmlNode} The DOM text node.
494 getTextEl : function(){
495 return this.textNode;
498 <div id="method-Ext.tree.TreeNodeUI-getIconEl"></div>/**
499 * Returns the icon <img> element.
500 * @return {HtmlElement} The DOM image element.
502 getIconEl : function(){
503 return this.iconNode;
506 <div id="method-Ext.tree.TreeNodeUI-isChecked"></div>/**
507 * Returns the checked status of the node. If the node was rendered with no
508 * checkbox, it returns false.
509 * @return {Boolean} The checked flag.
511 isChecked : function(){
512 return this.checkbox ? this.checkbox.checked : false;
516 updateExpandIcon : function(){
521 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
522 hasChild = n.hasChildNodes();
523 if(hasChild || n.attributes.expandable){
526 c1 = "x-tree-node-collapsed";
527 c2 = "x-tree-node-expanded";
530 c1 = "x-tree-node-expanded";
531 c2 = "x-tree-node-collapsed";
534 this.removeClass("x-tree-node-leaf");
535 this.wasLeaf = false;
537 if(this.c1 != c1 || this.c2 != c2){
538 Ext.fly(this.elNode).replaceClass(c1, c2);
539 this.c1 = c1; this.c2 = c2;
543 Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
549 var ecc = "x-tree-ec-icon "+cls;
551 this.ecNode.className = ecc;
558 onIdChange: function(id){
560 this.elNode.setAttribute('ext:tree-node-id', id);
565 getChildIndent : function(){
566 if(!this.childIndent){
570 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
572 buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
574 buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
579 this.childIndent = buf.join("");
581 return this.childIndent;
585 renderIndent : function(){
588 p = this.node.parentNode;
590 indent = p.ui.getChildIndent();
592 if(this.indentMarkup != indent){ // don't rerender if not required
593 this.indentNode.innerHTML = indent;
594 this.indentMarkup = indent;
596 this.updateExpandIcon();
600 destroy : function(){
602 Ext.dd.Registry.unregister(this.elNode.id);
605 Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
607 Ext.fly(this[el]).remove();
615 <div id="cls-Ext.tree.RootTreeNodeUI"></div>/**
616 * @class Ext.tree.RootTreeNodeUI
617 * This class provides the default UI implementation for <b>root</b> Ext TreeNodes.
618 * The RootTreeNode UI implementation allows customizing the appearance of the root tree node.<br>
620 * If you are customizing the Tree's user interface, you
621 * may need to extend this class, but you should never need to instantiate this class.<br>
623 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
627 var targetNode = this.node.ownerTree.innerCt.dom;
628 this.node.expanded = true;
629 targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
630 this.wrap = this.ctNode = targetNode.firstChild;
633 collapse : Ext.emptyFn,