twitter-bootstrap-rails 3.2.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of twitter-bootstrap-rails might be problematic. Click here for more details.

Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -130
  3. data/app/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  4. data/app/assets/fonts/glyphicons-halflings-regular.svg +273 -214
  5. data/app/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  6. data/app/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  7. data/app/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  8. data/app/assets/javascripts/twitter/bootstrap/affix.js +46 -26
  9. data/app/assets/javascripts/twitter/bootstrap/alert.js +7 -5
  10. data/app/assets/javascripts/twitter/bootstrap/button.js +27 -17
  11. data/app/assets/javascripts/twitter/bootstrap/carousel.js +35 -21
  12. data/app/assets/javascripts/twitter/bootstrap/collapse.js +68 -27
  13. data/app/assets/javascripts/twitter/bootstrap/dropdown.js +55 -41
  14. data/app/assets/javascripts/twitter/bootstrap/modal.js +88 -31
  15. data/app/assets/javascripts/twitter/bootstrap/popover.js +5 -10
  16. data/app/assets/javascripts/twitter/bootstrap/scrollspy.js +28 -26
  17. data/app/assets/javascripts/twitter/bootstrap/tab.js +45 -18
  18. data/app/assets/javascripts/twitter/bootstrap/tooltip.js +111 -54
  19. data/app/assets/javascripts/twitter/bootstrap/transition.js +2 -2
  20. data/app/helpers/glyph_helper.rb +6 -3
  21. data/lib/generators/bootstrap/install/templates/bootstrap_and_overrides.css +3 -4
  22. data/lib/generators/bootstrap/install/templates/bootstrap_and_overrides.less +7 -18
  23. data/lib/generators/bootstrap/themed/templates/index.html.erb +2 -0
  24. data/lib/generators/bootstrap/themed/templates/index.html.haml +1 -0
  25. data/lib/generators/bootstrap/themed/templates/index.html.slim +2 -0
  26. data/lib/twitter/bootstrap/rails/version.rb +1 -1
  27. data/vendor/toolkit/twitter/bootstrap/alerts.less +5 -0
  28. data/vendor/toolkit/twitter/bootstrap/badges.less +14 -3
  29. data/vendor/toolkit/twitter/bootstrap/bootstrap.less +6 -0
  30. data/vendor/toolkit/twitter/bootstrap/breadcrumbs.less +0 -0
  31. data/vendor/toolkit/twitter/bootstrap/button-groups.less +13 -14
  32. data/vendor/toolkit/twitter/bootstrap/buttons.less +14 -7
  33. data/vendor/toolkit/twitter/bootstrap/carousel.less +34 -7
  34. data/vendor/toolkit/twitter/bootstrap/close.less +1 -0
  35. data/vendor/toolkit/twitter/bootstrap/code.less +0 -0
  36. data/vendor/toolkit/twitter/bootstrap/component-animations.less +3 -1
  37. data/vendor/toolkit/twitter/bootstrap/dropdowns.less +9 -8
  38. data/vendor/toolkit/twitter/bootstrap/forms.less +110 -41
  39. data/vendor/toolkit/twitter/bootstrap/glyphicons.less +80 -9
  40. data/vendor/toolkit/twitter/bootstrap/grid.less +0 -0
  41. data/vendor/toolkit/twitter/bootstrap/input-groups.less +8 -3
  42. data/vendor/toolkit/twitter/bootstrap/jumbotron.less +10 -4
  43. data/vendor/toolkit/twitter/bootstrap/labels.less +0 -0
  44. data/vendor/toolkit/twitter/bootstrap/list-group.less +11 -13
  45. data/vendor/toolkit/twitter/bootstrap/media.less +40 -30
  46. data/vendor/toolkit/twitter/bootstrap/mixins.less +1 -0
  47. data/vendor/toolkit/twitter/bootstrap/mixins/alerts.less +0 -0
  48. data/vendor/toolkit/twitter/bootstrap/mixins/background-variant.less +2 -1
  49. data/vendor/toolkit/twitter/bootstrap/mixins/border-radius.less +0 -0
  50. data/vendor/toolkit/twitter/bootstrap/mixins/buttons.less +19 -6
  51. data/vendor/toolkit/twitter/bootstrap/mixins/center-block.less +0 -0
  52. data/vendor/toolkit/twitter/bootstrap/mixins/clearfix.less +0 -0
  53. data/vendor/toolkit/twitter/bootstrap/mixins/forms.less +0 -0
  54. data/vendor/toolkit/twitter/bootstrap/mixins/gradients.less +0 -0
  55. data/vendor/toolkit/twitter/bootstrap/mixins/grid-framework.less +4 -4
  56. data/vendor/toolkit/twitter/bootstrap/mixins/grid.less +4 -4
  57. data/vendor/toolkit/twitter/bootstrap/mixins/hide-text.less +2 -2
  58. data/vendor/toolkit/twitter/bootstrap/mixins/image.less +0 -0
  59. data/vendor/toolkit/twitter/bootstrap/mixins/labels.less +1 -1
  60. data/vendor/toolkit/twitter/bootstrap/mixins/list-group.less +2 -1
  61. data/vendor/toolkit/twitter/bootstrap/mixins/nav-divider.less +0 -0
  62. data/vendor/toolkit/twitter/bootstrap/mixins/nav-vertical-align.less +0 -0
  63. data/vendor/toolkit/twitter/bootstrap/mixins/opacity.less +0 -0
  64. data/vendor/toolkit/twitter/bootstrap/mixins/pagination.less +2 -1
  65. data/vendor/toolkit/twitter/bootstrap/mixins/panels.less +0 -0
  66. data/vendor/toolkit/twitter/bootstrap/mixins/progress-bar.less +0 -0
  67. data/vendor/toolkit/twitter/bootstrap/mixins/reset-filter.less +0 -0
  68. data/vendor/toolkit/twitter/bootstrap/mixins/reset-text.less +18 -0
  69. data/vendor/toolkit/twitter/bootstrap/mixins/resize.less +0 -0
  70. data/vendor/toolkit/twitter/bootstrap/mixins/responsive-visibility.less +1 -1
  71. data/vendor/toolkit/twitter/bootstrap/mixins/size.less +0 -0
  72. data/vendor/toolkit/twitter/bootstrap/mixins/tab-focus.less +0 -0
  73. data/vendor/toolkit/twitter/bootstrap/mixins/table-row.less +0 -0
  74. data/vendor/toolkit/twitter/bootstrap/mixins/text-emphasis.less +2 -1
  75. data/vendor/toolkit/twitter/bootstrap/mixins/text-overflow.less +0 -0
  76. data/vendor/toolkit/twitter/bootstrap/mixins/vendor-prefixes.less +8 -5
  77. data/vendor/toolkit/twitter/bootstrap/modals.less +3 -3
  78. data/vendor/toolkit/twitter/bootstrap/navbar.less +6 -1
  79. data/vendor/toolkit/twitter/bootstrap/navs.less +1 -1
  80. data/vendor/toolkit/twitter/bootstrap/normalize.less +12 -13
  81. data/vendor/toolkit/twitter/bootstrap/pager.less +1 -2
  82. data/vendor/toolkit/twitter/bootstrap/pagination.less +5 -4
  83. data/vendor/toolkit/twitter/bootstrap/panels.less +27 -4
  84. data/vendor/toolkit/twitter/bootstrap/popovers.less +5 -7
  85. data/vendor/toolkit/twitter/bootstrap/print.less +96 -96
  86. data/vendor/toolkit/twitter/bootstrap/progress-bars.less +1 -14
  87. data/vendor/toolkit/twitter/bootstrap/responsive-embed.less +10 -9
  88. data/vendor/toolkit/twitter/bootstrap/responsive-utilities.less +0 -0
  89. data/vendor/toolkit/twitter/bootstrap/scaffolding.less +12 -1
  90. data/vendor/toolkit/twitter/bootstrap/tables.less +6 -5
  91. data/vendor/toolkit/twitter/bootstrap/theme.less +47 -16
  92. data/vendor/toolkit/twitter/bootstrap/thumbnails.less +1 -1
  93. data/vendor/toolkit/twitter/bootstrap/tooltip.less +13 -7
  94. data/vendor/toolkit/twitter/bootstrap/type.less +2 -8
  95. data/vendor/toolkit/twitter/bootstrap/utilities.less +0 -1
  96. data/vendor/toolkit/twitter/bootstrap/variables.less +36 -14
  97. data/vendor/toolkit/twitter/bootstrap/wells.less +0 -0
  98. metadata +45 -56
  99. data/app/assets/fonts/fontawesome-webfont.eot +0 -0
  100. data/app/assets/fonts/fontawesome-webfont.svg +0 -640
  101. data/app/assets/fonts/fontawesome-webfont.ttf +0 -0
  102. data/app/assets/fonts/fontawesome-webfont.woff +0 -0
  103. data/app/assets/stylesheets/twitter-bootstrap-static/fontawesome.css.erb +0 -2026
  104. data/vendor/static-source/fontawesome.less +0 -8
  105. data/vendor/toolkit/fontawesome/bordered-pulled.less +0 -16
  106. data/vendor/toolkit/fontawesome/core.less +0 -11
  107. data/vendor/toolkit/fontawesome/fixed-width.less +0 -6
  108. data/vendor/toolkit/fontawesome/font-awesome.less +0 -17
  109. data/vendor/toolkit/fontawesome/icons.less +0 -552
  110. data/vendor/toolkit/fontawesome/larger.less +0 -13
  111. data/vendor/toolkit/fontawesome/list.less +0 -19
  112. data/vendor/toolkit/fontawesome/mixins.less +0 -25
  113. data/vendor/toolkit/fontawesome/path.less +0 -14
  114. data/vendor/toolkit/fontawesome/rotated-flipped.less +0 -20
  115. data/vendor/toolkit/fontawesome/spinning.less +0 -29
  116. data/vendor/toolkit/fontawesome/stacked.less +0 -20
  117. data/vendor/toolkit/fontawesome/variables.less +0 -561
@@ -1,8 +1,8 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tab.js v3.2.0
2
+ * Bootstrap: tab.js v3.3.6
3
3
  * http://getbootstrap.com/javascript/#tabs
4
4
  * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
5
+ * Copyright 2011-2015 Twitter, Inc.
6
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
7
  * ======================================================================== */
8
8
 
@@ -14,10 +14,14 @@
14
14
  // ====================
15
15
 
16
16
  var Tab = function (element) {
17
+ // jscs:disable requireDollarBeforejQueryAssignment
17
18
  this.element = $(element)
19
+ // jscs:enable requireDollarBeforejQueryAssignment
18
20
  }
19
21
 
20
- Tab.VERSION = '3.2.0'
22
+ Tab.VERSION = '3.3.6'
23
+
24
+ Tab.TRANSITION_DURATION = 150
21
25
 
22
26
  Tab.prototype.show = function () {
23
27
  var $this = this.element
@@ -31,22 +35,30 @@
31
35
 
32
36
  if ($this.parent('li').hasClass('active')) return
33
37
 
34
- var previous = $ul.find('.active:last a')[0]
35
- var e = $.Event('show.bs.tab', {
36
- relatedTarget: previous
38
+ var $previous = $ul.find('.active:last a')
39
+ var hideEvent = $.Event('hide.bs.tab', {
40
+ relatedTarget: $this[0]
41
+ })
42
+ var showEvent = $.Event('show.bs.tab', {
43
+ relatedTarget: $previous[0]
37
44
  })
38
45
 
39
- $this.trigger(e)
46
+ $previous.trigger(hideEvent)
47
+ $this.trigger(showEvent)
40
48
 
41
- if (e.isDefaultPrevented()) return
49
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
42
50
 
43
51
  var $target = $(selector)
44
52
 
45
53
  this.activate($this.closest('li'), $ul)
46
54
  this.activate($target, $target.parent(), function () {
55
+ $previous.trigger({
56
+ type: 'hidden.bs.tab',
57
+ relatedTarget: $this[0]
58
+ })
47
59
  $this.trigger({
48
60
  type: 'shown.bs.tab',
49
- relatedTarget: previous
61
+ relatedTarget: $previous[0]
50
62
  })
51
63
  })
52
64
  }
@@ -55,15 +67,21 @@
55
67
  var $active = container.find('> .active')
56
68
  var transition = callback
57
69
  && $.support.transition
58
- && $active.hasClass('fade')
70
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
59
71
 
60
72
  function next() {
61
73
  $active
62
74
  .removeClass('active')
63
75
  .find('> .dropdown-menu > .active')
64
- .removeClass('active')
76
+ .removeClass('active')
77
+ .end()
78
+ .find('[data-toggle="tab"]')
79
+ .attr('aria-expanded', false)
65
80
 
66
- element.addClass('active')
81
+ element
82
+ .addClass('active')
83
+ .find('[data-toggle="tab"]')
84
+ .attr('aria-expanded', true)
67
85
 
68
86
  if (transition) {
69
87
  element[0].offsetWidth // reflow for transition
@@ -72,17 +90,22 @@
72
90
  element.removeClass('fade')
73
91
  }
74
92
 
75
- if (element.parent('.dropdown-menu')) {
76
- element.closest('li.dropdown').addClass('active')
93
+ if (element.parent('.dropdown-menu').length) {
94
+ element
95
+ .closest('li.dropdown')
96
+ .addClass('active')
97
+ .end()
98
+ .find('[data-toggle="tab"]')
99
+ .attr('aria-expanded', true)
77
100
  }
78
101
 
79
102
  callback && callback()
80
103
  }
81
104
 
82
- transition ?
105
+ $active.length && transition ?
83
106
  $active
84
107
  .one('bsTransitionEnd', next)
85
- .emulateTransitionEnd(150) :
108
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
86
109
  next()
87
110
 
88
111
  $active.removeClass('in')
@@ -120,9 +143,13 @@
120
143
  // TAB DATA-API
121
144
  // ============
122
145
 
123
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
146
+ var clickHandler = function (e) {
124
147
  e.preventDefault()
125
148
  Plugin.call($(this), 'show')
126
- })
149
+ }
150
+
151
+ $(document)
152
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
153
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
127
154
 
128
155
  }(jQuery);
@@ -1,9 +1,9 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tooltip.js v3.2.0
2
+ * Bootstrap: tooltip.js v3.3.6
3
3
  * http://getbootstrap.com/javascript/#tooltip
4
4
  * Inspired by the original jQuery.tipsy by Jason Frame
5
5
  * ========================================================================
6
- * Copyright 2011-2014 Twitter, Inc.
6
+ * Copyright 2011-2015 Twitter, Inc.
7
7
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8
8
  * ======================================================================== */
9
9
 
@@ -15,17 +15,20 @@
15
15
  // ===============================
16
16
 
17
17
  var Tooltip = function (element, options) {
18
- this.type =
19
- this.options =
20
- this.enabled =
21
- this.timeout =
22
- this.hoverState =
18
+ this.type = null
19
+ this.options = null
20
+ this.enabled = null
21
+ this.timeout = null
22
+ this.hoverState = null
23
23
  this.$element = null
24
+ this.inState = null
24
25
 
25
26
  this.init('tooltip', element, options)
26
27
  }
27
28
 
28
- Tooltip.VERSION = '3.2.0'
29
+ Tooltip.VERSION = '3.3.6'
30
+
31
+ Tooltip.TRANSITION_DURATION = 150
29
32
 
30
33
  Tooltip.DEFAULTS = {
31
34
  animation: true,
@@ -48,7 +51,12 @@
48
51
  this.type = type
49
52
  this.$element = $(element)
50
53
  this.options = this.getOptions(options)
51
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
54
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
55
+ this.inState = { click: false, hover: false, focus: false }
56
+
57
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
58
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
59
+ }
52
60
 
53
61
  var triggers = this.options.trigger.split(' ')
54
62
 
@@ -108,6 +116,15 @@
108
116
  $(obj.currentTarget).data('bs.' + this.type, self)
109
117
  }
110
118
 
119
+ if (obj instanceof $.Event) {
120
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
121
+ }
122
+
123
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
124
+ self.hoverState = 'in'
125
+ return
126
+ }
127
+
111
128
  clearTimeout(self.timeout)
112
129
 
113
130
  self.hoverState = 'in'
@@ -119,6 +136,14 @@
119
136
  }, self.options.delay.show)
120
137
  }
121
138
 
139
+ Tooltip.prototype.isInStateTrue = function () {
140
+ for (var key in this.inState) {
141
+ if (this.inState[key]) return true
142
+ }
143
+
144
+ return false
145
+ }
146
+
122
147
  Tooltip.prototype.leave = function (obj) {
123
148
  var self = obj instanceof this.constructor ?
124
149
  obj : $(obj.currentTarget).data('bs.' + this.type)
@@ -128,6 +153,12 @@
128
153
  $(obj.currentTarget).data('bs.' + this.type, self)
129
154
  }
130
155
 
156
+ if (obj instanceof $.Event) {
157
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
158
+ }
159
+
160
+ if (self.isInStateTrue()) return
161
+
131
162
  clearTimeout(self.timeout)
132
163
 
133
164
  self.hoverState = 'out'
@@ -145,7 +176,7 @@
145
176
  if (this.hasContent() && this.enabled) {
146
177
  this.$element.trigger(e)
147
178
 
148
- var inDom = $.contains(document.documentElement, this.$element[0])
179
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
149
180
  if (e.isDefaultPrevented() || !inDom) return
150
181
  var that = this
151
182
 
@@ -174,6 +205,7 @@
174
205
  .data('bs.' + this.type, this)
175
206
 
176
207
  this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
208
+ this.$element.trigger('inserted.bs.' + this.type)
177
209
 
178
210
  var pos = this.getPosition()
179
211
  var actualWidth = $tip[0].offsetWidth
@@ -181,13 +213,12 @@
181
213
 
182
214
  if (autoPlace) {
183
215
  var orgPlacement = placement
184
- var $parent = this.$element.parent()
185
- var parentDim = this.getPosition($parent)
216
+ var viewportDim = this.getPosition(this.$viewport)
186
217
 
187
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
188
- placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
189
- placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
190
- placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
218
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
219
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
220
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
221
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
191
222
  placement
192
223
 
193
224
  $tip
@@ -200,14 +231,17 @@
200
231
  this.applyPlacement(calculatedOffset, placement)
201
232
 
202
233
  var complete = function () {
234
+ var prevHoverState = that.hoverState
203
235
  that.$element.trigger('shown.bs.' + that.type)
204
236
  that.hoverState = null
237
+
238
+ if (prevHoverState == 'out') that.leave(that)
205
239
  }
206
240
 
207
241
  $.support.transition && this.$tip.hasClass('fade') ?
208
242
  $tip
209
243
  .one('bsTransitionEnd', complete)
210
- .emulateTransitionEnd(150) :
244
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
211
245
  complete()
212
246
  }
213
247
  }
@@ -225,8 +259,8 @@
225
259
  if (isNaN(marginTop)) marginTop = 0
226
260
  if (isNaN(marginLeft)) marginLeft = 0
227
261
 
228
- offset.top = offset.top + marginTop
229
- offset.left = offset.left + marginLeft
262
+ offset.top += marginTop
263
+ offset.left += marginLeft
230
264
 
231
265
  // $.fn.offset doesn't round pixel values
232
266
  // so we use setOffset directly with our own function B-0
@@ -254,16 +288,18 @@
254
288
  if (delta.left) offset.left += delta.left
255
289
  else offset.top += delta.top
256
290
 
257
- var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
258
- var arrowPosition = delta.left ? 'left' : 'top'
259
- var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
291
+ var isVertical = /top|bottom/.test(placement)
292
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
293
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
260
294
 
261
295
  $tip.offset(offset)
262
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
296
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
263
297
  }
264
298
 
265
- Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
266
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
299
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
300
+ this.arrow()
301
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
302
+ .css(isVertical ? 'top' : 'left', '')
267
303
  }
268
304
 
269
305
  Tooltip.prototype.setContent = function () {
@@ -274,16 +310,17 @@
274
310
  $tip.removeClass('fade in top bottom left right')
275
311
  }
276
312
 
277
- Tooltip.prototype.hide = function () {
313
+ Tooltip.prototype.hide = function (callback) {
278
314
  var that = this
279
- var $tip = this.tip()
315
+ var $tip = $(this.$tip)
280
316
  var e = $.Event('hide.bs.' + this.type)
281
317
 
282
- this.$element.removeAttr('aria-describedby')
283
-
284
318
  function complete() {
285
319
  if (that.hoverState != 'in') $tip.detach()
286
- that.$element.trigger('hidden.bs.' + that.type)
320
+ that.$element
321
+ .removeAttr('aria-describedby')
322
+ .trigger('hidden.bs.' + that.type)
323
+ callback && callback()
287
324
  }
288
325
 
289
326
  this.$element.trigger(e)
@@ -292,10 +329,10 @@
292
329
 
293
330
  $tip.removeClass('in')
294
331
 
295
- $.support.transition && this.$tip.hasClass('fade') ?
332
+ $.support.transition && $tip.hasClass('fade') ?
296
333
  $tip
297
334
  .one('bsTransitionEnd', complete)
298
- .emulateTransitionEnd(150) :
335
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
299
336
  complete()
300
337
 
301
338
  this.hoverState = null
@@ -305,7 +342,7 @@
305
342
 
306
343
  Tooltip.prototype.fixTitle = function () {
307
344
  var $e = this.$element
308
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
345
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
309
346
  $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
310
347
  }
311
348
  }
@@ -316,20 +353,27 @@
316
353
 
317
354
  Tooltip.prototype.getPosition = function ($element) {
318
355
  $element = $element || this.$element
356
+
319
357
  var el = $element[0]
320
358
  var isBody = el.tagName == 'BODY'
321
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
322
- scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
323
- width: isBody ? $(window).width() : $element.outerWidth(),
324
- height: isBody ? $(window).height() : $element.outerHeight()
325
- }, isBody ? { top: 0, left: 0 } : $element.offset())
359
+
360
+ var elRect = el.getBoundingClientRect()
361
+ if (elRect.width == null) {
362
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
363
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
364
+ }
365
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
366
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
367
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
368
+
369
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
326
370
  }
327
371
 
328
372
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
329
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
330
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
373
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
374
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
331
375
  placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
332
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
376
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
333
377
 
334
378
  }
335
379
 
@@ -353,7 +397,7 @@
353
397
  var rightEdgeOffset = pos.left + viewportPadding + actualWidth
354
398
  if (leftEdgeOffset < viewportDimensions.left) { // left overflow
355
399
  delta.left = viewportDimensions.left - leftEdgeOffset
356
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
400
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
357
401
  delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
358
402
  }
359
403
  }
@@ -379,21 +423,19 @@
379
423
  }
380
424
 
381
425
  Tooltip.prototype.tip = function () {
382
- return (this.$tip = this.$tip || $(this.options.template))
426
+ if (!this.$tip) {
427
+ this.$tip = $(this.options.template)
428
+ if (this.$tip.length != 1) {
429
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
430
+ }
431
+ }
432
+ return this.$tip
383
433
  }
384
434
 
385
435
  Tooltip.prototype.arrow = function () {
386
436
  return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
387
437
  }
388
438
 
389
- Tooltip.prototype.validate = function () {
390
- if (!this.$element[0].parentNode) {
391
- this.hide()
392
- this.$element = null
393
- this.options = null
394
- }
395
- }
396
-
397
439
  Tooltip.prototype.enable = function () {
398
440
  this.enabled = true
399
441
  }
@@ -416,12 +458,27 @@
416
458
  }
417
459
  }
418
460
 
419
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
461
+ if (e) {
462
+ self.inState.click = !self.inState.click
463
+ if (self.isInStateTrue()) self.enter(self)
464
+ else self.leave(self)
465
+ } else {
466
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
467
+ }
420
468
  }
421
469
 
422
470
  Tooltip.prototype.destroy = function () {
471
+ var that = this
423
472
  clearTimeout(this.timeout)
424
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
473
+ this.hide(function () {
474
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
475
+ if (that.$tip) {
476
+ that.$tip.detach()
477
+ }
478
+ that.$tip = null
479
+ that.$arrow = null
480
+ that.$viewport = null
481
+ })
425
482
  }
426
483
 
427
484
 
@@ -434,7 +491,7 @@
434
491
  var data = $this.data('bs.tooltip')
435
492
  var options = typeof option == 'object' && option
436
493
 
437
- if (!data && option == 'destroy') return
494
+ if (!data && /destroy|hide/.test(option)) return
438
495
  if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
439
496
  if (typeof option == 'string') data[option]()
440
497
  })