Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / ToolTip.html
1 <html>\r
2 <head>\r
3   <title>The source code</title>\r
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
6 </head>\r
7 <body  onload="prettyPrint();">\r
8     <pre class="prettyprint lang-js"><div id="cls-Ext.ToolTip"></div>/**\r
9  * @class Ext.ToolTip\r
10  * @extends Ext.Tip\r
11  * A standard tooltip implementation for providing additional information when hovering over a target element.\r
12  * @constructor\r
13  * Create a new Tooltip\r
14  * @param {Object} config The configuration options\r
15  */\r
16 Ext.ToolTip = Ext.extend(Ext.Tip, {\r
17     <div id="prop-Ext.ToolTip-triggerElement"></div>/**\r
18      * When a Tooltip is configured with the {@link #delegate} option to cause selected child elements of the {@link #target}\r
19      * Element to each trigger a seperate show event, this property is set to the DOM element which triggered the show.\r
20      * @type DOMElement\r
21      * @property triggerElement\r
22      */\r
23     <div id="cfg-Ext.ToolTip-target"></div>/**\r
24      * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to monitor for mouseover events to trigger\r
25      * showing this ToolTip.\r
26      */\r
27     <div id="cfg-Ext.ToolTip-autoHide"></div>/**\r
28      * @cfg {Boolean} autoHide True to automatically hide the tooltip after the mouse exits the target element\r
29      * or after the {@link #dismissDelay} has expired if set (defaults to true).  If {@link closable} = true a close\r
30      * tool button will be rendered into the tooltip header.\r
31      */\r
32     <div id="cfg-Ext.ToolTip-showDelay"></div>/**\r
33      * @cfg {Number} showDelay Delay in milliseconds before the tooltip displays after the mouse enters the\r
34      * target element (defaults to 500)\r
35      */\r
36     showDelay: 500,\r
37     <div id="cfg-Ext.ToolTip-hideDelay"></div>/**\r
38      * @cfg {Number} hideDelay Delay in milliseconds after the mouse exits the target element but before the\r
39      * tooltip actually hides (defaults to 200).  Set to 0 for the tooltip to hide immediately.\r
40      */\r
41     hideDelay: 200,\r
42     <div id="cfg-Ext.ToolTip-dismissDelay"></div>/**\r
43      * @cfg {Number} dismissDelay Delay in milliseconds before the tooltip automatically hides (defaults to 5000).\r
44      * To disable automatic hiding, set dismissDelay = 0.\r
45      */\r
46     dismissDelay: 5000,\r
47     <div id="cfg-Ext.ToolTip-mouseOffset"></div>/**\r
48      * @cfg {Array} mouseOffset An XY offset from the mouse position where the tooltip should be shown (defaults to [15,18]).\r
49      */\r
50     <div id="cfg-Ext.ToolTip-trackMouse"></div>/**\r
51      * @cfg {Boolean} trackMouse True to have the tooltip follow the mouse as it moves over the target element (defaults to false).\r
52      */\r
53     trackMouse : false,\r
54     <div id="cfg-Ext.ToolTip-anchorToTarget"></div>/**\r
55      * @cfg {Boolean} anchorToTarget True to anchor the tooltip to the target element, false to\r
56      * anchor it relative to the mouse coordinates (defaults to true).  When anchorToTarget is\r
57      * true, use {@link #defaultAlign} to control tooltip alignment to the target element.  When\r
58      * anchorToTarget is false, use {@link #anchorPosition} instead to control alignment.\r
59      */\r
60     anchorToTarget: true,\r
61     <div id="cfg-Ext.ToolTip-anchorOffset"></div>/**\r
62      * @cfg {Number} anchorOffset A numeric pixel value used to offset the default position of the\r
63      * anchor arrow (defaults to 0).  When the anchor position is on the top or bottom of the tooltip,\r
64      * anchorOffset will be used as a horizontal offset.  Likewise, when the anchor position is on the\r
65      * left or right side, anchorOffset will be used as a vertical offset.\r
66      */\r
67     anchorOffset: 0,\r
68     <div id="cfg-Ext.ToolTip-delegate"></div>/**\r
69      * @cfg {String} delegate <p>Optional. A {@link Ext.DomQuery DomQuery} selector which allows selection of individual elements\r
70      * within the {@link #target} element to trigger showing and hiding the ToolTip as the mouse moves within the target.</p>\r
71      * <p>When specified, the child element of the target which caused a show event is placed into the {@link #triggerElement} property\r
72      * before the ToolTip is shown.</p>\r
73      * <p>This may be useful when a Component has regular, repeating elements in it, each of which need a Tooltip which contains\r
74      * information specific to that element. For example:</p><pre><code>\r
75 var myGrid = new Ext.grid.gridPanel(gridConfig);\r
76 myGrid.on('render', function(grid) {\r
77     var store = grid.getStore();  // Capture the Store.\r
78     var view = grid.getView();    // Capture the GridView.\r
79     myGrid.tip = new Ext.ToolTip({\r
80         target: view.mainBody,    // The overall target element.\r
81         delegate: '.x-grid3-row', // Each grid row causes its own seperate show and hide.\r
82         trackMouse: true,         // Moving within the row should not hide the tip.\r
83         renderTo: document.body,  // Render immediately so that tip.body can be referenced prior to the first show.\r
84         listeners: {              // Change content dynamically depending on which element triggered the show.\r
85             beforeshow: function updateTipBody(tip) {\r
86                 var rowIndex = view.findRowIndex(tip.triggerElement);\r
87                 tip.body.dom.innerHTML = "Over Record ID " + store.getAt(rowIndex).id;\r
88             }\r
89         }\r
90     });\r
91 });</code></pre>\r
92      */\r
93 \r
94     // private\r
95     targetCounter: 0,\r
96 \r
97     constrainPosition: false,\r
98 \r
99     // private\r
100     initComponent: function(){\r
101         Ext.ToolTip.superclass.initComponent.call(this);\r
102         this.lastActive = new Date();\r
103         this.initTarget(this.target);\r
104         this.origAnchor = this.anchor;\r
105     },\r
106 \r
107     // private\r
108     onRender : function(ct, position){\r
109         Ext.ToolTip.superclass.onRender.call(this, ct, position);\r
110         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();\r
111         this.anchorEl = this.el.createChild({\r
112             cls: 'x-tip-anchor ' + this.anchorCls\r
113         });\r
114     },\r
115 \r
116     // private\r
117     afterRender : function(){\r
118         Ext.ToolTip.superclass.afterRender.call(this);\r
119         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1);\r
120     },\r
121 \r
122     <div id="method-Ext.ToolTip-initTarget"></div>/**\r
123      * Binds this ToolTip to the specified element. The tooltip will be displayed when the mouse moves over the element.\r
124      * @param {Mixed} t The Element, HtmlElement, or ID of an element to bind to\r
125      */\r
126     initTarget : function(target){\r
127         var t;\r
128         if((t = Ext.get(target))){\r
129             if(this.target){\r
130                 this.target = Ext.get(this.target);\r
131                 this.target.un('mouseover', this.onTargetOver, this);\r
132                 this.target.un('mouseout', this.onTargetOut, this);\r
133                 this.target.un('mousemove', this.onMouseMove, this);\r
134             }\r
135             this.mon(t, {\r
136                 mouseover: this.onTargetOver,\r
137                 mouseout: this.onTargetOut,\r
138                 mousemove: this.onMouseMove,\r
139                 scope: this\r
140             });\r
141             this.target = t;\r
142         }\r
143         if(this.anchor){\r
144             this.anchorTarget = this.target;\r
145         }\r
146     },\r
147 \r
148     // private\r
149     onMouseMove : function(e){\r
150         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;\r
151         if (t) {\r
152             this.targetXY = e.getXY();\r
153             if (t === this.triggerElement) {\r
154                 if(!this.hidden && this.trackMouse){\r
155                     this.setPagePosition(this.getTargetXY());\r
156                 }\r
157             } else {\r
158                 this.hide();\r
159                 this.lastActive = new Date(0);\r
160                 this.onTargetOver(e);\r
161             }\r
162         } else if (!this.closable && this.isVisible()) {\r
163             this.hide();\r
164         }\r
165     },\r
166 \r
167     // private\r
168     getTargetXY : function(){\r
169         if(this.anchor){\r
170             this.targetCounter++;\r
171             var offsets = this.getOffsets();\r
172             var xy = (this.anchorToTarget && !this.trackMouse) ?\r
173                 this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) :\r
174                 this.targetXY;\r
175 \r
176             var dw = Ext.lib.Dom.getViewWidth()-5;\r
177             var dh = Ext.lib.Dom.getViewHeight()-5;\r
178             var scrollX = (document.documentElement.scrollLeft || document.body.scrollLeft || 0)+5;\r
179             var scrollY = (document.documentElement.scrollTop || document.body.scrollTop || 0)+5;\r
180 \r
181             var axy = [xy[0] + offsets[0], xy[1] + offsets[1]];\r
182             var sz = this.getSize();\r
183             this.anchorEl.removeClass(this.anchorCls);\r
184 \r
185             if(this.targetCounter < 2){\r
186                 if(axy[0] < scrollX){\r
187                     if(this.anchorToTarget){\r
188                         this.defaultAlign = 'l-r';\r
189                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}\r
190                     }\r
191                     this.anchor = 'left';\r
192                     return this.getTargetXY();\r
193                 }\r
194                 if(axy[0]+sz.width > dw){\r
195                     if(this.anchorToTarget){\r
196                         this.defaultAlign = 'r-l';\r
197                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}\r
198                     }\r
199                     this.anchor = 'right';\r
200                     return this.getTargetXY();\r
201                 }\r
202                 if(axy[1] < scrollY){\r
203                     if(this.anchorToTarget){\r
204                         this.defaultAlign = 't-b';\r
205                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}\r
206                     }\r
207                     this.anchor = 'top';\r
208                     return this.getTargetXY();\r
209                 }\r
210                 if(axy[1]+sz.height > dh){\r
211                     if(this.anchorToTarget){\r
212                         this.defaultAlign = 'b-t';\r
213                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}\r
214                     }\r
215                     this.anchor = 'bottom';\r
216                     return this.getTargetXY();\r
217                 }\r
218             }\r
219 \r
220             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();\r
221             this.anchorEl.addClass(this.anchorCls);\r
222             this.targetCounter = 0;\r
223             return axy;\r
224         }else{\r
225             var mouseOffset = this.getMouseOffset();\r
226             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];\r
227         }\r
228     },\r
229 \r
230     getMouseOffset : function(){\r
231         var offset = this.anchor ? [0,0] : [15,18];\r
232         if(this.mouseOffset){\r
233             offset[0] += this.mouseOffset[0];\r
234             offset[1] += this.mouseOffset[1];\r
235         }\r
236         return offset;\r
237     },\r
238 \r
239     // private\r
240     getAnchorPosition : function(){\r
241         if(this.anchor){\r
242             this.tipAnchor = this.anchor.charAt(0);\r
243         }else{\r
244             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);\r
245             if(!m){\r
246                throw "AnchorTip.defaultAlign is invalid";\r
247             }\r
248             this.tipAnchor = m[1].charAt(0);\r
249         }\r
250 \r
251         switch(this.tipAnchor){\r
252             case 't': return 'top';\r
253             case 'b': return 'bottom';\r
254             case 'r': return 'right';\r
255         }\r
256         return 'left';\r
257     },\r
258 \r
259     // private\r
260     getAnchorAlign : function(){\r
261         switch(this.anchor){\r
262             case 'top'  : return 'tl-bl';\r
263             case 'left' : return 'tl-tr';\r
264             case 'right': return 'tr-tl';\r
265             default     : return 'bl-tl';\r
266         }\r
267     },\r
268 \r
269     // private\r
270     getOffsets: function(){\r
271         var offsets, ap = this.getAnchorPosition().charAt(0);\r
272         if(this.anchorToTarget && !this.trackMouse){\r
273             switch(ap){\r
274                 case 't':\r
275                     offsets = [0, 9];\r
276                     break;\r
277                 case 'b':\r
278                     offsets = [0, -13];\r
279                     break;\r
280                 case 'r':\r
281                     offsets = [-13, 0];\r
282                     break;\r
283                 default:\r
284                     offsets = [9, 0];\r
285                     break;\r
286             }\r
287         }else{\r
288             switch(ap){\r
289                 case 't':\r
290                     offsets = [-15-this.anchorOffset, 30];\r
291                     break;\r
292                 case 'b':\r
293                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];\r
294                     break;\r
295                 case 'r':\r
296                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];\r
297                     break;\r
298                 default:\r
299                     offsets = [25, -13-this.anchorOffset];\r
300                     break;\r
301             }\r
302         }\r
303         var mouseOffset = this.getMouseOffset();\r
304         offsets[0] += mouseOffset[0];\r
305         offsets[1] += mouseOffset[1];\r
306 \r
307         return offsets;\r
308     },\r
309 \r
310     // private\r
311     onTargetOver : function(e){\r
312         if(this.disabled || e.within(this.target.dom, true)){\r
313             return;\r
314         }\r
315         var t = e.getTarget(this.delegate);\r
316         if (t) {\r
317             this.triggerElement = t;\r
318             this.clearTimer('hide');\r
319             this.targetXY = e.getXY();\r
320             this.delayShow();\r
321         }\r
322     },\r
323 \r
324     // private\r
325     delayShow : function(){\r
326         if(this.hidden && !this.showTimer){\r
327             if(this.lastActive.getElapsed() < this.quickShowInterval){\r
328                 this.show();\r
329             }else{\r
330                 this.showTimer = this.show.defer(this.showDelay, this);\r
331             }\r
332         }else if(!this.hidden && this.autoHide !== false){\r
333             this.show();\r
334         }\r
335     },\r
336 \r
337     // private\r
338     onTargetOut : function(e){\r
339         if(this.disabled || e.within(this.target.dom, true)){\r
340             return;\r
341         }\r
342         this.clearTimer('show');\r
343         if(this.autoHide !== false){\r
344             this.delayHide();\r
345         }\r
346     },\r
347 \r
348     // private\r
349     delayHide : function(){\r
350         if(!this.hidden && !this.hideTimer){\r
351             this.hideTimer = this.hide.defer(this.hideDelay, this);\r
352         }\r
353     },\r
354 \r
355     <div id="method-Ext.ToolTip-hide"></div>/**\r
356      * Hides this tooltip if visible.\r
357      */\r
358     hide: function(){\r
359         this.clearTimer('dismiss');\r
360         this.lastActive = new Date();\r
361         if(this.anchorEl){\r
362             this.anchorEl.hide();\r
363         }\r
364         Ext.ToolTip.superclass.hide.call(this);\r
365         delete this.triggerElement;\r
366     },\r
367 \r
368     <div id="method-Ext.ToolTip-show"></div>/**\r
369      * Shows this tooltip at the current event target XY position.\r
370      */\r
371     show : function(){\r
372         if(this.anchor){\r
373             // pre-show it off screen so that the el will have dimensions\r
374             // for positioning calcs when getting xy next\r
375             this.showAt([-1000,-1000]);\r
376             this.origConstrainPosition = this.constrainPosition;\r
377             this.constrainPosition = false;\r
378             this.anchor = this.origAnchor;\r
379         }\r
380         this.showAt(this.getTargetXY());\r
381 \r
382         if(this.anchor){\r
383             this.syncAnchor();\r
384             this.anchorEl.show();\r
385             this.constrainPosition = this.origConstrainPosition;\r
386         }else{\r
387             this.anchorEl.hide();\r
388         }\r
389     },\r
390 \r
391     // inherit docs\r
392     showAt : function(xy){\r
393         this.lastActive = new Date();\r
394         this.clearTimers();\r
395         Ext.ToolTip.superclass.showAt.call(this, xy);\r
396         if(this.dismissDelay && this.autoHide !== false){\r
397             this.dismissTimer = this.hide.defer(this.dismissDelay, this);\r
398         }\r
399     },\r
400 \r
401     // private\r
402     syncAnchor : function(){\r
403         var anchorPos, targetPos, offset;\r
404         switch(this.tipAnchor.charAt(0)){\r
405             case 't':\r
406                 anchorPos = 'b';\r
407                 targetPos = 'tl';\r
408                 offset = [20+this.anchorOffset, 2];\r
409                 break;\r
410             case 'r':\r
411                 anchorPos = 'l';\r
412                 targetPos = 'tr';\r
413                 offset = [-2, 11+this.anchorOffset];\r
414                 break;\r
415             case 'b':\r
416                 anchorPos = 't';\r
417                 targetPos = 'bl';\r
418                 offset = [20+this.anchorOffset, -2];\r
419                 break;\r
420             default:\r
421                 anchorPos = 'r';\r
422                 targetPos = 'tl';\r
423                 offset = [2, 11+this.anchorOffset];\r
424                 break;\r
425         }\r
426         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);\r
427     },\r
428 \r
429     // private\r
430     setPagePosition : function(x, y){\r
431         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);\r
432         if(this.anchor){\r
433             this.syncAnchor();\r
434         }\r
435     },\r
436 \r
437     // private\r
438     clearTimer : function(name){\r
439         name = name + 'Timer';\r
440         clearTimeout(this[name]);\r
441         delete this[name];\r
442     },\r
443 \r
444     // private\r
445     clearTimers : function(){\r
446         this.clearTimer('show');\r
447         this.clearTimer('dismiss');\r
448         this.clearTimer('hide');\r
449     },\r
450 \r
451     // private\r
452     onShow : function(){\r
453         Ext.ToolTip.superclass.onShow.call(this);\r
454         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);\r
455     },\r
456 \r
457     // private\r
458     onHide : function(){\r
459         Ext.ToolTip.superclass.onHide.call(this);\r
460         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);\r
461     },\r
462 \r
463     // private\r
464     onDocMouseDown : function(e){\r
465         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){\r
466             this.disable();\r
467             this.enable.defer(100, this);\r
468         }\r
469     },\r
470 \r
471     // private\r
472     onDisable : function(){\r
473         this.clearTimers();\r
474         this.hide();\r
475     },\r
476 \r
477     // private\r
478     adjustPosition : function(x, y){\r
479         if(this.contstrainPosition){\r
480             var ay = this.targetXY[1], h = this.getSize().height;\r
481             if(y <= ay && (y+h) >= ay){\r
482                 y = ay-h-5;\r
483             }\r
484         }\r
485         return {x : x, y: y};\r
486     },\r
487 \r
488     // private\r
489     onDestroy : function(){\r
490         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);\r
491         Ext.ToolTip.superclass.onDestroy.call(this);\r
492     }\r
493 });</pre>    \r
494 </body>\r
495 </html>