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.
14 * It needs to add support for additional attributes like tooltip-position
18 * @param {Object} config The config object
21 Roo.bootstrap.Tooltip = function(config){
22 Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
24 this.alignment = Roo.bootstrap.Tooltip.alignment;
26 if(typeof(config) != 'undefined' && typeof(config.alignment) != 'undefined'){
27 this.alignment = config.alignment;
32 Roo.apply(Roo.bootstrap.Tooltip, {
34 * @function init initialize tooltip monitoring.
39 currentRegion : false,
45 Roo.get(document).on('mouseover', this.enter ,this);
46 Roo.get(document).on('mouseout', this.leave, this);
49 this.currentTip = new Roo.bootstrap.Tooltip();
54 var dom = ev.getTarget();
56 //Roo.log(['enter',dom]);
57 var el = Roo.fly(dom);
58 Roo.log("Tooltip enter");
63 //Roo.log(this.currentEl);
64 //Roo.log(this.currentEl.contains(dom));
65 if (this.currentEl == el) {
68 if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
74 if (this.currentTip.el) {
75 this.currentTip.el.setVisibilityMode(Roo.Element.DISPLAY).hide(); // force hiding...
79 if(!el || el.dom == document){
85 if (!el.attr('tooltip')) {
86 pel = el.findParent("[tooltip]");
88 bindEl = Roo.get(pel);
94 // you can not look for children, as if el is the body.. then everythign is the child..
95 if (!pel && !el.attr('tooltip')) { //
96 if (!el.select("[tooltip]").elements.length) {
99 // is the mouse over this child...?
100 bindEl = el.select("[tooltip]").first();
102 if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
103 //Roo.log("not in region.");
106 //Roo.log("child element over..");
110 this.currentTip.bind(bindEl);
111 this.currentRegion = Roo.lib.Region.getRegion(dom);
112 this.currentTip.enter();
117 var dom = ev.getTarget();
118 //Roo.log(['leave',dom]);
119 if (!this.currentEl) {
124 if (dom != this.currentEl.dom) {
128 if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0] ))) {
131 // only activate leave if mouse cursor is outside... bounding box..
136 if (this.currentTip) {
137 this.currentTip.leave();
139 //Roo.log('clear currentEl');
140 this.currentEl = false;
145 'left' : ['r-l', [-2,0], 'right'],
146 'right' : ['l-r', [2,0], 'left'],
147 'bottom' : ['t-b', [0,2], 'top'],
148 'top' : [ 'b-t', [0,-2], 'bottom']
154 Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, {
159 delay : null, // can be { show : 300 , hide: 500}
163 hoverState : null, //???
165 placement : 'bottom',
169 getAutoCreate : function(){
176 cls : 'tooltip-arrow arrow'
179 cls : 'tooltip-inner'
191 initEvents : function()
193 this.arrowEl = this.el.select('.arrow', true).first();
194 this.innerEl = this.el.select('.tooltip-inner', true).first();
197 enter : function () {
199 if (this.timeout != null) {
200 clearTimeout(this.timeout);
203 this.hoverState = 'in';
204 //Roo.log("enter - show");
205 if (!this.delay || !this.delay.show) {
210 this.timeout = setTimeout(function () {
211 if (_t.hoverState == 'in') {
218 clearTimeout(this.timeout);
220 this.hoverState = 'out';
221 if (!this.delay || !this.delay.hide) {
227 this.timeout = setTimeout(function () {
228 //Roo.log("leave - timeout");
230 if (_t.hoverState == 'out') {
232 Roo.bootstrap.Tooltip.currentEl = false;
237 show : function (msg)
240 this.render(document.body);
243 //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
245 var tip = msg || this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
247 this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
249 this.el.removeClass(['fade','top','bottom', 'left', 'right','in',
250 'bs-tooltip-top','bs-tooltip-bottom', 'bs-tooltip-left', 'bs-tooltip-right']);
252 var placement = typeof this.placement == 'function' ?
253 this.placement.call(this, this.el, on_el) :
256 var autoToken = /\s?auto?\s?/i;
257 var autoPlace = autoToken.test(placement);
259 placement = placement.replace(autoToken, '') || 'top';
263 //this.el.setXY([0,0]);
265 //this.el.dom.style.display='block';
267 //this.el.appendTo(on_el);
269 var p = this.getPosition();
270 var box = this.el.getBox();
276 var align = this.alignment[placement];
278 var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
280 if(placement == 'top' || placement == 'bottom'){
285 if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
289 var scroll = Roo.select('body', true).first().getScroll();
291 if(xy[1] > Roo.lib.Dom.getViewHeight() + scroll.top - this.el.getHeight()){
295 align = this.alignment[placement];
297 this.arrowEl.setLeft((this.innerEl.getWidth()/2) - 5);
301 var elems = document.getElementsByTagName('div');
302 var highest = Number.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1);
303 for (var i = 0; i < elems.length; i++) {
304 var zindex = Number.parseInt(
305 document.defaultView.getComputedStyle(elems[i], null).getPropertyValue("z-index"),
308 if (zindex > highest) {
315 this.el.dom.style.zIndex = highest;
317 this.el.alignTo(this.bindEl, align[0],align[1]);
318 //var arrow = this.el.select('.arrow',true).first();
319 //arrow.set(align[2],
321 this.el.addClass(placement);
322 this.el.addClass("bs-tooltip-"+ placement);
324 this.el.addClass('in fade show');
326 this.hoverState = null;
328 if (this.el.hasClass('fade')) {
343 //this.el.setXY([0,0]);
344 this.el.removeClass(['show', 'in']);