bootstrap-sass 3.3.4.1 → 3.3.5

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 bootstrap-sass might be problematic. Click here for more details.

Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +4 -3
  4. data/assets/javascripts/bootstrap-sprockets.js +2 -2
  5. data/assets/javascripts/bootstrap.js +143 -97
  6. data/assets/javascripts/bootstrap.min.js +4 -4
  7. data/assets/javascripts/bootstrap/affix.js +3 -3
  8. data/assets/javascripts/bootstrap/alert.js +2 -2
  9. data/assets/javascripts/bootstrap/button.js +13 -9
  10. data/assets/javascripts/bootstrap/carousel.js +2 -2
  11. data/assets/javascripts/bootstrap/collapse.js +2 -2
  12. data/assets/javascripts/bootstrap/dropdown.js +46 -42
  13. data/assets/javascripts/bootstrap/modal.js +5 -7
  14. data/assets/javascripts/bootstrap/popover.js +2 -2
  15. data/assets/javascripts/bootstrap/scrollspy.js +2 -2
  16. data/assets/javascripts/bootstrap/tab.js +5 -3
  17. data/assets/javascripts/bootstrap/tooltip.js +58 -20
  18. data/assets/javascripts/bootstrap/transition.js +1 -1
  19. data/assets/stylesheets/_bootstrap.scss +6 -0
  20. data/assets/stylesheets/bootstrap/_badges.scss +1 -1
  21. data/assets/stylesheets/bootstrap/_button-groups.scss +3 -2
  22. data/assets/stylesheets/bootstrap/_buttons.scss +13 -5
  23. data/assets/stylesheets/bootstrap/_carousel.scss +2 -2
  24. data/assets/stylesheets/bootstrap/_dropdowns.scss +3 -1
  25. data/assets/stylesheets/bootstrap/_forms.scss +46 -13
  26. data/assets/stylesheets/bootstrap/_glyphicons.scss +11 -9
  27. data/assets/stylesheets/bootstrap/_input-groups.scss +1 -0
  28. data/assets/stylesheets/bootstrap/_jumbotron.scss +5 -3
  29. data/assets/stylesheets/bootstrap/_list-group.scss +9 -3
  30. data/assets/stylesheets/bootstrap/_media.scss +5 -0
  31. data/assets/stylesheets/bootstrap/_mixins.scss +1 -0
  32. data/assets/stylesheets/bootstrap/_normalize.scss +8 -11
  33. data/assets/stylesheets/bootstrap/_pagination.scss +3 -2
  34. data/assets/stylesheets/bootstrap/_panels.scss +6 -0
  35. data/assets/stylesheets/bootstrap/_popovers.scss +4 -8
  36. data/assets/stylesheets/bootstrap/_print.scss +0 -6
  37. data/assets/stylesheets/bootstrap/_responsive-utilities.scss +4 -2
  38. data/assets/stylesheets/bootstrap/_scaffolding.scss +1 -2
  39. data/assets/stylesheets/bootstrap/_theme.scss +23 -5
  40. data/assets/stylesheets/bootstrap/_tooltip.scss +4 -5
  41. data/assets/stylesheets/bootstrap/_variables.scss +7 -1
  42. data/assets/stylesheets/bootstrap/mixins/_background-variant.scss +2 -1
  43. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +18 -2
  44. data/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +2 -2
  45. data/assets/stylesheets/bootstrap/mixins/_grid.scss +2 -2
  46. data/assets/stylesheets/bootstrap/mixins/_hide-text.scss +1 -1
  47. data/assets/stylesheets/bootstrap/mixins/_list-group.scss +3 -2
  48. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +2 -1
  49. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +18 -0
  50. data/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +1 -1
  51. data/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +2 -1
  52. data/bower.json +1 -6
  53. data/lib/bootstrap-sass.rb +1 -1
  54. data/lib/bootstrap-sass/version.rb +2 -2
  55. data/package.json +1 -1
  56. data/tasks/converter/less_conversion.rb +9 -2
  57. data/templates/project/_bootstrap-variables.sass +8 -2
  58. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c548004d45f09e256dafbc81d58751358225ff42
4
- data.tar.gz: 8fabdcd1bd2e52d97ea9843cee2305d04b3aee9d
3
+ metadata.gz: e4c43d0ff42090a42536b5f8c41b42307789e7da
4
+ data.tar.gz: 4ff995d7bdc39251fd79a0153867204923cacbd2
5
5
  SHA512:
6
- metadata.gz: 751906d2d101bb9702de434aa46fd8ce677f3a32eb3f8e15d48d682703de10daa89da77b496421ded670391f3c29ded93da092985440c8ac5228c399dfb14e2f
7
- data.tar.gz: 40ac7bb1e47dd7bf9101c75b5eff29f15ed83f5c57384e677b7079c3cbac0b594ed5b2e5cdebfce4fd76156a7dc0745afa9ccd5bb4cd471fa27466ce26bdb763
6
+ metadata.gz: ccbdd71b2c148abf5fea1fca53e0ee516907f469fc751a14718df25bf7605e93f4f25204af850ad3ff620ef31a070b7ef4e6ecab97ffc744eacf9c3f158a664e
7
+ data.tar.gz: ecf8dfa146a672f49410292be15bdd5aba2fa574248779165cb02b540adb5b51c9b5168e1b8f36e3a458b3b1b64403603e11c170361bd891a5ed711f1dea1ca1
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.3.5
4
+
5
+ Fix for standalone Compass extension compatibility. [#914](https://github.com/twbs/bootstrap-sass/issues/914)
6
+
7
+ Framework version: Bootstrap **v3.3.5**
8
+
3
9
  ## 3.3.4
4
10
 
5
11
  No Sass-specific changes.
data/README.md CHANGED
@@ -21,7 +21,7 @@ Please see the appropriate guide for your environment of choice:
21
21
  In your Gemfile you need to add the `bootstrap-sass` gem, and ensure that the `sass-rails` gem is present - it is added to new Rails applications by default.
22
22
 
23
23
  ```ruby
24
- gem 'bootstrap-sass', '~> 3.3.4'
24
+ gem 'bootstrap-sass', '~> 3.3.5'
25
25
  gem 'sass-rails', '>= 3.2'
26
26
  ```
27
27
 
@@ -142,7 +142,7 @@ If this happens, change the import order so that Compass mixins are loaded later
142
142
 
143
143
  ### c. Bower
144
144
 
145
- bootstrap-sass Bower package is compatible with node-sass 1.2.3+. You can install it with:
145
+ bootstrap-sass Bower package is compatible with node-sass 3.2.0+. You can install it with:
146
146
 
147
147
  ```console
148
148
  $ bower install bootstrap-sass
@@ -275,7 +275,7 @@ $navbar-default-color: $light-orange;
275
275
  ## Version
276
276
 
277
277
  Bootstrap for Sass version may differ from the upstream version in the last number, known as
278
- [MINOR](http://semver.org/spec/v2.0.0.html). The minor version may be ahead of the corresponding upstream minor.
278
+ [PATCH](http://semver.org/spec/v2.0.0.html). The patch version may be ahead of the corresponding upstream minor.
279
279
  This happens when we need to release Sass-specific changes.
280
280
 
281
281
  Before v3.3.2, Bootstrap for Sass version used to reflect the upstream version, with an additional number for
@@ -285,6 +285,7 @@ The upstream versions vs the Bootstrap for Sass versions are:
285
285
 
286
286
  | Upstream | Sass |
287
287
  |---------:|--------:|
288
+ | 3.3.5 | 3.3.5 |
288
289
  | 3.3.4 | 3.3.4 |
289
290
  | 3.3.2 | 3.3.3 |
290
291
  | <= 3.3.1 | 3.3.1.x |
@@ -4,9 +4,9 @@
4
4
  //= require ./bootstrap/carousel
5
5
  //= require ./bootstrap/collapse
6
6
  //= require ./bootstrap/dropdown
7
- //= require ./bootstrap/modal
8
- //= require ./bootstrap/scrollspy
9
7
  //= require ./bootstrap/tab
10
8
  //= require ./bootstrap/transition
9
+ //= require ./bootstrap/scrollspy
10
+ //= require ./bootstrap/modal
11
11
  //= require ./bootstrap/tooltip
12
12
  //= require ./bootstrap/popover
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * Bootstrap v3.3.4 (http://getbootstrap.com)
2
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
3
3
  * Copyright 2011-2015 Twitter, Inc.
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
4
+ * Licensed under the MIT license
5
5
  */
6
6
 
7
7
  if (typeof jQuery === 'undefined') {
@@ -17,7 +17,7 @@ if (typeof jQuery === 'undefined') {
17
17
  }(jQuery);
18
18
 
19
19
  /* ========================================================================
20
- * Bootstrap: transition.js v3.3.4
20
+ * Bootstrap: transition.js v3.3.5
21
21
  * http://getbootstrap.com/javascript/#transitions
22
22
  * ========================================================================
23
23
  * Copyright 2011-2015 Twitter, Inc.
@@ -77,7 +77,7 @@ if (typeof jQuery === 'undefined') {
77
77
  }(jQuery);
78
78
 
79
79
  /* ========================================================================
80
- * Bootstrap: alert.js v3.3.4
80
+ * Bootstrap: alert.js v3.3.5
81
81
  * http://getbootstrap.com/javascript/#alerts
82
82
  * ========================================================================
83
83
  * Copyright 2011-2015 Twitter, Inc.
@@ -96,7 +96,7 @@ if (typeof jQuery === 'undefined') {
96
96
  $(el).on('click', dismiss, this.close)
97
97
  }
98
98
 
99
- Alert.VERSION = '3.3.4'
99
+ Alert.VERSION = '3.3.5'
100
100
 
101
101
  Alert.TRANSITION_DURATION = 150
102
102
 
@@ -172,7 +172,7 @@ if (typeof jQuery === 'undefined') {
172
172
  }(jQuery);
173
173
 
174
174
  /* ========================================================================
175
- * Bootstrap: button.js v3.3.4
175
+ * Bootstrap: button.js v3.3.5
176
176
  * http://getbootstrap.com/javascript/#buttons
177
177
  * ========================================================================
178
178
  * Copyright 2011-2015 Twitter, Inc.
@@ -192,7 +192,7 @@ if (typeof jQuery === 'undefined') {
192
192
  this.isLoading = false
193
193
  }
194
194
 
195
- Button.VERSION = '3.3.4'
195
+ Button.VERSION = '3.3.5'
196
196
 
197
197
  Button.DEFAULTS = {
198
198
  loadingText: 'loading...'
@@ -204,7 +204,7 @@ if (typeof jQuery === 'undefined') {
204
204
  var val = $el.is('input') ? 'val' : 'html'
205
205
  var data = $el.data()
206
206
 
207
- state = state + 'Text'
207
+ state += 'Text'
208
208
 
209
209
  if (data.resetText == null) $el.data('resetText', $el[val]())
210
210
 
@@ -229,15 +229,19 @@ if (typeof jQuery === 'undefined') {
229
229
  if ($parent.length) {
230
230
  var $input = this.$element.find('input')
231
231
  if ($input.prop('type') == 'radio') {
232
- if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
233
- else $parent.find('.active').removeClass('active')
232
+ if ($input.prop('checked')) changed = false
233
+ $parent.find('.active').removeClass('active')
234
+ this.$element.addClass('active')
235
+ } else if ($input.prop('type') == 'checkbox') {
236
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
237
+ this.$element.toggleClass('active')
234
238
  }
235
- if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
239
+ $input.prop('checked', this.$element.hasClass('active'))
240
+ if (changed) $input.trigger('change')
236
241
  } else {
237
242
  this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
243
+ this.$element.toggleClass('active')
238
244
  }
239
-
240
- if (changed) this.$element.toggleClass('active')
241
245
  }
242
246
 
243
247
 
@@ -280,7 +284,7 @@ if (typeof jQuery === 'undefined') {
280
284
  var $btn = $(e.target)
281
285
  if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
282
286
  Plugin.call($btn, 'toggle')
283
- e.preventDefault()
287
+ if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
284
288
  })
285
289
  .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
286
290
  $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
@@ -289,7 +293,7 @@ if (typeof jQuery === 'undefined') {
289
293
  }(jQuery);
290
294
 
291
295
  /* ========================================================================
292
- * Bootstrap: carousel.js v3.3.4
296
+ * Bootstrap: carousel.js v3.3.5
293
297
  * http://getbootstrap.com/javascript/#carousel
294
298
  * ========================================================================
295
299
  * Copyright 2011-2015 Twitter, Inc.
@@ -320,7 +324,7 @@ if (typeof jQuery === 'undefined') {
320
324
  .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
321
325
  }
322
326
 
323
- Carousel.VERSION = '3.3.4'
327
+ Carousel.VERSION = '3.3.5'
324
328
 
325
329
  Carousel.TRANSITION_DURATION = 600
326
330
 
@@ -527,7 +531,7 @@ if (typeof jQuery === 'undefined') {
527
531
  }(jQuery);
528
532
 
529
533
  /* ========================================================================
530
- * Bootstrap: collapse.js v3.3.4
534
+ * Bootstrap: collapse.js v3.3.5
531
535
  * http://getbootstrap.com/javascript/#collapse
532
536
  * ========================================================================
533
537
  * Copyright 2011-2015 Twitter, Inc.
@@ -557,7 +561,7 @@ if (typeof jQuery === 'undefined') {
557
561
  if (this.options.toggle) this.toggle()
558
562
  }
559
563
 
560
- Collapse.VERSION = '3.3.4'
564
+ Collapse.VERSION = '3.3.5'
561
565
 
562
566
  Collapse.TRANSITION_DURATION = 350
563
567
 
@@ -739,7 +743,7 @@ if (typeof jQuery === 'undefined') {
739
743
  }(jQuery);
740
744
 
741
745
  /* ========================================================================
742
- * Bootstrap: dropdown.js v3.3.4
746
+ * Bootstrap: dropdown.js v3.3.5
743
747
  * http://getbootstrap.com/javascript/#dropdowns
744
748
  * ========================================================================
745
749
  * Copyright 2011-2015 Twitter, Inc.
@@ -759,7 +763,41 @@ if (typeof jQuery === 'undefined') {
759
763
  $(element).on('click.bs.dropdown', this.toggle)
760
764
  }
761
765
 
762
- Dropdown.VERSION = '3.3.4'
766
+ Dropdown.VERSION = '3.3.5'
767
+
768
+ function getParent($this) {
769
+ var selector = $this.attr('data-target')
770
+
771
+ if (!selector) {
772
+ selector = $this.attr('href')
773
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
774
+ }
775
+
776
+ var $parent = selector && $(selector)
777
+
778
+ return $parent && $parent.length ? $parent : $this.parent()
779
+ }
780
+
781
+ function clearMenus(e) {
782
+ if (e && e.which === 3) return
783
+ $(backdrop).remove()
784
+ $(toggle).each(function () {
785
+ var $this = $(this)
786
+ var $parent = getParent($this)
787
+ var relatedTarget = { relatedTarget: this }
788
+
789
+ if (!$parent.hasClass('open')) return
790
+
791
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
792
+
793
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
794
+
795
+ if (e.isDefaultPrevented()) return
796
+
797
+ $this.attr('aria-expanded', 'false')
798
+ $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
799
+ })
800
+ }
763
801
 
764
802
  Dropdown.prototype.toggle = function (e) {
765
803
  var $this = $(this)
@@ -774,7 +812,10 @@ if (typeof jQuery === 'undefined') {
774
812
  if (!isActive) {
775
813
  if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
776
814
  // if mobile we use a backdrop because click events don't delegate
777
- $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
815
+ $(document.createElement('div'))
816
+ .addClass('dropdown-backdrop')
817
+ .insertAfter($(this))
818
+ .on('click', clearMenus)
778
819
  }
779
820
 
780
821
  var relatedTarget = { relatedTarget: this }
@@ -807,57 +848,25 @@ if (typeof jQuery === 'undefined') {
807
848
  var $parent = getParent($this)
808
849
  var isActive = $parent.hasClass('open')
809
850
 
810
- if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
851
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
811
852
  if (e.which == 27) $parent.find(toggle).trigger('focus')
812
853
  return $this.trigger('click')
813
854
  }
814
855
 
815
856
  var desc = ' li:not(.disabled):visible a'
816
- var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
857
+ var $items = $parent.find('.dropdown-menu' + desc)
817
858
 
818
859
  if (!$items.length) return
819
860
 
820
861
  var index = $items.index(e.target)
821
862
 
822
- if (e.which == 38 && index > 0) index-- // up
823
- if (e.which == 40 && index < $items.length - 1) index++ // down
824
- if (!~index) index = 0
863
+ if (e.which == 38 && index > 0) index-- // up
864
+ if (e.which == 40 && index < $items.length - 1) index++ // down
865
+ if (!~index) index = 0
825
866
 
826
867
  $items.eq(index).trigger('focus')
827
868
  }
828
869
 
829
- function clearMenus(e) {
830
- if (e && e.which === 3) return
831
- $(backdrop).remove()
832
- $(toggle).each(function () {
833
- var $this = $(this)
834
- var $parent = getParent($this)
835
- var relatedTarget = { relatedTarget: this }
836
-
837
- if (!$parent.hasClass('open')) return
838
-
839
- $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
840
-
841
- if (e.isDefaultPrevented()) return
842
-
843
- $this.attr('aria-expanded', 'false')
844
- $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
845
- })
846
- }
847
-
848
- function getParent($this) {
849
- var selector = $this.attr('data-target')
850
-
851
- if (!selector) {
852
- selector = $this.attr('href')
853
- selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
854
- }
855
-
856
- var $parent = selector && $(selector)
857
-
858
- return $parent && $parent.length ? $parent : $this.parent()
859
- }
860
-
861
870
 
862
871
  // DROPDOWN PLUGIN DEFINITION
863
872
  // ==========================
@@ -895,13 +904,12 @@ if (typeof jQuery === 'undefined') {
895
904
  .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
896
905
  .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
897
906
  .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
898
- .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
899
- .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
907
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
900
908
 
901
909
  }(jQuery);
902
910
 
903
911
  /* ========================================================================
904
- * Bootstrap: modal.js v3.3.4
912
+ * Bootstrap: modal.js v3.3.5
905
913
  * http://getbootstrap.com/javascript/#modals
906
914
  * ========================================================================
907
915
  * Copyright 2011-2015 Twitter, Inc.
@@ -935,7 +943,7 @@ if (typeof jQuery === 'undefined') {
935
943
  }
936
944
  }
937
945
 
938
- Modal.VERSION = '3.3.4'
946
+ Modal.VERSION = '3.3.5'
939
947
 
940
948
  Modal.TRANSITION_DURATION = 300
941
949
  Modal.BACKDROP_TRANSITION_DURATION = 150
@@ -992,9 +1000,7 @@ if (typeof jQuery === 'undefined') {
992
1000
  that.$element[0].offsetWidth // force reflow
993
1001
  }
994
1002
 
995
- that.$element
996
- .addClass('in')
997
- .attr('aria-hidden', false)
1003
+ that.$element.addClass('in')
998
1004
 
999
1005
  that.enforceFocus()
1000
1006
 
@@ -1028,7 +1034,6 @@ if (typeof jQuery === 'undefined') {
1028
1034
 
1029
1035
  this.$element
1030
1036
  .removeClass('in')
1031
- .attr('aria-hidden', true)
1032
1037
  .off('click.dismiss.bs.modal')
1033
1038
  .off('mouseup.dismiss.bs.modal')
1034
1039
 
@@ -1092,7 +1097,8 @@ if (typeof jQuery === 'undefined') {
1092
1097
  if (this.isShown && this.options.backdrop) {
1093
1098
  var doAnimate = $.support.transition && animate
1094
1099
 
1095
- this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
1100
+ this.$backdrop = $(document.createElement('div'))
1101
+ .addClass('modal-backdrop ' + animate)
1096
1102
  .appendTo(this.$body)
1097
1103
 
1098
1104
  this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
@@ -1241,7 +1247,7 @@ if (typeof jQuery === 'undefined') {
1241
1247
  }(jQuery);
1242
1248
 
1243
1249
  /* ========================================================================
1244
- * Bootstrap: tooltip.js v3.3.4
1250
+ * Bootstrap: tooltip.js v3.3.5
1245
1251
  * http://getbootstrap.com/javascript/#tooltip
1246
1252
  * Inspired by the original jQuery.tipsy by Jason Frame
1247
1253
  * ========================================================================
@@ -1263,11 +1269,12 @@ if (typeof jQuery === 'undefined') {
1263
1269
  this.timeout = null
1264
1270
  this.hoverState = null
1265
1271
  this.$element = null
1272
+ this.inState = null
1266
1273
 
1267
1274
  this.init('tooltip', element, options)
1268
1275
  }
1269
1276
 
1270
- Tooltip.VERSION = '3.3.4'
1277
+ Tooltip.VERSION = '3.3.5'
1271
1278
 
1272
1279
  Tooltip.TRANSITION_DURATION = 150
1273
1280
 
@@ -1292,7 +1299,8 @@ if (typeof jQuery === 'undefined') {
1292
1299
  this.type = type
1293
1300
  this.$element = $(element)
1294
1301
  this.options = this.getOptions(options)
1295
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1302
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1303
+ this.inState = { click: false, hover: false, focus: false }
1296
1304
 
1297
1305
  if (this.$element[0] instanceof document.constructor && !this.options.selector) {
1298
1306
  throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
@@ -1351,16 +1359,20 @@ if (typeof jQuery === 'undefined') {
1351
1359
  var self = obj instanceof this.constructor ?
1352
1360
  obj : $(obj.currentTarget).data('bs.' + this.type)
1353
1361
 
1354
- if (self && self.$tip && self.$tip.is(':visible')) {
1355
- self.hoverState = 'in'
1356
- return
1357
- }
1358
-
1359
1362
  if (!self) {
1360
1363
  self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1361
1364
  $(obj.currentTarget).data('bs.' + this.type, self)
1362
1365
  }
1363
1366
 
1367
+ if (obj instanceof $.Event) {
1368
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
1369
+ }
1370
+
1371
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
1372
+ self.hoverState = 'in'
1373
+ return
1374
+ }
1375
+
1364
1376
  clearTimeout(self.timeout)
1365
1377
 
1366
1378
  self.hoverState = 'in'
@@ -1372,6 +1384,14 @@ if (typeof jQuery === 'undefined') {
1372
1384
  }, self.options.delay.show)
1373
1385
  }
1374
1386
 
1387
+ Tooltip.prototype.isInStateTrue = function () {
1388
+ for (var key in this.inState) {
1389
+ if (this.inState[key]) return true
1390
+ }
1391
+
1392
+ return false
1393
+ }
1394
+
1375
1395
  Tooltip.prototype.leave = function (obj) {
1376
1396
  var self = obj instanceof this.constructor ?
1377
1397
  obj : $(obj.currentTarget).data('bs.' + this.type)
@@ -1381,6 +1401,12 @@ if (typeof jQuery === 'undefined') {
1381
1401
  $(obj.currentTarget).data('bs.' + this.type, self)
1382
1402
  }
1383
1403
 
1404
+ if (obj instanceof $.Event) {
1405
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
1406
+ }
1407
+
1408
+ if (self.isInStateTrue()) return
1409
+
1384
1410
  clearTimeout(self.timeout)
1385
1411
 
1386
1412
  self.hoverState = 'out'
@@ -1427,6 +1453,7 @@ if (typeof jQuery === 'undefined') {
1427
1453
  .data('bs.' + this.type, this)
1428
1454
 
1429
1455
  this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1456
+ this.$element.trigger('inserted.bs.' + this.type)
1430
1457
 
1431
1458
  var pos = this.getPosition()
1432
1459
  var actualWidth = $tip[0].offsetWidth
@@ -1434,13 +1461,12 @@ if (typeof jQuery === 'undefined') {
1434
1461
 
1435
1462
  if (autoPlace) {
1436
1463
  var orgPlacement = placement
1437
- var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1438
- var containerDim = this.getPosition($container)
1464
+ var viewportDim = this.getPosition(this.$viewport)
1439
1465
 
1440
- placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1441
- placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1442
- placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1443
- placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1466
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
1467
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
1468
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
1469
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
1444
1470
  placement
1445
1471
 
1446
1472
  $tip
@@ -1481,8 +1507,8 @@ if (typeof jQuery === 'undefined') {
1481
1507
  if (isNaN(marginTop)) marginTop = 0
1482
1508
  if (isNaN(marginLeft)) marginLeft = 0
1483
1509
 
1484
- offset.top = offset.top + marginTop
1485
- offset.left = offset.left + marginLeft
1510
+ offset.top += marginTop
1511
+ offset.left += marginLeft
1486
1512
 
1487
1513
  // $.fn.offset doesn't round pixel values
1488
1514
  // so we use setOffset directly with our own function B-0
@@ -1564,7 +1590,7 @@ if (typeof jQuery === 'undefined') {
1564
1590
 
1565
1591
  Tooltip.prototype.fixTitle = function () {
1566
1592
  var $e = this.$element
1567
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1593
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
1568
1594
  $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1569
1595
  }
1570
1596
  }
@@ -1619,7 +1645,7 @@ if (typeof jQuery === 'undefined') {
1619
1645
  var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1620
1646
  if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1621
1647
  delta.left = viewportDimensions.left - leftEdgeOffset
1622
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1648
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
1623
1649
  delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1624
1650
  }
1625
1651
  }
@@ -1645,7 +1671,13 @@ if (typeof jQuery === 'undefined') {
1645
1671
  }
1646
1672
 
1647
1673
  Tooltip.prototype.tip = function () {
1648
- return (this.$tip = this.$tip || $(this.options.template))
1674
+ if (!this.$tip) {
1675
+ this.$tip = $(this.options.template)
1676
+ if (this.$tip.length != 1) {
1677
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
1678
+ }
1679
+ }
1680
+ return this.$tip
1649
1681
  }
1650
1682
 
1651
1683
  Tooltip.prototype.arrow = function () {
@@ -1674,7 +1706,13 @@ if (typeof jQuery === 'undefined') {
1674
1706
  }
1675
1707
  }
1676
1708
 
1677
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1709
+ if (e) {
1710
+ self.inState.click = !self.inState.click
1711
+ if (self.isInStateTrue()) self.enter(self)
1712
+ else self.leave(self)
1713
+ } else {
1714
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1715
+ }
1678
1716
  }
1679
1717
 
1680
1718
  Tooltip.prototype.destroy = function () {
@@ -1682,6 +1720,12 @@ if (typeof jQuery === 'undefined') {
1682
1720
  clearTimeout(this.timeout)
1683
1721
  this.hide(function () {
1684
1722
  that.$element.off('.' + that.type).removeData('bs.' + that.type)
1723
+ if (that.$tip) {
1724
+ that.$tip.detach()
1725
+ }
1726
+ that.$tip = null
1727
+ that.$arrow = null
1728
+ that.$viewport = null
1685
1729
  })
1686
1730
  }
1687
1731
 
@@ -1718,7 +1762,7 @@ if (typeof jQuery === 'undefined') {
1718
1762
  }(jQuery);
1719
1763
 
1720
1764
  /* ========================================================================
1721
- * Bootstrap: popover.js v3.3.4
1765
+ * Bootstrap: popover.js v3.3.5
1722
1766
  * http://getbootstrap.com/javascript/#popovers
1723
1767
  * ========================================================================
1724
1768
  * Copyright 2011-2015 Twitter, Inc.
@@ -1738,7 +1782,7 @@ if (typeof jQuery === 'undefined') {
1738
1782
 
1739
1783
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1740
1784
 
1741
- Popover.VERSION = '3.3.4'
1785
+ Popover.VERSION = '3.3.5'
1742
1786
 
1743
1787
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1744
1788
  placement: 'right',
@@ -1827,7 +1871,7 @@ if (typeof jQuery === 'undefined') {
1827
1871
  }(jQuery);
1828
1872
 
1829
1873
  /* ========================================================================
1830
- * Bootstrap: scrollspy.js v3.3.4
1874
+ * Bootstrap: scrollspy.js v3.3.5
1831
1875
  * http://getbootstrap.com/javascript/#scrollspy
1832
1876
  * ========================================================================
1833
1877
  * Copyright 2011-2015 Twitter, Inc.
@@ -1856,7 +1900,7 @@ if (typeof jQuery === 'undefined') {
1856
1900
  this.process()
1857
1901
  }
1858
1902
 
1859
- ScrollSpy.VERSION = '3.3.4'
1903
+ ScrollSpy.VERSION = '3.3.5'
1860
1904
 
1861
1905
  ScrollSpy.DEFAULTS = {
1862
1906
  offset: 10
@@ -2000,7 +2044,7 @@ if (typeof jQuery === 'undefined') {
2000
2044
  }(jQuery);
2001
2045
 
2002
2046
  /* ========================================================================
2003
- * Bootstrap: tab.js v3.3.4
2047
+ * Bootstrap: tab.js v3.3.5
2004
2048
  * http://getbootstrap.com/javascript/#tabs
2005
2049
  * ========================================================================
2006
2050
  * Copyright 2011-2015 Twitter, Inc.
@@ -2015,10 +2059,12 @@ if (typeof jQuery === 'undefined') {
2015
2059
  // ====================
2016
2060
 
2017
2061
  var Tab = function (element) {
2062
+ // jscs:disable requireDollarBeforejQueryAssignment
2018
2063
  this.element = $(element)
2064
+ // jscs:enable requireDollarBeforejQueryAssignment
2019
2065
  }
2020
2066
 
2021
- Tab.VERSION = '3.3.4'
2067
+ Tab.VERSION = '3.3.5'
2022
2068
 
2023
2069
  Tab.TRANSITION_DURATION = 150
2024
2070
 
@@ -2066,7 +2112,7 @@ if (typeof jQuery === 'undefined') {
2066
2112
  var $active = container.find('> .active')
2067
2113
  var transition = callback
2068
2114
  && $.support.transition
2069
- && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
2115
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
2070
2116
 
2071
2117
  function next() {
2072
2118
  $active
@@ -2154,7 +2200,7 @@ if (typeof jQuery === 'undefined') {
2154
2200
  }(jQuery);
2155
2201
 
2156
2202
  /* ========================================================================
2157
- * Bootstrap: affix.js v3.3.4
2203
+ * Bootstrap: affix.js v3.3.5
2158
2204
  * http://getbootstrap.com/javascript/#affix
2159
2205
  * ========================================================================
2160
2206
  * Copyright 2011-2015 Twitter, Inc.
@@ -2183,7 +2229,7 @@ if (typeof jQuery === 'undefined') {
2183
2229
  this.checkPosition()
2184
2230
  }
2185
2231
 
2186
- Affix.VERSION = '3.3.4'
2232
+ Affix.VERSION = '3.3.5'
2187
2233
 
2188
2234
  Affix.RESET = 'affix affix-top affix-bottom'
2189
2235
 
@@ -2233,7 +2279,7 @@ if (typeof jQuery === 'undefined') {
2233
2279
  var offset = this.options.offset
2234
2280
  var offsetTop = offset.top
2235
2281
  var offsetBottom = offset.bottom
2236
- var scrollHeight = $(document.body).height()
2282
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
2237
2283
 
2238
2284
  if (typeof offset != 'object') offsetBottom = offsetTop = offset
2239
2285
  if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)