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