pkg-tips-debug.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:36k
源码类别:

JavaScript

开发平台:

JavaScript

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