Mercurial > wikked
comparison static/bootstrap/js/bootstrap-tooltip.js @ 88:a5a3d454eac9
Updated Bootstrap.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Fri, 05 Apr 2013 08:08:12 -0700 |
parents | 130eccd396d8 |
children |
comparison
equal
deleted
inserted
replaced
87:c0cf67362fb1 | 88:a5a3d454eac9 |
---|---|
1 /* =========================================================== | 1 /* =========================================================== |
2 * bootstrap-tooltip.js v2.2.2 | 2 * bootstrap-tooltip.js v2.3.1 |
3 * http://twitter.github.com/bootstrap/javascript.html#tooltips | 3 * http://twitter.github.com/bootstrap/javascript.html#tooltips |
4 * Inspired by the original jQuery.tipsy by Jason Frame | 4 * Inspired by the original jQuery.tipsy by Jason Frame |
5 * =========================================================== | 5 * =========================================================== |
6 * Copyright 2012 Twitter, Inc. | 6 * Copyright 2012 Twitter, Inc. |
7 * | 7 * |
36 constructor: Tooltip | 36 constructor: Tooltip |
37 | 37 |
38 , init: function (type, element, options) { | 38 , init: function (type, element, options) { |
39 var eventIn | 39 var eventIn |
40 , eventOut | 40 , eventOut |
41 , triggers | |
42 , trigger | |
43 , i | |
41 | 44 |
42 this.type = type | 45 this.type = type |
43 this.$element = $(element) | 46 this.$element = $(element) |
44 this.options = this.getOptions(options) | 47 this.options = this.getOptions(options) |
45 this.enabled = true | 48 this.enabled = true |
46 | 49 |
47 if (this.options.trigger == 'click') { | 50 triggers = this.options.trigger.split(' ') |
48 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) | 51 |
49 } else if (this.options.trigger != 'manual') { | 52 for (i = triggers.length; i--;) { |
50 eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' | 53 trigger = triggers[i] |
51 eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' | 54 if (trigger == 'click') { |
52 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) | 55 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) |
53 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) | 56 } else if (trigger != 'manual') { |
57 eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' | |
58 eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' | |
59 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) | |
60 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) | |
61 } | |
54 } | 62 } |
55 | 63 |
56 this.options.selector ? | 64 this.options.selector ? |
57 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : | 65 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : |
58 this.fixTitle() | 66 this.fixTitle() |
59 } | 67 } |
60 | 68 |
61 , getOptions: function (options) { | 69 , getOptions: function (options) { |
62 options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) | 70 options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options) |
63 | 71 |
64 if (options.delay && typeof options.delay == 'number') { | 72 if (options.delay && typeof options.delay == 'number') { |
65 options.delay = { | 73 options.delay = { |
66 show: options.delay | 74 show: options.delay |
67 , hide: options.delay | 75 , hide: options.delay |
70 | 78 |
71 return options | 79 return options |
72 } | 80 } |
73 | 81 |
74 , enter: function (e) { | 82 , enter: function (e) { |
75 var self = $(e.currentTarget)[this.type](this._options).data(this.type) | 83 var defaults = $.fn[this.type].defaults |
84 , options = {} | |
85 , self | |
86 | |
87 this._options && $.each(this._options, function (key, value) { | |
88 if (defaults[key] != value) options[key] = value | |
89 }, this) | |
90 | |
91 self = $(e.currentTarget)[this.type](options).data(this.type) | |
76 | 92 |
77 if (!self.options.delay || !self.options.delay.show) return self.show() | 93 if (!self.options.delay || !self.options.delay.show) return self.show() |
78 | 94 |
79 clearTimeout(this.timeout) | 95 clearTimeout(this.timeout) |
80 self.hoverState = 'in' | 96 self.hoverState = 'in' |
95 }, self.options.delay.hide) | 111 }, self.options.delay.hide) |
96 } | 112 } |
97 | 113 |
98 , show: function () { | 114 , show: function () { |
99 var $tip | 115 var $tip |
100 , inside | |
101 , pos | 116 , pos |
102 , actualWidth | 117 , actualWidth |
103 , actualHeight | 118 , actualHeight |
104 , placement | 119 , placement |
105 , tp | 120 , tp |
121 , e = $.Event('show') | |
106 | 122 |
107 if (this.hasContent() && this.enabled) { | 123 if (this.hasContent() && this.enabled) { |
124 this.$element.trigger(e) | |
125 if (e.isDefaultPrevented()) return | |
108 $tip = this.tip() | 126 $tip = this.tip() |
109 this.setContent() | 127 this.setContent() |
110 | 128 |
111 if (this.options.animation) { | 129 if (this.options.animation) { |
112 $tip.addClass('fade') | 130 $tip.addClass('fade') |
114 | 132 |
115 placement = typeof this.options.placement == 'function' ? | 133 placement = typeof this.options.placement == 'function' ? |
116 this.options.placement.call(this, $tip[0], this.$element[0]) : | 134 this.options.placement.call(this, $tip[0], this.$element[0]) : |
117 this.options.placement | 135 this.options.placement |
118 | 136 |
119 inside = /in/.test(placement) | |
120 | |
121 $tip | 137 $tip |
122 .detach() | 138 .detach() |
123 .css({ top: 0, left: 0, display: 'block' }) | 139 .css({ top: 0, left: 0, display: 'block' }) |
124 .insertAfter(this.$element) | 140 |
125 | 141 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) |
126 pos = this.getPosition(inside) | 142 |
143 pos = this.getPosition() | |
127 | 144 |
128 actualWidth = $tip[0].offsetWidth | 145 actualWidth = $tip[0].offsetWidth |
129 actualHeight = $tip[0].offsetHeight | 146 actualHeight = $tip[0].offsetHeight |
130 | 147 |
131 switch (inside ? placement.split(' ')[1] : placement) { | 148 switch (placement) { |
132 case 'bottom': | 149 case 'bottom': |
133 tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} | 150 tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} |
134 break | 151 break |
135 case 'top': | 152 case 'top': |
136 tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} | 153 tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} |
141 case 'right': | 158 case 'right': |
142 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} | 159 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} |
143 break | 160 break |
144 } | 161 } |
145 | 162 |
146 $tip | 163 this.applyPlacement(tp, placement) |
147 .offset(tp) | 164 this.$element.trigger('shown') |
148 .addClass(placement) | 165 } |
149 .addClass('in') | 166 } |
150 } | 167 |
168 , applyPlacement: function(offset, placement){ | |
169 var $tip = this.tip() | |
170 , width = $tip[0].offsetWidth | |
171 , height = $tip[0].offsetHeight | |
172 , actualWidth | |
173 , actualHeight | |
174 , delta | |
175 , replace | |
176 | |
177 $tip | |
178 .offset(offset) | |
179 .addClass(placement) | |
180 .addClass('in') | |
181 | |
182 actualWidth = $tip[0].offsetWidth | |
183 actualHeight = $tip[0].offsetHeight | |
184 | |
185 if (placement == 'top' && actualHeight != height) { | |
186 offset.top = offset.top + height - actualHeight | |
187 replace = true | |
188 } | |
189 | |
190 if (placement == 'bottom' || placement == 'top') { | |
191 delta = 0 | |
192 | |
193 if (offset.left < 0){ | |
194 delta = offset.left * -2 | |
195 offset.left = 0 | |
196 $tip.offset(offset) | |
197 actualWidth = $tip[0].offsetWidth | |
198 actualHeight = $tip[0].offsetHeight | |
199 } | |
200 | |
201 this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') | |
202 } else { | |
203 this.replaceArrow(actualHeight - height, actualHeight, 'top') | |
204 } | |
205 | |
206 if (replace) $tip.offset(offset) | |
207 } | |
208 | |
209 , replaceArrow: function(delta, dimension, position){ | |
210 this | |
211 .arrow() | |
212 .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') | |
151 } | 213 } |
152 | 214 |
153 , setContent: function () { | 215 , setContent: function () { |
154 var $tip = this.tip() | 216 var $tip = this.tip() |
155 , title = this.getTitle() | 217 , title = this.getTitle() |
159 } | 221 } |
160 | 222 |
161 , hide: function () { | 223 , hide: function () { |
162 var that = this | 224 var that = this |
163 , $tip = this.tip() | 225 , $tip = this.tip() |
226 , e = $.Event('hide') | |
227 | |
228 this.$element.trigger(e) | |
229 if (e.isDefaultPrevented()) return | |
164 | 230 |
165 $tip.removeClass('in') | 231 $tip.removeClass('in') |
166 | 232 |
167 function removeWithAnimation() { | 233 function removeWithAnimation() { |
168 var timeout = setTimeout(function () { | 234 var timeout = setTimeout(function () { |
177 | 243 |
178 $.support.transition && this.$tip.hasClass('fade') ? | 244 $.support.transition && this.$tip.hasClass('fade') ? |
179 removeWithAnimation() : | 245 removeWithAnimation() : |
180 $tip.detach() | 246 $tip.detach() |
181 | 247 |
248 this.$element.trigger('hidden') | |
249 | |
182 return this | 250 return this |
183 } | 251 } |
184 | 252 |
185 , fixTitle: function () { | 253 , fixTitle: function () { |
186 var $e = this.$element | 254 var $e = this.$element |
191 | 259 |
192 , hasContent: function () { | 260 , hasContent: function () { |
193 return this.getTitle() | 261 return this.getTitle() |
194 } | 262 } |
195 | 263 |
196 , getPosition: function (inside) { | 264 , getPosition: function () { |
197 return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { | 265 var el = this.$element[0] |
198 width: this.$element[0].offsetWidth | 266 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { |
199 , height: this.$element[0].offsetHeight | 267 width: el.offsetWidth |
200 }) | 268 , height: el.offsetHeight |
269 }, this.$element.offset()) | |
201 } | 270 } |
202 | 271 |
203 , getTitle: function () { | 272 , getTitle: function () { |
204 var title | 273 var title |
205 , $e = this.$element | 274 , $e = this.$element |
211 return title | 280 return title |
212 } | 281 } |
213 | 282 |
214 , tip: function () { | 283 , tip: function () { |
215 return this.$tip = this.$tip || $(this.options.template) | 284 return this.$tip = this.$tip || $(this.options.template) |
285 } | |
286 | |
287 , arrow: function(){ | |
288 return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") | |
216 } | 289 } |
217 | 290 |
218 , validate: function () { | 291 , validate: function () { |
219 if (!this.$element[0].parentNode) { | 292 if (!this.$element[0].parentNode) { |
220 this.hide() | 293 this.hide() |
234 , toggleEnabled: function () { | 307 , toggleEnabled: function () { |
235 this.enabled = !this.enabled | 308 this.enabled = !this.enabled |
236 } | 309 } |
237 | 310 |
238 , toggle: function (e) { | 311 , toggle: function (e) { |
239 var self = $(e.currentTarget)[this.type](this._options).data(this.type) | 312 var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this |
240 self[self.tip().hasClass('in') ? 'hide' : 'show']() | 313 self.tip().hasClass('in') ? self.hide() : self.show() |
241 } | 314 } |
242 | 315 |
243 , destroy: function () { | 316 , destroy: function () { |
244 this.hide().$element.off('.' + this.type).removeData(this.type) | 317 this.hide().$element.off('.' + this.type).removeData(this.type) |
245 } | 318 } |
267 $.fn.tooltip.defaults = { | 340 $.fn.tooltip.defaults = { |
268 animation: true | 341 animation: true |
269 , placement: 'top' | 342 , placement: 'top' |
270 , selector: false | 343 , selector: false |
271 , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' | 344 , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' |
272 , trigger: 'hover' | 345 , trigger: 'hover focus' |
273 , title: '' | 346 , title: '' |
274 , delay: 0 | 347 , delay: 0 |
275 , html: false | 348 , html: false |
349 , container: false | |
276 } | 350 } |
277 | 351 |
278 | 352 |
279 /* TOOLTIP NO CONFLICT | 353 /* TOOLTIP NO CONFLICT |
280 * =================== */ | 354 * =================== */ |