source: trunk/web/addons/job_monarch/lib/extjs/source/widgets/tree/TreeNodeUI.js @ 619

Last change on this file since 619 was 619, checked in by ramonb, 15 years ago

lib/:

  • added new AJAX dependancies: ExtJS, pChart, Lightbox2
File size: 18.4 KB
Line 
1/*
2 * Ext JS Library 2.2.1
3 * Copyright(c) 2006-2009, Ext JS, LLC.
4 * licensing@extjs.com
5 *
6 * http://extjs.com/license
7 */
8
9/**
10 * @class Ext.tree.TreeNodeUI
11 * This class provides the default UI implementation for Ext TreeNodes.
12 * The TreeNode UI implementation is separate from the
13 * tree implementation, and allows customizing of the appearance of
14 * tree nodes.<br>
15 * <p>
16 * If you are customizing the Tree's user interface, you
17 * may need to extend this class, but you should never need to instantiate this class.<br>
18 * <p>
19 * This class provides access to the user interface components of an Ext TreeNode, through
20 * {@link Ext.tree.TreeNode#getUI}
21 */
22Ext.tree.TreeNodeUI = function(node){
23    this.node = node;
24    this.rendered = false;
25    this.animating = false;
26    this.wasLeaf = true;
27    this.ecc = 'x-tree-ec-icon x-tree-elbow';
28    this.emptyIcon = Ext.BLANK_IMAGE_URL;
29};
30
31Ext.tree.TreeNodeUI.prototype = {
32    // private
33    removeChild : function(node){
34        if(this.rendered){
35            this.ctNode.removeChild(node.ui.getEl());
36        } 
37    },
38
39    // private
40    beforeLoad : function(){
41         this.addClass("x-tree-node-loading");
42    },
43
44    // private
45    afterLoad : function(){
46         this.removeClass("x-tree-node-loading");
47    },
48
49    // private
50    onTextChange : function(node, text, oldText){
51        if(this.rendered){
52            this.textNode.innerHTML = text;
53        }
54    },
55
56    // private
57    onDisableChange : function(node, state){
58        this.disabled = state;
59                if (this.checkbox) {
60                        this.checkbox.disabled = state;
61                }       
62        if(state){
63            this.addClass("x-tree-node-disabled");
64        }else{
65            this.removeClass("x-tree-node-disabled");
66        } 
67    },
68
69    // private
70    onSelectedChange : function(state){
71        if(state){
72            this.focus();
73            this.addClass("x-tree-selected");
74        }else{
75            //this.blur();
76            this.removeClass("x-tree-selected");
77        }
78    },
79
80    // private
81    onMove : function(tree, node, oldParent, newParent, index, refNode){
82        this.childIndent = null;
83        if(this.rendered){
84            var targetNode = newParent.ui.getContainer();
85            if(!targetNode){//target not rendered
86                this.holder = document.createElement("div");
87                this.holder.appendChild(this.wrap);
88                return;
89            }
90            var insertBefore = refNode ? refNode.ui.getEl() : null;
91            if(insertBefore){
92                targetNode.insertBefore(this.wrap, insertBefore);
93            }else{
94                targetNode.appendChild(this.wrap);
95            }
96            this.node.renderIndent(true);
97        }
98    },
99
100/**
101 * Adds one or more CSS classes to the node's UI element.
102 * Duplicate classes are automatically filtered out.
103 * @param {String/Array} className The CSS class to add, or an array of classes
104 */
105    addClass : function(cls){
106        if(this.elNode){
107            Ext.fly(this.elNode).addClass(cls);
108        }
109    },
110
111/**
112 * Removes one or more CSS classes from the node's UI element.
113 * @param {String/Array} className The CSS class to remove, or an array of classes
114 */
115    removeClass : function(cls){
116        if(this.elNode){
117            Ext.fly(this.elNode).removeClass(cls); 
118        }
119    },
120
121    // private
122    remove : function(){
123        if(this.rendered){
124            this.holder = document.createElement("div");
125            this.holder.appendChild(this.wrap);
126        } 
127    },
128
129    // private
130    fireEvent : function(){
131        return this.node.fireEvent.apply(this.node, arguments); 
132    },
133
134    // private
135    initEvents : function(){
136        this.node.on("move", this.onMove, this);
137
138        if(this.node.disabled){
139            this.addClass("x-tree-node-disabled");
140                        if (this.checkbox) {
141                                this.checkbox.disabled = true;
142                        }           
143        }
144        if(this.node.hidden){
145            this.hide();
146        }
147        var ot = this.node.getOwnerTree();
148        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
149        if(dd && (!this.node.isRoot || ot.rootVisible)){
150            Ext.dd.Registry.register(this.elNode, {
151                node: this.node,
152                handles: this.getDDHandles(),
153                isHandle: false
154            });
155        }
156    },
157
158    // private
159    getDDHandles : function(){
160        return [this.iconNode, this.textNode, this.elNode];
161    },
162
163/**
164 * Hides this node.
165 */
166    hide : function(){
167        this.node.hidden = true;
168        if(this.wrap){
169            this.wrap.style.display = "none";
170        }
171    },
172
173/**
174 * Shows this node.
175 */
176    show : function(){
177        this.node.hidden = false;
178        if(this.wrap){
179            this.wrap.style.display = "";
180        } 
181    },
182
183    // private
184    onContextMenu : function(e){
185        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
186            e.preventDefault();
187            this.focus();
188            this.fireEvent("contextmenu", this.node, e);
189        }
190    },
191
192    // private
193    onClick : function(e){
194        if(this.dropping){
195            e.stopEvent();
196            return;
197        }
198        if(this.fireEvent("beforeclick", this.node, e) !== false){
199            var a = e.getTarget('a');
200            if(!this.disabled && this.node.attributes.href && a){
201                this.fireEvent("click", this.node, e);
202                return;
203            }else if(a && e.ctrlKey){
204                e.stopEvent();
205            }
206            e.preventDefault();
207            if(this.disabled){
208                return;
209            }
210
211            if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
212                this.node.toggle();
213            }
214
215            this.fireEvent("click", this.node, e);
216        }else{
217            e.stopEvent();
218        }
219    },
220
221    // private
222    onDblClick : function(e){
223        e.preventDefault();
224        if(this.disabled){
225            return;
226        }
227        if(this.checkbox){
228            this.toggleCheck();
229        }
230        if(!this.animating && this.node.isExpandable()){
231            this.node.toggle();
232        }
233        this.fireEvent("dblclick", this.node, e);
234    },
235
236    onOver : function(e){
237        this.addClass('x-tree-node-over');
238    },
239
240    onOut : function(e){
241        this.removeClass('x-tree-node-over');
242    },
243
244    // private
245    onCheckChange : function(){
246        var checked = this.checkbox.checked;
247                // fix for IE6
248                this.checkbox.defaultChecked = checked;
249        this.node.attributes.checked = checked;
250        this.fireEvent('checkchange', this.node, checked);
251    },
252
253    // private
254    ecClick : function(e){
255        if(!this.animating && this.node.isExpandable()){
256            this.node.toggle();
257        }
258    },
259
260    // private
261    startDrop : function(){
262        this.dropping = true;
263    },
264   
265    // delayed drop so the click event doesn't get fired on a drop
266    endDrop : function(){ 
267       setTimeout(function(){
268           this.dropping = false;
269       }.createDelegate(this), 50); 
270    },
271
272    // private
273    expand : function(){
274        this.updateExpandIcon();
275        this.ctNode.style.display = "";
276    },
277
278    // private
279    focus : function(){
280        if(!this.node.preventHScroll){
281            try{this.anchor.focus();
282            }catch(e){}
283        }else{
284            try{
285                var noscroll = this.node.getOwnerTree().getTreeEl().dom;
286                var l = noscroll.scrollLeft;
287                this.anchor.focus();
288                noscroll.scrollLeft = l;
289            }catch(e){}
290        }
291    },
292
293/**
294 * Sets the checked status of the tree node to the passed value, or, if no value was passed,
295 * toggles the checked status. If the node was rendered with no checkbox, this has no effect.
296 * @param {Boolean} (optional) The new checked status.
297 */
298    toggleCheck : function(value){
299        var cb = this.checkbox;
300        if(cb){
301            cb.checked = (value === undefined ? !cb.checked : value);
302            this.onCheckChange();
303        }
304    },
305
306    // private
307    blur : function(){
308        try{
309            this.anchor.blur();
310        }catch(e){} 
311    },
312
313    // private
314    animExpand : function(callback){
315        var ct = Ext.get(this.ctNode);
316        ct.stopFx();
317        if(!this.node.isExpandable()){
318            this.updateExpandIcon();
319            this.ctNode.style.display = "";
320            Ext.callback(callback);
321            return;
322        }
323        this.animating = true;
324        this.updateExpandIcon();
325       
326        ct.slideIn('t', {
327           callback : function(){
328               this.animating = false;
329               Ext.callback(callback);
330            },
331            scope: this,
332            duration: this.node.ownerTree.duration || .25
333        });
334    },
335
336    // private
337    highlight : function(){
338        var tree = this.node.getOwnerTree();
339        Ext.fly(this.wrap).highlight(
340            tree.hlColor || "C3DAF9",
341            {endColor: tree.hlBaseColor}
342        );
343    },
344
345    // private
346    collapse : function(){
347        this.updateExpandIcon();
348        this.ctNode.style.display = "none";
349    },
350
351    // private
352    animCollapse : function(callback){
353        var ct = Ext.get(this.ctNode);
354        ct.enableDisplayMode('block');
355        ct.stopFx();
356
357        this.animating = true;
358        this.updateExpandIcon();
359
360        ct.slideOut('t', {
361            callback : function(){
362               this.animating = false;
363               Ext.callback(callback);
364            },
365            scope: this,
366            duration: this.node.ownerTree.duration || .25
367        });
368    },
369
370    // private
371    getContainer : function(){
372        return this.ctNode; 
373    },
374
375    // private
376    getEl : function(){
377        return this.wrap; 
378    },
379
380    // private
381    appendDDGhost : function(ghostNode){
382        ghostNode.appendChild(this.elNode.cloneNode(true));
383    },
384
385    // private
386    getDDRepairXY : function(){
387        return Ext.lib.Dom.getXY(this.iconNode);
388    },
389
390    // private
391    onRender : function(){
392        this.render();   
393    },
394
395    // private
396    render : function(bulkRender){
397        var n = this.node, a = n.attributes;
398        var targetNode = n.parentNode ? 
399              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
400       
401        if(!this.rendered){
402            this.rendered = true;
403
404            this.renderElements(n, a, targetNode, bulkRender);
405
406            if(a.qtip){
407               if(this.textNode.setAttributeNS){
408                   this.textNode.setAttributeNS("ext", "qtip", a.qtip);
409                   if(a.qtipTitle){
410                       this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
411                   }
412               }else{
413                   this.textNode.setAttribute("ext:qtip", a.qtip);
414                   if(a.qtipTitle){
415                       this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
416                   }
417               } 
418            }else if(a.qtipCfg){
419                a.qtipCfg.target = Ext.id(this.textNode);
420                Ext.QuickTips.register(a.qtipCfg);
421            }
422            this.initEvents();
423            if(!this.node.expanded){
424                this.updateExpandIcon(true);
425            }
426        }else{
427            if(bulkRender === true) {
428                targetNode.appendChild(this.wrap);
429            }
430        }
431    },
432
433    // private
434    renderElements : function(n, a, targetNode, bulkRender){
435        // add some indent caching, this helps performance when rendering a large tree
436        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
437
438        var cb = typeof a.checked == 'boolean';
439
440        var href = a.href ? a.href : Ext.isGecko ? "" : "#";
441        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">',
442            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
443            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
444            '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
445            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
446            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
447             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
448            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
449            "</li>"].join('');
450
451        var nel;
452        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
453            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
454        }else{
455            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
456        }
457       
458        this.elNode = this.wrap.childNodes[0];
459        this.ctNode = this.wrap.childNodes[1];
460        var cs = this.elNode.childNodes;
461        this.indentNode = cs[0];
462        this.ecNode = cs[1];
463        this.iconNode = cs[2];
464        var index = 3;
465        if(cb){
466            this.checkbox = cs[3];
467                        // fix for IE6
468                        this.checkbox.defaultChecked = this.checkbox.checked;                   
469            index++;
470        }
471        this.anchor = cs[index];
472        this.textNode = cs[index].firstChild;
473    },
474
475/**
476 * Returns the &lt;a> element that provides focus for the node's UI.
477 * @return {HtmlElement} The DOM anchor element.
478 */
479    getAnchor : function(){
480        return this.anchor;
481    },
482   
483/**
484 * Returns the text node.
485 * @return {HtmlNode} The DOM text node.
486 */
487    getTextEl : function(){
488        return this.textNode;
489    },
490   
491/**
492 * Returns the icon &lt;img> element.
493 * @return {HtmlElement} The DOM image element.
494 */
495    getIconEl : function(){
496        return this.iconNode;
497    },
498
499/**
500 * Returns the checked status of the node. If the node was rendered with no
501 * checkbox, it returns false.
502 * @return {Boolean} The checked flag.
503 */
504    isChecked : function(){
505        return this.checkbox ? this.checkbox.checked : false; 
506    },
507
508    // private
509    updateExpandIcon : function(){
510        if(this.rendered){
511            var n = this.node, c1, c2;
512            var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
513            if(n.isExpandable()){
514                if(n.expanded){
515                    cls += "-minus";
516                    c1 = "x-tree-node-collapsed";
517                    c2 = "x-tree-node-expanded";
518                }else{
519                    cls += "-plus";
520                    c1 = "x-tree-node-expanded";
521                    c2 = "x-tree-node-collapsed";
522                }
523                if(this.wasLeaf){
524                    this.removeClass("x-tree-node-leaf");
525                    this.wasLeaf = false;
526                }
527                if(this.c1 != c1 || this.c2 != c2){
528                    Ext.fly(this.elNode).replaceClass(c1, c2);
529                    this.c1 = c1; this.c2 = c2;
530                }
531            }else{
532                if(!this.wasLeaf){
533                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
534                    delete this.c1;
535                    delete this.c2;
536                    this.wasLeaf = true;
537                }
538            }
539            var ecc = "x-tree-ec-icon "+cls;
540            if(this.ecc != ecc){
541                this.ecNode.className = ecc;
542                this.ecc = ecc;
543            }
544        }
545    },
546
547    // private
548    getChildIndent : function(){
549        if(!this.childIndent){
550            var buf = [];
551            var p = this.node;
552            while(p){
553                if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
554                    if(!p.isLast()) {
555                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
556                    } else {
557                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
558                    }
559                }
560                p = p.parentNode;
561            }
562            this.childIndent = buf.join("");
563        }
564        return this.childIndent;
565    },
566
567    // private
568    renderIndent : function(){
569        if(this.rendered){
570            var indent = "";
571            var p = this.node.parentNode;
572            if(p){
573                indent = p.ui.getChildIndent();
574            }
575            if(this.indentMarkup != indent){ // don't rerender if not required
576                this.indentNode.innerHTML = indent;
577                this.indentMarkup = indent;
578            }
579            this.updateExpandIcon();
580        }
581    },
582
583    destroy : function(){
584        if(this.elNode){
585            Ext.dd.Registry.unregister(this.elNode.id);
586        }
587        delete this.elNode;
588        delete this.ctNode;
589        delete this.indentNode;
590        delete this.ecNode;
591        delete this.iconNode;
592        delete this.checkbox;
593        delete this.anchor;
594        delete this.textNode;
595       
596        if (this.holder){
597             delete this.wrap;
598             Ext.removeNode(this.holder);
599             delete this.holder;
600        }else{
601            Ext.removeNode(this.wrap);
602            delete this.wrap;
603        }
604    }
605};
606
607/**
608 * @class Ext.tree.RootTreeNodeUI
609 * This class provides the default UI implementation for <b>root</b> Ext TreeNodes.
610 * The RootTreeNode UI implementation allows customizing the appearance of the root tree node.<br>
611 * <p>
612 * If you are customizing the Tree's user interface, you
613 * may need to extend this class, but you should never need to instantiate this class.<br>
614 */
615Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
616    // private
617    render : function(){
618        if(!this.rendered){
619            var targetNode = this.node.ownerTree.innerCt.dom;
620            this.node.expanded = true;
621            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
622            this.wrap = this.ctNode = targetNode.firstChild;
623        }
624    },
625    collapse : Ext.emptyFn,
626    expand : Ext.emptyFn
627});
Note: See TracBrowser for help on using the repository browser.