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