Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / src / widgets / tips / QuickTip.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.QuickTip\r
9  * @extends Ext.ToolTip\r
10  * @xtype quicktip\r
11  * A specialized tooltip class for tooltips that can be specified in markup and automatically managed by the global\r
12  * {@link Ext.QuickTips} instance.  See the QuickTips class header for additional usage details and examples.\r
13  * @constructor\r
14  * Create a new Tip\r
15  * @param {Object} config The configuration options\r
16  */\r
17 Ext.QuickTip = Ext.extend(Ext.ToolTip, {\r
18     /**\r
19      * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to associate with this quicktip (defaults to the document).\r
20      */\r
21     /**\r
22      * @cfg {Boolean} interceptTitles True to automatically use the element's DOM title value if available (defaults to false).\r
23      */\r
24     interceptTitles : false,\r
25 \r
26     // private\r
27     tagConfig : {\r
28         namespace : "ext",\r
29         attribute : "qtip",\r
30         width : "qwidth",\r
31         target : "target",\r
32         title : "qtitle",\r
33         hide : "hide",\r
34         cls : "qclass",\r
35         align : "qalign",\r
36         anchor : "anchor"\r
37     },\r
38 \r
39     // private\r
40     initComponent : function(){\r
41         this.target = this.target || Ext.getDoc();\r
42         this.targets = this.targets || {};\r
43         Ext.QuickTip.superclass.initComponent.call(this);\r
44     },\r
45 \r
46     /**\r
47      * Configures a new quick tip instance and assigns it to a target element.  The following config values are\r
48      * supported (for example usage, see the {@link Ext.QuickTips} class header):\r
49      * <div class="mdetail-params"><ul>\r
50      * <li>autoHide</li>\r
51      * <li>cls</li>\r
52      * <li>dismissDelay (overrides the singleton value)</li>\r
53      * <li>target (required)</li>\r
54      * <li>text (required)</li>\r
55      * <li>title</li>\r
56      * <li>width</li></ul></div>\r
57      * @param {Object} config The config object\r
58      */\r
59     register : function(config){\r
60         var cs = Ext.isArray(config) ? config : arguments;\r
61         for(var i = 0, len = cs.length; i < len; i++){\r
62             var c = cs[i];\r
63             var target = c.target;\r
64             if(target){\r
65                 if(Ext.isArray(target)){\r
66                     for(var j = 0, jlen = target.length; j < jlen; j++){\r
67                         this.targets[Ext.id(target[j])] = c;\r
68                     }\r
69                 } else{\r
70                     this.targets[Ext.id(target)] = c;\r
71                 }\r
72             }\r
73         }\r
74     },\r
75 \r
76     /**\r
77      * Removes this quick tip from its element and destroys it.\r
78      * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.\r
79      */\r
80     unregister : function(el){\r
81         delete this.targets[Ext.id(el)];\r
82     },\r
83     \r
84     /**\r
85      * Hides a visible tip or cancels an impending show for a particular element.\r
86      * @param {String/HTMLElement/Element} el The element that is the target of the tip.\r
87      */\r
88     cancelShow: function(el){\r
89         var at = this.activeTarget;\r
90         el = Ext.get(el).dom;\r
91         if(this.isVisible()){\r
92             if(at && at.el == el){\r
93                 this.hide();\r
94             }\r
95         }else if(at && at.el == el){\r
96             this.clearTimer('show');\r
97         }\r
98     },\r
99     \r
100     getTipCfg: function(e) {\r
101         var t = e.getTarget(), \r
102             ttp, \r
103             cfg;\r
104         if(this.interceptTitles && t.title && Ext.isString(t.title)){\r
105             ttp = t.title;\r
106             t.qtip = ttp;\r
107             t.removeAttribute("title");\r
108             e.preventDefault();\r
109         }else{\r
110             cfg = this.tagConfig;\r
111             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);\r
112         }\r
113         return ttp;\r
114     },\r
115 \r
116     // private\r
117     onTargetOver : function(e){\r
118         if(this.disabled){\r
119             return;\r
120         }\r
121         this.targetXY = e.getXY();\r
122         var t = e.getTarget();\r
123         if(!t || t.nodeType !== 1 || t == document || t == document.body){\r
124             return;\r
125         }\r
126         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){\r
127             this.clearTimer('hide');\r
128             this.show();\r
129             return;\r
130         }\r
131         if(t && this.targets[t.id]){\r
132             this.activeTarget = this.targets[t.id];\r
133             this.activeTarget.el = t;\r
134             this.anchor = this.activeTarget.anchor;\r
135             if(this.anchor){\r
136                 this.anchorTarget = t;\r
137             }\r
138             this.delayShow();\r
139             return;\r
140         }\r
141         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;\r
142         if(ttp = this.getTipCfg(e)){\r
143             var autoHide = et.getAttribute(cfg.hide, ns);\r
144             this.activeTarget = {\r
145                 el: t,\r
146                 text: ttp,\r
147                 width: et.getAttribute(cfg.width, ns),\r
148                 autoHide: autoHide != "user" && autoHide !== 'false',\r
149                 title: et.getAttribute(cfg.title, ns),\r
150                 cls: et.getAttribute(cfg.cls, ns),\r
151                 align: et.getAttribute(cfg.align, ns)\r
152                 \r
153             };\r
154             this.anchor = et.getAttribute(cfg.anchor, ns);\r
155             if(this.anchor){\r
156                 this.anchorTarget = t;\r
157             }\r
158             this.delayShow();\r
159         }\r
160     },\r
161 \r
162     // private\r
163     onTargetOut : function(e){\r
164 \r
165         // If moving within the current target, and it does not have a new tip, ignore the mouseout\r
166         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {\r
167             return;\r
168         }\r
169 \r
170         this.clearTimer('show');\r
171         if(this.autoHide !== false){\r
172             this.delayHide();\r
173         }\r
174     },\r
175 \r
176     // inherit docs\r
177     showAt : function(xy){\r
178         var t = this.activeTarget;\r
179         if(t){\r
180             if(!this.rendered){\r
181                 this.render(Ext.getBody());\r
182                 this.activeTarget = t;\r
183             }\r
184             if(t.width){\r
185                 this.setWidth(t.width);\r
186                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));\r
187                 this.measureWidth = false;\r
188             } else{\r
189                 this.measureWidth = true;\r
190             }\r
191             this.setTitle(t.title || '');\r
192             this.body.update(t.text);\r
193             this.autoHide = t.autoHide;\r
194             this.dismissDelay = t.dismissDelay || this.dismissDelay;\r
195             if(this.lastCls){\r
196                 this.el.removeClass(this.lastCls);\r
197                 delete this.lastCls;\r
198             }\r
199             if(t.cls){\r
200                 this.el.addClass(t.cls);\r
201                 this.lastCls = t.cls;\r
202             }\r
203             if(this.anchor){\r
204                 this.constrainPosition = false;\r
205             }else if(t.align){ // TODO: this doesn't seem to work consistently\r
206                 xy = this.el.getAlignToXY(t.el, t.align);\r
207                 this.constrainPosition = false;\r
208             }else{\r
209                 this.constrainPosition = true;\r
210             }\r
211         }\r
212         Ext.QuickTip.superclass.showAt.call(this, xy);\r
213     },\r
214 \r
215     // inherit docs\r
216     hide: function(){\r
217         delete this.activeTarget;\r
218         Ext.QuickTip.superclass.hide.call(this);\r
219     }\r
220 });\r
221 Ext.reg('quicktip', Ext.QuickTip);