6dc729942c611590267b9a8ab1308dc4a5486a15
[roojs1] / Roo / bootstrap / Tooltip.js
1 /*
2  * - LGPL
3  *
4  * Tooltip
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.Tooltip
10  * Bootstrap Tooltip class
11  * This is basic at present - all componets support it by default, however they should add tooltipEl() method
12  * to determine which dom element triggers the tooltip.
13  * 
14  * It needs to add support for additional attributes like tooltip-position
15  * 
16  * @constructor
17  * Create a new Toolti
18  * @param {Object} config The config object
19  */
20
21 Roo.bootstrap.Tooltip = function(config){
22     Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
23     
24     this.alignment = Roo.bootstrap.Tooltip.alignment;
25     
26     if(typeof(config) != 'undefined' && typeof(config.alignment) != 'undefined'){
27         this.alignment = config.alignment;
28     }
29     
30 };
31
32 Roo.apply(Roo.bootstrap.Tooltip, {
33     /**
34      * @function init initialize tooltip monitoring.
35      * @static
36      */
37     currentEl : false,
38     currentTip : false,
39     currentRegion : false,
40     
41     //  init : delay?
42     
43     init : function()
44     {
45         Roo.get(document).on('mouseover', this.enter ,this);
46         Roo.get(document).on('mouseout', this.leave, this);
47          
48         
49         this.currentTip = new Roo.bootstrap.Tooltip();
50     },
51     
52     enter : function(ev)
53     {
54         var dom = ev.getTarget();
55         
56         //Roo.log(['enter',dom]);
57         var el = Roo.fly(dom);
58         if (this.currentEl) {
59             //Roo.log(dom);
60             //Roo.log(this.currentEl);
61             //Roo.log(this.currentEl.contains(dom));
62             if (this.currentEl == el) {
63                 return;
64             }
65             if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
66                 return;
67             }
68
69         }
70         
71         if (this.currentTip.el) {
72             this.currentTip.el.setVisibilityMode(Roo.Element.DISPLAY).hide(); // force hiding...
73         }    
74         //Roo.log(ev);
75         
76         if(!el || el.dom == document){
77             return;
78         }
79         
80         var bindEl = el;
81         
82         // you can not look for children, as if el is the body.. then everythign is the child..
83         if (!el.attr('tooltip')) { //
84             if (!el.select("[tooltip]").elements.length) {
85                 return;
86             }
87             // is the mouse over this child...?
88             bindEl = el.select("[tooltip]").first();
89             var xy = ev.getXY();
90             if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
91                 //Roo.log("not in region.");
92                 return;
93             }
94             //Roo.log("child element over..");
95             
96         }
97         this.currentEl = bindEl;
98         this.currentTip.bind(bindEl);
99         this.currentRegion = Roo.lib.Region.getRegion(dom);
100         this.currentTip.enter();
101         
102     },
103     leave : function(ev)
104     {
105         var dom = ev.getTarget();
106         //Roo.log(['leave',dom]);
107         if (!this.currentEl) {
108             return;
109         }
110         
111         
112         if (dom != this.currentEl.dom) {
113             return;
114         }
115         var xy = ev.getXY();
116         if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
117             return;
118         }
119         // only activate leave if mouse cursor is outside... bounding box..
120         
121         
122         
123         
124         if (this.currentTip) {
125             this.currentTip.leave();
126         }
127         //Roo.log('clear currentEl');
128         this.currentEl = false;
129         
130         
131     },
132     alignment : {
133         'left' : ['r-l', [-2,0], 'right'],
134         'right' : ['l-r', [2,0], 'left'],
135         'bottom' : ['t-b', [0,2], 'top'],
136         'top' : [ 'b-t', [0,-2], 'bottom']
137     }
138     
139 });
140
141
142 Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
143     
144     
145     bindEl : false,
146     
147     delay : null, // can be { show : 300 , hide: 500}
148     
149     timeout : null,
150     
151     hoverState : null, //???
152     
153     placement : 'bottom', 
154     
155     alignment : false,
156     
157     getAutoCreate : function(){
158     
159         var cfg = {
160            cls : 'tooltip',
161            role : 'tooltip',
162            cn : [
163                 {
164                     cls : 'tooltip-arrow'
165                 },
166                 {
167                     cls : 'tooltip-inner'
168                 }
169            ]
170         };
171         
172         return cfg;
173     },
174     bind : function(el)
175     {
176         this.bindEl = el;
177     },
178       
179     
180     enter : function () {
181        
182         if (this.timeout != null) {
183             clearTimeout(this.timeout);
184         }
185         
186         this.hoverState = 'in';
187          //Roo.log("enter - show");
188         if (!this.delay || !this.delay.show) {
189             this.show();
190             return;
191         }
192         var _t = this;
193         this.timeout = setTimeout(function () {
194             if (_t.hoverState == 'in') {
195                 _t.show();
196             }
197         }, this.delay.show);
198     },
199     leave : function()
200     {
201         clearTimeout(this.timeout);
202     
203         this.hoverState = 'out';
204          if (!this.delay || !this.delay.hide) {
205             this.hide();
206             return;
207         }
208        
209         var _t = this;
210         this.timeout = setTimeout(function () {
211             //Roo.log("leave - timeout");
212             
213             if (_t.hoverState == 'out') {
214                 _t.hide();
215                 Roo.bootstrap.Tooltip.currentEl = false;
216             }
217         }, delay);
218     },
219     
220     show : function (msg)
221     {
222         if (!this.el) {
223             this.render(document.body);
224         }
225         // set content.
226         //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
227         
228         var tip = msg || this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
229         
230         this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
231         
232         this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
233         
234         var placement = typeof this.placement == 'function' ?
235             this.placement.call(this, this.el, on_el) :
236             this.placement;
237             
238         var autoToken = /\s?auto?\s?/i;
239         var autoPlace = autoToken.test(placement);
240         if (autoPlace) {
241             placement = placement.replace(autoToken, '') || 'top';
242         }
243         
244         //this.el.detach()
245         //this.el.setXY([0,0]);
246         this.el.show();
247         //this.el.dom.style.display='block';
248         
249         //this.el.appendTo(on_el);
250         
251         var p = this.getPosition();
252         var box = this.el.getBox();
253         
254         if (autoPlace) {
255             // fixme..
256         }
257         
258         var align = this.alignment[placement];
259         
260         var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
261         
262         if(placement == 'top' || placement == 'bottom'){
263             if(xy[0] < 0){
264                 placement = 'right';
265             }
266             
267             if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
268                 placement = 'left';
269             }
270             
271             var scroll = Roo.select('body', true).first().getScroll();
272             
273             if(xy[1] > Roo.lib.Dom.getViewHeight() + scroll.top - this.el.getHeight()){
274                 placement = 'top';
275             }
276             
277             align = this.alignment[placement];
278         }
279         
280         this.el.alignTo(this.bindEl, align[0],align[1]);
281         //var arrow = this.el.select('.arrow',true).first();
282         //arrow.set(align[2], 
283         
284         this.el.addClass(placement);
285         
286         this.el.addClass('in fade');
287         
288         this.hoverState = null;
289         
290         if (this.el.hasClass('fade')) {
291             // fade it?
292         }
293         
294     },
295     hide : function()
296     {
297          
298         if (!this.el) {
299             return;
300         }
301         //this.el.setXY([0,0]);
302         this.el.removeClass('in');
303         //this.el.hide();
304         
305     }
306     
307 });
308  
309
310