PageRenderTime 63ms CodeModel.GetById 13ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/ext/pkgs/pkg-tips-debug.js

http://hdbc.googlecode.com/
JavaScript | 994 lines | 612 code | 65 blank | 317 comment | 124 complexity | 9f7536015e0b7e1b0df51ac1131e53c0 MD5 | raw file
  1/*!
  2 * Ext JS Library 3.0.0
  3 * Copyright(c) 2006-2009 Ext JS, LLC
  4 * licensing@extjs.com
  5 * http://www.extjs.com/license
  6 */
  7/**
  8 * @class Ext.Tip
  9 * @extends Ext.Panel
 10 * This is the base class for {@link Ext.QuickTip} and {@link Ext.Tooltip} that provides the basic layout and
 11 * positioning that all tip-based classes require. This class can be used directly for simple, statically-positioned
 12 * tips that are displayed programmatically, or it can be extended to provide custom tip implementations.
 13 * @constructor
 14 * Create a new Tip
 15 * @param {Object} config The configuration options
 16 */
 17Ext.Tip = Ext.extend(Ext.Panel, {
 18    /**
 19     * @cfg {Boolean} closable True to render a close tool button into the tooltip header (defaults to false).
 20     */
 21    /**
 22     * @cfg {Number} width
 23     * Width in pixels of the tip (defaults to auto).  Width will be ignored if it exceeds the bounds of
 24     * {@link #minWidth} or {@link #maxWidth}.  The maximum supported value is 500.
 25     */
 26    /**
 27     * @cfg {Number} minWidth The minimum width of the tip in pixels (defaults to 40).
 28     */
 29    minWidth : 40,
 30    /**
 31     * @cfg {Number} maxWidth The maximum width of the tip in pixels (defaults to 300).  The maximum supported value is 500.
 32     */
 33    maxWidth : 300,
 34    /**
 35     * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop"
 36     * for bottom-right shadow (defaults to "sides").
 37     */
 38    shadow : "sides",
 39    /**
 40     * @cfg {String} defaultAlign <b>Experimental</b>. The default {@link Ext.Element#alignTo} anchor position value
 41     * for this tip relative to its element of origin (defaults to "tl-bl?").
 42     */
 43    defaultAlign : "tl-bl?",
 44    autoRender: true,
 45    quickShowInterval : 250,
 46
 47    // private panel overrides
 48    frame:true,
 49    hidden:true,
 50    baseCls: 'x-tip',
 51    floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
 52    autoHeight:true,
 53
 54    closeAction: 'hide',
 55
 56    // private
 57    initComponent : function(){
 58        Ext.Tip.superclass.initComponent.call(this);
 59        if(this.closable && !this.title){
 60            this.elements += ',header';
 61        }
 62    },
 63
 64    // private
 65    afterRender : function(){
 66        Ext.Tip.superclass.afterRender.call(this);
 67        if(this.closable){
 68            this.addTool({
 69                id: 'close',
 70                handler: this[this.closeAction],
 71                scope: this
 72            });
 73        }
 74    },
 75
 76    /**
 77     * Shows this tip at the specified XY position.  Example usage:
 78     * <pre><code>
 79// Show the tip at x:50 and y:100
 80tip.showAt([50,100]);
 81</code></pre>
 82     * @param {Array} xy An array containing the x and y coordinates
 83     */
 84    showAt : function(xy){
 85        Ext.Tip.superclass.show.call(this);
 86        if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
 87            this.doAutoWidth();
 88        }
 89        if(this.constrainPosition){
 90            xy = this.el.adjustForConstraints(xy);
 91        }
 92        this.setPagePosition(xy[0], xy[1]);
 93    },
 94
 95    // protected
 96    doAutoWidth : function(){
 97        var bw = this.body.getTextWidth();
 98        if(this.title){
 99            bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
100        }
101        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
102        this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
103        
104        // IE7 repaint bug on initial show
105        if(Ext.isIE7 && !this.repainted){
106            this.el.repaint();
107            this.repainted = true;
108        }
109    },
110
111    /**
112     * <b>Experimental</b>. Shows this tip at a position relative to another element using a standard {@link Ext.Element#alignTo}
113     * anchor position value.  Example usage:
114     * <pre><code>
115// Show the tip at the default position ('tl-br?')
116tip.showBy('my-el');
117
118// Show the tip's top-left corner anchored to the element's top-right corner
119tip.showBy('my-el', 'tl-tr');
120</code></pre>
121     * @param {Mixed} el An HTMLElement, Ext.Element or string id of the target element to align to
122     * @param {String} position (optional) A valid {@link Ext.Element#alignTo} anchor position (defaults to 'tl-br?' or
123     * {@link #defaultAlign} if specified).
124     */
125    showBy : function(el, pos){
126        if(!this.rendered){
127            this.render(Ext.getBody());
128        }
129        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
130    },
131
132    initDraggable : function(){
133        this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
134        this.header.addClass('x-tip-draggable');
135    }
136});
137
138// private - custom Tip DD implementation
139Ext.Tip.DD = function(tip, config){
140    Ext.apply(this, config);
141    this.tip = tip;
142    Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
143    this.setHandleElId(tip.header.id);
144    this.scroll = false;
145};
146
147Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
148    moveOnly:true,
149    scroll:false,
150    headerOffsets:[100, 25],
151    startDrag : function(){
152        this.tip.el.disableShadow();
153    },
154    endDrag : function(e){
155        this.tip.el.enableShadow(true);
156    }
157});/**
158 * @class Ext.ToolTip
159 * @extends Ext.Tip
160 * A standard tooltip implementation for providing additional information when hovering over a target element.
161 * @constructor
162 * Create a new Tooltip
163 * @param {Object} config The configuration options
164 */
165Ext.ToolTip = Ext.extend(Ext.Tip, {
166    /**
167     * When a Tooltip is configured with the {@link #delegate} option to cause selected child elements of the {@link #target}
168     * Element to each trigger a seperate show event, this property is set to the DOM element which triggered the show.
169     * @type DOMElement
170     * @property triggerElement
171     */
172    /**
173     * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to monitor for mouseover events to trigger
174     * showing this ToolTip.
175     */
176    /**
177     * @cfg {Boolean} autoHide True to automatically hide the tooltip after the mouse exits the target element
178     * or after the {@link #dismissDelay} has expired if set (defaults to true).  If {@link closable} = true a close
179     * tool button will be rendered into the tooltip header.
180     */
181    /**
182     * @cfg {Number} showDelay Delay in milliseconds before the tooltip displays after the mouse enters the
183     * target element (defaults to 500)
184     */
185    showDelay: 500,
186    /**
187     * @cfg {Number} hideDelay Delay in milliseconds after the mouse exits the target element but before the
188     * tooltip actually hides (defaults to 200).  Set to 0 for the tooltip to hide immediately.
189     */
190    hideDelay: 200,
191    /**
192     * @cfg {Number} dismissDelay Delay in milliseconds before the tooltip automatically hides (defaults to 5000).
193     * To disable automatic hiding, set dismissDelay = 0.
194     */
195    dismissDelay: 5000,
196    /**
197     * @cfg {Array} mouseOffset An XY offset from the mouse position where the tooltip should be shown (defaults to [15,18]).
198     */
199    /**
200     * @cfg {Boolean} trackMouse True to have the tooltip follow the mouse as it moves over the target element (defaults to false).
201     */
202    trackMouse : false,
203    /**
204     * @cfg {Boolean} anchorToTarget True to anchor the tooltip to the target element, false to
205     * anchor it relative to the mouse coordinates (defaults to true).  When anchorToTarget is
206     * true, use {@link #defaultAlign} to control tooltip alignment to the target element.  When
207     * anchorToTarget is false, use {@link #anchorPosition} instead to control alignment.
208     */
209    anchorToTarget: true,
210    /**
211     * @cfg {Number} anchorOffset A numeric pixel value used to offset the default position of the
212     * anchor arrow (defaults to 0).  When the anchor position is on the top or bottom of the tooltip,
213     * anchorOffset will be used as a horizontal offset.  Likewise, when the anchor position is on the
214     * left or right side, anchorOffset will be used as a vertical offset.
215     */
216    anchorOffset: 0,
217    /**
218     * @cfg {String} delegate <p>Optional. A {@link Ext.DomQuery DomQuery} selector which allows selection of individual elements
219     * within the {@link #target} element to trigger showing and hiding the ToolTip as the mouse moves within the target.</p>
220     * <p>When specified, the child element of the target which caused a show event is placed into the {@link #triggerElement} property
221     * before the ToolTip is shown.</p>
222     * <p>This may be useful when a Component has regular, repeating elements in it, each of which need a Tooltip which contains
223     * information specific to that element. For example:</p><pre><code>
224var myGrid = new Ext.grid.gridPanel(gridConfig);
225myGrid.on('render', function(grid) {
226    var store = grid.getStore();  // Capture the Store.
227    var view = grid.getView();    // Capture the GridView.
228    myGrid.tip = new Ext.ToolTip({
229        target: view.mainBody,    // The overall target element.
230        delegate: '.x-grid3-row', // Each grid row causes its own seperate show and hide.
231        trackMouse: true,         // Moving within the row should not hide the tip.
232        renderTo: document.body,  // Render immediately so that tip.body can be referenced prior to the first show.
233        listeners: {              // Change content dynamically depending on which element triggered the show.
234            beforeshow: function updateTipBody(tip) {
235                var rowIndex = view.findRowIndex(tip.triggerElement);
236                tip.body.dom.innerHTML = "Over Record ID " + store.getAt(rowIndex).id;
237            }
238        }
239    });
240});</code></pre>
241     */
242
243    // private
244    targetCounter: 0,
245
246    constrainPosition: false,
247
248    // private
249    initComponent: function(){
250        Ext.ToolTip.superclass.initComponent.call(this);
251        this.lastActive = new Date();
252        this.initTarget(this.target);
253        this.origAnchor = this.anchor;
254    },
255
256    // private
257    onRender : function(ct, position){
258        Ext.ToolTip.superclass.onRender.call(this, ct, position);
259        this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
260        this.anchorEl = this.el.createChild({
261            cls: 'x-tip-anchor ' + this.anchorCls
262        });
263    },
264
265    // private
266    afterRender : function(){
267        Ext.ToolTip.superclass.afterRender.call(this);
268        this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1);
269    },
270
271    /**
272     * Binds this ToolTip to the specified element. The tooltip will be displayed when the mouse moves over the element.
273     * @param {Mixed} t The Element, HtmlElement, or ID of an element to bind to
274     */
275    initTarget : function(target){
276        var t;
277        if((t = Ext.get(target))){
278            if(this.target){
279                this.target = Ext.get(this.target);
280                this.target.un('mouseover', this.onTargetOver, this);
281                this.target.un('mouseout', this.onTargetOut, this);
282                this.target.un('mousemove', this.onMouseMove, this);
283            }
284            this.mon(t, {
285                mouseover: this.onTargetOver,
286                mouseout: this.onTargetOut,
287                mousemove: this.onMouseMove,
288                scope: this
289            });
290            this.target = t;
291        }
292        if(this.anchor){
293            this.anchorTarget = this.target;
294        }
295    },
296
297    // private
298    onMouseMove : function(e){
299        var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
300        if (t) {
301            this.targetXY = e.getXY();
302            if (t === this.triggerElement) {
303                if(!this.hidden && this.trackMouse){
304                    this.setPagePosition(this.getTargetXY());
305                }
306            } else {
307                this.hide();
308                this.lastActive = new Date(0);
309                this.onTargetOver(e);
310            }
311        } else if (!this.closable && this.isVisible()) {
312            this.hide();
313        }
314    },
315
316    // private
317    getTargetXY : function(){
318        if(this.anchor){
319            this.targetCounter++;
320            var offsets = this.getOffsets();
321            var xy = (this.anchorToTarget && !this.trackMouse) ?
322                this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) :
323                this.targetXY;
324
325            var dw = Ext.lib.Dom.getViewWidth()-5;
326            var dh = Ext.lib.Dom.getViewHeight()-5;
327            var scrollX = (document.documentElement.scrollLeft || document.body.scrollLeft || 0)+5;
328            var scrollY = (document.documentElement.scrollTop || document.body.scrollTop || 0)+5;
329
330            var axy = [xy[0] + offsets[0], xy[1] + offsets[1]];
331            var sz = this.getSize();
332            this.anchorEl.removeClass(this.anchorCls);
333
334            if(this.targetCounter < 2){
335                if(axy[0] < scrollX){
336                    if(this.anchorToTarget){
337                        this.defaultAlign = 'l-r';
338                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
339                    }
340                    this.anchor = 'left';
341                    return this.getTargetXY();
342                }
343                if(axy[0]+sz.width > dw){
344                    if(this.anchorToTarget){
345                        this.defaultAlign = 'r-l';
346                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
347                    }
348                    this.anchor = 'right';
349                    return this.getTargetXY();
350                }
351                if(axy[1] < scrollY){
352                    if(this.anchorToTarget){
353                        this.defaultAlign = 't-b';
354                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
355                    }
356                    this.anchor = 'top';
357                    return this.getTargetXY();
358                }
359                if(axy[1]+sz.height > dh){
360                    if(this.anchorToTarget){
361                        this.defaultAlign = 'b-t';
362                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
363                    }
364                    this.anchor = 'bottom';
365                    return this.getTargetXY();
366                }
367            }
368
369            this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
370            this.anchorEl.addClass(this.anchorCls);
371            this.targetCounter = 0;
372            return axy;
373        }else{
374            var mouseOffset = this.getMouseOffset();
375            return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
376        }
377    },
378
379    getMouseOffset : function(){
380        var offset = this.anchor ? [0,0] : [15,18];
381        if(this.mouseOffset){
382            offset[0] += this.mouseOffset[0];
383            offset[1] += this.mouseOffset[1];
384        }
385        return offset;
386    },
387
388    // private
389    getAnchorPosition : function(){
390        if(this.anchor){
391            this.tipAnchor = this.anchor.charAt(0);
392        }else{
393            var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
394            if(!m){
395               throw "AnchorTip.defaultAlign is invalid";
396            }
397            this.tipAnchor = m[1].charAt(0);
398        }
399
400        switch(this.tipAnchor){
401            case 't': return 'top';
402            case 'b': return 'bottom';
403            case 'r': return 'right';
404        }
405        return 'left';
406    },
407
408    // private
409    getAnchorAlign : function(){
410        switch(this.anchor){
411            case 'top'  : return 'tl-bl';
412            case 'left' : return 'tl-tr';
413            case 'right': return 'tr-tl';
414            default     : return 'bl-tl';
415        }
416    },
417
418    // private
419    getOffsets: function(){
420        var offsets, ap = this.getAnchorPosition().charAt(0);
421        if(this.anchorToTarget && !this.trackMouse){
422            switch(ap){
423                case 't':
424                    offsets = [0, 9];
425                    break;
426                case 'b':
427                    offsets = [0, -13];
428                    break;
429                case 'r':
430                    offsets = [-13, 0];
431                    break;
432                default:
433                    offsets = [9, 0];
434                    break;
435            }
436        }else{
437            switch(ap){
438                case 't':
439                    offsets = [-15-this.anchorOffset, 30];
440                    break;
441                case 'b':
442                    offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
443                    break;
444                case 'r':
445                    offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
446                    break;
447                default:
448                    offsets = [25, -13-this.anchorOffset];
449                    break;
450            }
451        }
452        var mouseOffset = this.getMouseOffset();
453        offsets[0] += mouseOffset[0];
454        offsets[1] += mouseOffset[1];
455
456        return offsets;
457    },
458
459    // private
460    onTargetOver : function(e){
461        if(this.disabled || e.within(this.target.dom, true)){
462            return;
463        }
464        var t = e.getTarget(this.delegate);
465        if (t) {
466            this.triggerElement = t;
467            this.clearTimer('hide');
468            this.targetXY = e.getXY();
469            this.delayShow();
470        }
471    },
472
473    // private
474    delayShow : function(){
475        if(this.hidden && !this.showTimer){
476            if(this.lastActive.getElapsed() < this.quickShowInterval){
477                this.show();
478            }else{
479                this.showTimer = this.show.defer(this.showDelay, this);
480            }
481        }else if(!this.hidden && this.autoHide !== false){
482            this.show();
483        }
484    },
485
486    // private
487    onTargetOut : function(e){
488        if(this.disabled || e.within(this.target.dom, true)){
489            return;
490        }
491        this.clearTimer('show');
492        if(this.autoHide !== false){
493            this.delayHide();
494        }
495    },
496
497    // private
498    delayHide : function(){
499        if(!this.hidden && !this.hideTimer){
500            this.hideTimer = this.hide.defer(this.hideDelay, this);
501        }
502    },
503
504    /**
505     * Hides this tooltip if visible.
506     */
507    hide: function(){
508        this.clearTimer('dismiss');
509        this.lastActive = new Date();
510        if(this.anchorEl){
511            this.anchorEl.hide();
512        }
513        Ext.ToolTip.superclass.hide.call(this);
514        delete this.triggerElement;
515    },
516
517    /**
518     * Shows this tooltip at the current event target XY position.
519     */
520    show : function(){
521        if(this.anchor){
522            // pre-show it off screen so that the el will have dimensions
523            // for positioning calcs when getting xy next
524            this.showAt([-1000,-1000]);
525            this.origConstrainPosition = this.constrainPosition;
526            this.constrainPosition = false;
527            this.anchor = this.origAnchor;
528        }
529        this.showAt(this.getTargetXY());
530
531        if(this.anchor){
532            this.syncAnchor();
533            this.anchorEl.show();
534            this.constrainPosition = this.origConstrainPosition;
535        }else{
536            this.anchorEl.hide();
537        }
538    },
539
540    // inherit docs
541    showAt : function(xy){
542        this.lastActive = new Date();
543        this.clearTimers();
544        Ext.ToolTip.superclass.showAt.call(this, xy);
545        if(this.dismissDelay && this.autoHide !== false){
546            this.dismissTimer = this.hide.defer(this.dismissDelay, this);
547        }
548    },
549
550    // private
551    syncAnchor : function(){
552        var anchorPos, targetPos, offset;
553        switch(this.tipAnchor.charAt(0)){
554            case 't':
555                anchorPos = 'b';
556                targetPos = 'tl';
557                offset = [20+this.anchorOffset, 2];
558                break;
559            case 'r':
560                anchorPos = 'l';
561                targetPos = 'tr';
562                offset = [-2, 11+this.anchorOffset];
563                break;
564            case 'b':
565                anchorPos = 't';
566                targetPos = 'bl';
567                offset = [20+this.anchorOffset, -2];
568                break;
569            default:
570                anchorPos = 'r';
571                targetPos = 'tl';
572                offset = [2, 11+this.anchorOffset];
573                break;
574        }
575        this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
576    },
577
578    // private
579    setPagePosition : function(x, y){
580        Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
581        if(this.anchor){
582            this.syncAnchor();
583        }
584    },
585
586    // private
587    clearTimer : function(name){
588        name = name + 'Timer';
589        clearTimeout(this[name]);
590        delete this[name];
591    },
592
593    // private
594    clearTimers : function(){
595        this.clearTimer('show');
596        this.clearTimer('dismiss');
597        this.clearTimer('hide');
598    },
599
600    // private
601    onShow : function(){
602        Ext.ToolTip.superclass.onShow.call(this);
603        Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
604    },
605
606    // private
607    onHide : function(){
608        Ext.ToolTip.superclass.onHide.call(this);
609        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
610    },
611
612    // private
613    onDocMouseDown : function(e){
614        if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
615            this.disable();
616            this.enable.defer(100, this);
617        }
618    },
619
620    // private
621    onDisable : function(){
622        this.clearTimers();
623        this.hide();
624    },
625
626    // private
627    adjustPosition : function(x, y){
628        if(this.contstrainPosition){
629            var ay = this.targetXY[1], h = this.getSize().height;
630            if(y <= ay && (y+h) >= ay){
631                y = ay-h-5;
632            }
633        }
634        return {x : x, y: y};
635    },
636
637    // private
638    onDestroy : function(){
639        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
640        Ext.ToolTip.superclass.onDestroy.call(this);
641    }
642});/**
643 * @class Ext.QuickTip
644 * @extends Ext.ToolTip
645 * A specialized tooltip class for tooltips that can be specified in markup and automatically managed by the global
646 * {@link Ext.QuickTips} instance.  See the QuickTips class header for additional usage details and examples.
647 * @constructor
648 * Create a new Tip
649 * @param {Object} config The configuration options
650 */
651Ext.QuickTip = Ext.extend(Ext.ToolTip, {
652    /**
653     * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to associate with this quicktip (defaults to the document).
654     */
655    /**
656     * @cfg {Boolean} interceptTitles True to automatically use the element's DOM title value if available (defaults to false).
657     */
658    interceptTitles : false,
659
660    // private
661    tagConfig : {
662        namespace : "ext",
663        attribute : "qtip",
664        width : "qwidth",
665        target : "target",
666        title : "qtitle",
667        hide : "hide",
668        cls : "qclass",
669        align : "qalign",
670        anchor : "anchor"
671    },
672
673    // private
674    initComponent : function(){
675        this.target = this.target || Ext.getDoc();
676        this.targets = this.targets || {};
677        Ext.QuickTip.superclass.initComponent.call(this);
678    },
679
680    /**
681     * Configures a new quick tip instance and assigns it to a target element.  The following config values are
682     * supported (for example usage, see the {@link Ext.QuickTips} class header):
683     * <div class="mdetail-params"><ul>
684     * <li>autoHide</li>
685     * <li>cls</li>
686     * <li>dismissDelay (overrides the singleton value)</li>
687     * <li>target (required)</li>
688     * <li>text (required)</li>
689     * <li>title</li>
690     * <li>width</li></ul></div>
691     * @param {Object} config The config object
692     */
693    register : function(config){
694        var cs = Ext.isArray(config) ? config : arguments;
695        for(var i = 0, len = cs.length; i < len; i++){
696            var c = cs[i];
697            var target = c.target;
698            if(target){
699                if(Ext.isArray(target)){
700                    for(var j = 0, jlen = target.length; j < jlen; j++){
701                        this.targets[Ext.id(target[j])] = c;
702                    }
703                } else{
704                    this.targets[Ext.id(target)] = c;
705                }
706            }
707        }
708    },
709
710    /**
711     * Removes this quick tip from its element and destroys it.
712     * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
713     */
714    unregister : function(el){
715        delete this.targets[Ext.id(el)];
716    },
717    
718    /**
719     * Hides a visible tip or cancels an impending show for a particular element.
720     * @param {String/HTMLElement/Element} el The element that is the target of the tip.
721     */
722    cancelShow: function(el){
723        var at = this.activeTarget;
724        el = Ext.get(el).dom;
725        if(this.isVisible()){
726            if(at && at.el == el){
727                this.hide();
728            }
729        }else if(at && at.el == el){
730            this.clearTimer('show');
731        }
732    },
733
734    // private
735    onTargetOver : function(e){
736        if(this.disabled){
737            return;
738        }
739        this.targetXY = e.getXY();
740        var t = e.getTarget();
741        if(!t || t.nodeType !== 1 || t == document || t == document.body){
742            return;
743        }
744        if(this.activeTarget && t == this.activeTarget.el){
745            this.clearTimer('hide');
746            this.show();
747            return;
748        }
749        if(t && this.targets[t.id]){
750            this.activeTarget = this.targets[t.id];
751            this.activeTarget.el = t;
752            this.anchor = this.activeTarget.anchor;
753            if(this.anchor){
754                this.anchorTarget = t;
755            }
756            this.delayShow();
757            return;
758        }
759        
760        var ttp, et = Ext.fly(t), cfg = this.tagConfig;
761        var ns = cfg.namespace;
762        if(this.interceptTitles && t.title){
763            ttp = t.title;
764            t.qtip = ttp;
765            t.removeAttribute("title");
766            e.preventDefault();
767        } else{
768            ttp = t.qtip || et.getAttribute(cfg.attribute, ns);
769        }
770        if(ttp){
771            var autoHide = et.getAttribute(cfg.hide, ns);
772            this.activeTarget = {
773                el: t,
774                text: ttp,
775                width: et.getAttribute(cfg.width, ns),
776                autoHide: autoHide != "user" && autoHide !== 'false',
777                title: et.getAttribute(cfg.title, ns),
778                cls: et.getAttribute(cfg.cls, ns),
779                align: et.getAttribute(cfg.align, ns)
780                
781            };
782            this.anchor = et.getAttribute(cfg.anchor, ns);
783            if(this.anchor){
784                this.anchorTarget = t;
785            }
786            this.delayShow();
787        }
788    },
789
790    // private
791    onTargetOut : function(e){
792        this.clearTimer('show');
793        if(this.autoHide !== false){
794            this.delayHide();
795        }
796    },
797
798    // inherit docs
799    showAt : function(xy){
800        var t = this.activeTarget;
801        if(t){
802            if(!this.rendered){
803                this.render(Ext.getBody());
804                this.activeTarget = t;
805            }
806            if(t.width){
807                this.setWidth(t.width);
808                this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
809                this.measureWidth = false;
810            } else{
811                this.measureWidth = true;
812            }
813            this.setTitle(t.title || '');
814            this.body.update(t.text);
815            this.autoHide = t.autoHide;
816            this.dismissDelay = t.dismissDelay || this.dismissDelay;
817            if(this.lastCls){
818                this.el.removeClass(this.lastCls);
819                delete this.lastCls;
820            }
821            if(t.cls){
822                this.el.addClass(t.cls);
823                this.lastCls = t.cls;
824            }
825            if(this.anchor){
826                this.constrainPosition = false;
827            }else if(t.align){ // TODO: this doesn't seem to work consistently
828                xy = this.el.getAlignToXY(t.el, t.align);
829                this.constrainPosition = false;
830            }else{
831                this.constrainPosition = true;
832            }
833        }
834        Ext.QuickTip.superclass.showAt.call(this, xy);
835    },
836
837    // inherit docs
838    hide: function(){
839        delete this.activeTarget;
840        Ext.QuickTip.superclass.hide.call(this);
841    }
842});/**
843 * @class Ext.QuickTips
844 * <p>Provides attractive and customizable tooltips for any element. The QuickTips
845 * singleton is used to configure and manage tooltips globally for multiple elements
846 * in a generic manner.  To create individual tooltips with maximum customizability,
847 * you should consider either {@link Ext.Tip} or {@link Ext.ToolTip}.</p>
848 * <p>Quicktips can be configured via tag attributes directly in markup, or by
849 * registering quick tips programmatically via the {@link #register} method.</p>
850 * <p>The singleton's instance of {@link Ext.QuickTip} is available via
851 * {@link #getQuickTip}, and supports all the methods, and all the all the
852 * configuration properties of Ext.QuickTip. These settings will apply to all
853 * tooltips shown by the singleton.</p>
854 * <p>Below is the summary of the configuration properties which can be used.
855 * For detailed descriptions see {@link #getQuickTip}</p>
856 * <p><b>QuickTips singleton configs (all are optional)</b></p>
857 * <div class="mdetail-params"><ul><li>dismissDelay</li>
858 * <li>hideDelay</li>
859 * <li>maxWidth</li>
860 * <li>minWidth</li>
861 * <li>showDelay</li>
862 * <li>trackMouse</li></ul></div>
863 * <p><b>Target element configs (optional unless otherwise noted)</b></p>
864 * <div class="mdetail-params"><ul><li>autoHide</li>
865 * <li>cls</li>
866 * <li>dismissDelay (overrides singleton value)</li>
867 * <li>target (required)</li>
868 * <li>text (required)</li>
869 * <li>title</li>
870 * <li>width</li></ul></div>
871 * <p>Here is an example showing how some of these config options could be used:</p>
872 * <pre><code>
873// Init the singleton.  Any tag-based quick tips will start working.
874Ext.QuickTips.init();
875
876// Apply a set of config properties to the singleton
877Ext.apply(Ext.QuickTips.getQuickTip(), {
878    maxWidth: 200,
879    minWidth: 100,
880    showDelay: 50,
881    trackMouse: true
882});
883
884// Manually register a quick tip for a specific element
885Ext.QuickTips.register({
886    target: 'my-div',
887    title: 'My Tooltip',
888    text: 'This tooltip was added in code',
889    width: 100,
890    dismissDelay: 20
891});
892</code></pre>
893 * <p>To register a quick tip in markup, you simply add one or more of the valid QuickTip attributes prefixed with
894 * the <b>ext:</b> namespace.  The HTML element itself is automatically set as the quick tip target. Here is the summary
895 * of supported attributes (optional unless otherwise noted):</p>
896 * <ul><li><b>hide</b>: Specifying "user" is equivalent to setting autoHide = false.  Any other value will be the
897 * same as autoHide = true.</li>
898 * <li><b>qclass</b>: A CSS class to be applied to the quick tip (equivalent to the 'cls' target element config).</li>
899 * <li><b>qtip (required)</b>: The quick tip text (equivalent to the 'text' target element config).</li>
900 * <li><b>qtitle</b>: The quick tip title (equivalent to the 'title' target element config).</li>
901 * <li><b>qwidth</b>: The quick tip width (equivalent to the 'width' target element config).</li></ul>
902 * <p>Here is an example of configuring an HTML element to display a tooltip from markup:</p>
903 * <pre><code>
904// Add a quick tip to an HTML button
905&lt;input type="button" value="OK" ext:qtitle="OK Button" ext:qwidth="100"
906     ext:qtip="This is a quick tip from markup!">&lt;/input>
907</code></pre>
908 * @singleton
909 */
910Ext.QuickTips = function(){
911    var tip, locks = [];
912    return {
913        /**
914         * Initialize the global QuickTips instance and prepare any quick tips.
915         * @param {Boolean} autoRender True to render the QuickTips container immediately to preload images. (Defaults to true) 
916         */
917        init : function(autoRender){
918            if(!tip){
919                if(!Ext.isReady){
920                    Ext.onReady(function(){
921                        Ext.QuickTips.init(autoRender);
922                    });
923                    return;
924                }
925                tip = new Ext.QuickTip({elements:'header,body'});
926                if(autoRender !== false){
927                    tip.render(Ext.getBody());
928                }
929            }
930        },
931
932        /**
933         * Enable quick tips globally.
934         */
935        enable : function(){
936            if(tip){
937                locks.pop();
938                if(locks.length < 1){
939                    tip.enable();
940                }
941            }
942        },
943
944        /**
945         * Disable quick tips globally.
946         */
947        disable : function(){
948            if(tip){
949                tip.disable();
950            }
951            locks.push(1);
952        },
953
954        /**
955         * Returns true if quick tips are enabled, else false.
956         * @return {Boolean}
957         */
958        isEnabled : function(){
959            return tip !== undefined && !tip.disabled;
960        },
961
962        /**
963         * Gets the global QuickTips instance.
964         */
965        getQuickTip : function(){
966            return tip;
967        },
968
969        /**
970         * Configures a new quick tip instance and assigns it to a target element.  See
971         * {@link Ext.QuickTip#register} for details.
972         * @param {Object} config The config object
973         */
974        register : function(){
975            tip.register.apply(tip, arguments);
976        },
977
978        /**
979         * Removes any registered quick tip from the target element and destroys it.
980         * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
981         */
982        unregister : function(){
983            tip.unregister.apply(tip, arguments);
984        },
985
986        /**
987         * Alias of {@link #register}.
988         * @param {Object} config The config object
989         */
990        tips :function(){
991            tip.register.apply(tip, arguments);
992        }
993    }
994}();