fix #7391 -New_Customer_Portal_30_Login
[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         var pel = false;
82         if (!el.attr('tooltip')) {
83             pel = el.findParent("[tooltip]");
84             if (pel) {
85                 bindEl = Roo.get(pel);
86             }
87         }
88         
89        
90         
91         // you can not look for children, as if el is the body.. then everythign is the child..
92         if (!pel && !el.attr('tooltip')) { //
93             if (!el.select("[tooltip]").elements.length) {
94                 return;
95             }
96             // is the mouse over this child...?
97             bindEl = el.select("[tooltip]").first();
98             var xy = ev.getXY();
99             if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
100                 //Roo.log("not in region.");
101                 return;
102             }
103             //Roo.log("child element over..");
104             
105         }
106         this.currentEl = el;
107         this.currentTip.bind(bindEl);
108         this.currentRegion = Roo.lib.Region.getRegion(dom);
109         this.currentTip.enter();
110         
111     },
112     leave : function(ev)
113     {
114         var dom = ev.getTarget();
115         //Roo.log(['leave',dom]);
116         if (!this.currentEl) {
117             return;
118         }
119         
120         
121         if (dom != this.currentEl.dom) {
122             return;
123         }
124         var xy = ev.getXY();
125         if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
126             return;
127         }
128         // only activate leave if mouse cursor is outside... bounding box..
129         
130         
131         
132         
133         if (this.currentTip) {
134             this.currentTip.leave();
135         }
136         //Roo.log('clear currentEl');
137         this.currentEl = false;
138         
139         
140     },
141     alignment : {
142         'left' : ['r-l', [-2,0], 'right'],
143         'right' : ['l-r', [2,0], 'left'],
144         'bottom' : ['t-b', [0,2], 'top'],
145         'top' : [ 'b-t', [0,-2], 'bottom']
146     }
147     
148 });
149
150
151 Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
152     
153     
154     bindEl : false,
155     
156     delay : null, // can be { show : 300 , hide: 500}
157     
158     timeout : null,
159     
160     hoverState : null, //???
161     
162     placement : 'bottom', 
163     
164     alignment : false,
165     
166     getAutoCreate : function(){
167     
168         var cfg = {
169            cls : 'tooltip',   
170            role : 'tooltip',
171            cn : [
172                 {
173                     cls : 'tooltip-arrow arrow'
174                 },
175                 {
176                     cls : 'tooltip-inner'
177                 }
178            ]
179         };
180         
181         return cfg;
182     },
183     bind : function(el)
184     {
185         this.bindEl = el;
186     },
187     
188     initEvents : function()
189     {
190         this.arrowEl = this.el.select('.arrow', true).first();
191         this.innerEl = this.el.select('.tooltip-inner', true).first();
192     },
193     
194     enter : function () {
195        
196         if (this.timeout != null) {
197             clearTimeout(this.timeout);
198         }
199         
200         this.hoverState = 'in';
201          //Roo.log("enter - show");
202         if (!this.delay || !this.delay.show) {
203             this.show();
204             return;
205         }
206         var _t = this;
207         this.timeout = setTimeout(function () {
208             if (_t.hoverState == 'in') {
209                 _t.show();
210             }
211         }, this.delay.show);
212     },
213     leave : function()
214     {
215         clearTimeout(this.timeout);
216     
217         this.hoverState = 'out';
218          if (!this.delay || !this.delay.hide) {
219             this.hide();
220             return;
221         }
222        
223         var _t = this;
224         this.timeout = setTimeout(function () {
225             //Roo.log("leave - timeout");
226             
227             if (_t.hoverState == 'out') {
228                 _t.hide();
229                 Roo.bootstrap.Tooltip.currentEl = false;
230             }
231         }, delay);
232     },
233     
234     show : function (msg)
235     {
236         if (!this.el) {
237             this.render(document.body);
238         }
239         // set content.
240         //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
241         
242         var tip = msg || this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
243         
244         this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
245         
246         this.el.removeClass(['fade','top','bottom', 'left', 'right','in',
247                              'bs-tooltip-top','bs-tooltip-bottom', 'bs-tooltip-left', 'bs-tooltip-right']);
248
249         if(this.bindEl.attr('tooltip-class')) {
250             this.el.addClass(this.bindEl.attr('tooltip-class'));
251         }
252         
253         var placement = typeof this.placement == 'function' ?
254             this.placement.call(this, this.el, on_el) :
255             this.placement;
256         
257         if(this.bindEl.attr('tooltip-placement')) {
258             placement = this.bindEl.attr('tooltip-placement');
259         }
260             
261         var autoToken = /\s?auto?\s?/i;
262         var autoPlace = autoToken.test(placement);
263         if (autoPlace) {
264             placement = placement.replace(autoToken, '') || 'top';
265         }
266         
267         //this.el.detach()
268         //this.el.setXY([0,0]);
269         this.el.show();
270         //this.el.dom.style.display='block';
271         
272         //this.el.appendTo(on_el);
273         
274         var p = this.getPosition();
275         var box = this.el.getBox();
276         
277         if (autoPlace) {
278             // fixme..
279         }
280         
281         var align = this.alignment[placement];
282         
283         var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
284         
285         if(placement == 'top' || placement == 'bottom'){
286             if(xy[0] < 0){
287                 placement = 'right';
288             }
289             
290             if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
291                 placement = 'left';
292             }
293             
294             var scroll = Roo.select('body', true).first().getScroll();
295             
296             if(xy[1] > Roo.lib.Dom.getViewHeight() + scroll.top - this.el.getHeight()){
297                 placement = 'top';
298             }
299             
300             align = this.alignment[placement];
301             
302             this.arrowEl.setLeft((this.innerEl.getWidth()/2) - 5);
303             
304         }
305         
306         var elems = document.getElementsByTagName('div');
307         var highest = Number.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1);
308         for (var i = 0; i < elems.length; i++) {
309           var zindex = Number.parseInt(
310                 document.defaultView.getComputedStyle(elems[i], null).getPropertyValue("z-index"),
311                 10
312           );
313           if (zindex > highest) {
314             highest = zindex;
315           }
316         }
317         
318         
319         
320         this.el.dom.style.zIndex = highest;
321         
322         this.el.alignTo(this.bindEl, align[0],align[1]);
323         //var arrow = this.el.select('.arrow',true).first();
324         //arrow.set(align[2], 
325         
326         this.el.addClass(placement);
327         this.el.addClass("bs-tooltip-"+ placement);
328         
329         this.el.addClass('in fade show');
330         
331         this.hoverState = null;
332         
333         if (this.el.hasClass('fade')) {
334             // fade it?
335         }
336         
337         
338         
339         
340         
341     },
342     hide : function()
343     {
344          
345         if (!this.el) {
346             return;
347         }
348         //this.el.setXY([0,0]);
349         if(this.bindEl.attr('tooltip-class')) {
350             this.el.removeClass(this.bindEl.attr('tooltip-class'));
351         }
352         this.el.removeClass(['show', 'in']);
353         //this.el.hide();
354         
355     }
356     
357 });
358  
359
360