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

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -3
  3. data/CONTRIBUTING.md +8 -1
  4. data/README.md +30 -36
  5. data/assets/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  6. data/assets/fonts/bootstrap/glyphicons-halflings-regular.svg +273 -214
  7. data/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  8. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  9. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  10. data/assets/javascripts/bootstrap.js +1081 -1079
  11. data/assets/javascripts/bootstrap.min.js +7 -0
  12. data/assets/javascripts/bootstrap/affix.js +4 -4
  13. data/assets/javascripts/bootstrap/alert.js +3 -3
  14. data/assets/javascripts/bootstrap/button.js +3 -3
  15. data/assets/javascripts/bootstrap/carousel.js +7 -10
  16. data/assets/javascripts/bootstrap/collapse.js +4 -4
  17. data/assets/javascripts/bootstrap/dropdown.js +3 -3
  18. data/assets/javascripts/bootstrap/modal.js +3 -3
  19. data/assets/javascripts/bootstrap/popover.js +7 -13
  20. data/assets/javascripts/bootstrap/scrollspy.js +3 -3
  21. data/assets/javascripts/bootstrap/tab.js +3 -3
  22. data/assets/javascripts/bootstrap/tooltip.js +10 -16
  23. data/assets/javascripts/bootstrap/transition.js +2 -2
  24. data/assets/stylesheets/_bootstrap-compass.scss +2 -0
  25. data/assets/stylesheets/_bootstrap-mincer.scss +2 -0
  26. data/assets/stylesheets/_bootstrap-sprockets.scss +2 -0
  27. data/assets/stylesheets/bootstrap/_alerts.scss +5 -0
  28. data/assets/stylesheets/bootstrap/_badges.scss +4 -0
  29. data/assets/stylesheets/bootstrap/_breadcrumbs.scss +1 -1
  30. data/assets/stylesheets/bootstrap/_button-groups.scss +2 -2
  31. data/assets/stylesheets/bootstrap/_buttons.scss +1 -1
  32. data/assets/stylesheets/bootstrap/_carousel.scss +8 -6
  33. data/assets/stylesheets/bootstrap/_close.scss +1 -0
  34. data/assets/stylesheets/bootstrap/_dropdowns.scss +2 -1
  35. data/assets/stylesheets/bootstrap/_forms.scss +41 -19
  36. data/assets/stylesheets/bootstrap/_glyphicons.scss +265 -198
  37. data/assets/stylesheets/bootstrap/_jumbotron.scss +1 -0
  38. data/assets/stylesheets/bootstrap/_media.scss +14 -0
  39. data/assets/stylesheets/bootstrap/_navbar.scss +1 -0
  40. data/assets/stylesheets/bootstrap/_panels.scss +5 -1
  41. data/assets/stylesheets/bootstrap/_popovers.scss +1 -1
  42. data/assets/stylesheets/bootstrap/_responsive-utilities.scss +4 -1
  43. data/assets/stylesheets/bootstrap/_tables.scss +3 -3
  44. data/assets/stylesheets/bootstrap/_theme.scss +3 -2
  45. data/assets/stylesheets/bootstrap/_tooltip.scss +1 -1
  46. data/assets/stylesheets/bootstrap/_variables.scss +6 -8
  47. data/assets/stylesheets/bootstrap/mixins/_hide-text.scss +1 -1
  48. data/assets/stylesheets/bootstrap/mixins/_opacity.scss +1 -1
  49. data/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +1 -1
  50. data/bootstrap-sass.gemspec +2 -2
  51. data/bower.json +3 -13
  52. data/lib/bootstrap-sass.rb +16 -4
  53. data/lib/bootstrap-sass/engine.rb +1 -1
  54. data/lib/bootstrap-sass/version.rb +2 -2
  55. data/package.json +2 -2
  56. data/tasks/bower.rake +1 -4
  57. data/tasks/converter.rb +1 -1
  58. data/tasks/converter/fonts_conversion.rb +1 -1
  59. data/tasks/converter/js_conversion.rb +6 -4
  60. data/tasks/converter/less_conversion.rb +23 -15
  61. data/templates/project/_bootstrap-variables.sass +6 -9
  62. data/templates/project/styles.sass +3 -0
  63. data/test/dummy_rails/config/environments/test.rb +2 -0
  64. data/test/sprockets_rails_test.rb +1 -1
  65. metadata +23 -21
@@ -1,171 +1,86 @@
1
- /* ========================================================================
2
- * Bootstrap: affix.js v3.3.1
3
- * http://getbootstrap.com/javascript/#affix
4
- * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
1
+ /*!
2
+ * Bootstrap v3.3.2 (http://getbootstrap.com)
3
+ * Copyright 2011-2015 Twitter, Inc.
6
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
- * ======================================================================== */
5
+ */
8
6
 
7
+ if (typeof jQuery === 'undefined') {
8
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
9
+ }
9
10
 
10
11
  +function ($) {
11
12
  'use strict';
12
-
13
- // AFFIX CLASS DEFINITION
14
- // ======================
15
-
16
- var Affix = function (element, options) {
17
- this.options = $.extend({}, Affix.DEFAULTS, options)
18
-
19
- this.$target = $(this.options.target)
20
- .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
21
- .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
22
-
23
- this.$element = $(element)
24
- this.affixed =
25
- this.unpin =
26
- this.pinnedOffset = null
27
-
28
- this.checkPosition()
29
- }
30
-
31
- Affix.VERSION = '3.3.1'
32
-
33
- Affix.RESET = 'affix affix-top affix-bottom'
34
-
35
- Affix.DEFAULTS = {
36
- offset: 0,
37
- target: window
38
- }
39
-
40
- Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
41
- var scrollTop = this.$target.scrollTop()
42
- var position = this.$element.offset()
43
- var targetHeight = this.$target.height()
44
-
45
- if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
46
-
47
- if (this.affixed == 'bottom') {
48
- if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
49
- return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
50
- }
51
-
52
- var initializing = this.affixed == null
53
- var colliderTop = initializing ? scrollTop : position.top
54
- var colliderHeight = initializing ? targetHeight : height
55
-
56
- if (offsetTop != null && colliderTop <= offsetTop) return 'top'
57
- if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
58
-
59
- return false
60
- }
61
-
62
- Affix.prototype.getPinnedOffset = function () {
63
- if (this.pinnedOffset) return this.pinnedOffset
64
- this.$element.removeClass(Affix.RESET).addClass('affix')
65
- var scrollTop = this.$target.scrollTop()
66
- var position = this.$element.offset()
67
- return (this.pinnedOffset = position.top - scrollTop)
68
- }
69
-
70
- Affix.prototype.checkPositionWithEventLoop = function () {
71
- setTimeout($.proxy(this.checkPosition, this), 1)
13
+ var version = $.fn.jquery.split(' ')[0].split('.')
14
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
15
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
72
16
  }
17
+ }(jQuery);
73
18
 
74
- Affix.prototype.checkPosition = function () {
75
- if (!this.$element.is(':visible')) return
76
-
77
- var height = this.$element.height()
78
- var offset = this.options.offset
79
- var offsetTop = offset.top
80
- var offsetBottom = offset.bottom
81
- var scrollHeight = $('body').height()
82
-
83
- if (typeof offset != 'object') offsetBottom = offsetTop = offset
84
- if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
85
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
86
-
87
- var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
88
-
89
- if (this.affixed != affix) {
90
- if (this.unpin != null) this.$element.css('top', '')
19
+ /* ========================================================================
20
+ * Bootstrap: transition.js v3.3.2
21
+ * http://getbootstrap.com/javascript/#transitions
22
+ * ========================================================================
23
+ * Copyright 2011-2015 Twitter, Inc.
24
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
+ * ======================================================================== */
91
26
 
92
- var affixType = 'affix' + (affix ? '-' + affix : '')
93
- var e = $.Event(affixType + '.bs.affix')
94
27
 
95
- this.$element.trigger(e)
28
+ +function ($) {
29
+ 'use strict';
96
30
 
97
- if (e.isDefaultPrevented()) return
31
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
32
+ // ============================================================
98
33
 
99
- this.affixed = affix
100
- this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
34
+ function transitionEnd() {
35
+ var el = document.createElement('bootstrap')
101
36
 
102
- this.$element
103
- .removeClass(Affix.RESET)
104
- .addClass(affixType)
105
- .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
37
+ var transEndEventNames = {
38
+ WebkitTransition : 'webkitTransitionEnd',
39
+ MozTransition : 'transitionend',
40
+ OTransition : 'oTransitionEnd otransitionend',
41
+ transition : 'transitionend'
106
42
  }
107
43
 
108
- if (affix == 'bottom') {
109
- this.$element.offset({
110
- top: scrollHeight - height - offsetBottom
111
- })
44
+ for (var name in transEndEventNames) {
45
+ if (el.style[name] !== undefined) {
46
+ return { end: transEndEventNames[name] }
47
+ }
112
48
  }
113
- }
114
-
115
-
116
- // AFFIX PLUGIN DEFINITION
117
- // =======================
118
-
119
- function Plugin(option) {
120
- return this.each(function () {
121
- var $this = $(this)
122
- var data = $this.data('bs.affix')
123
- var options = typeof option == 'object' && option
124
49
 
125
- if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
126
- if (typeof option == 'string') data[option]()
127
- })
50
+ return false // explicit for ie8 ( ._.)
128
51
  }
129
52
 
130
- var old = $.fn.affix
131
-
132
- $.fn.affix = Plugin
133
- $.fn.affix.Constructor = Affix
134
-
135
-
136
- // AFFIX NO CONFLICT
137
- // =================
138
-
139
- $.fn.affix.noConflict = function () {
140
- $.fn.affix = old
53
+ // http://blog.alexmaccaw.com/css-transitions
54
+ $.fn.emulateTransitionEnd = function (duration) {
55
+ var called = false
56
+ var $el = this
57
+ $(this).one('bsTransitionEnd', function () { called = true })
58
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
59
+ setTimeout(callback, duration)
141
60
  return this
142
61
  }
143
62
 
63
+ $(function () {
64
+ $.support.transition = transitionEnd()
144
65
 
145
- // AFFIX DATA-API
146
- // ==============
147
-
148
- $(window).on('load', function () {
149
- $('[data-spy="affix"]').each(function () {
150
- var $spy = $(this)
151
- var data = $spy.data()
152
-
153
- data.offset = data.offset || {}
154
-
155
- if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
156
- if (data.offsetTop != null) data.offset.top = data.offsetTop
66
+ if (!$.support.transition) return
157
67
 
158
- Plugin.call($spy, data)
159
- })
68
+ $.event.special.bsTransitionEnd = {
69
+ bindType: $.support.transition.end,
70
+ delegateType: $.support.transition.end,
71
+ handle: function (e) {
72
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
73
+ }
74
+ }
160
75
  })
161
76
 
162
77
  }(jQuery);
163
78
 
164
79
  /* ========================================================================
165
- * Bootstrap: alert.js v3.3.1
80
+ * Bootstrap: alert.js v3.3.2
166
81
  * http://getbootstrap.com/javascript/#alerts
167
82
  * ========================================================================
168
- * Copyright 2011-2014 Twitter, Inc.
83
+ * Copyright 2011-2015 Twitter, Inc.
169
84
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
170
85
  * ======================================================================== */
171
86
 
@@ -181,7 +96,7 @@
181
96
  $(el).on('click', dismiss, this.close)
182
97
  }
183
98
 
184
- Alert.VERSION = '3.3.1'
99
+ Alert.VERSION = '3.3.2'
185
100
 
186
101
  Alert.TRANSITION_DURATION = 150
187
102
 
@@ -257,10 +172,10 @@
257
172
  }(jQuery);
258
173
 
259
174
  /* ========================================================================
260
- * Bootstrap: button.js v3.3.1
175
+ * Bootstrap: button.js v3.3.2
261
176
  * http://getbootstrap.com/javascript/#buttons
262
177
  * ========================================================================
263
- * Copyright 2011-2014 Twitter, Inc.
178
+ * Copyright 2011-2015 Twitter, Inc.
264
179
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
265
180
  * ======================================================================== */
266
181
 
@@ -277,7 +192,7 @@
277
192
  this.isLoading = false
278
193
  }
279
194
 
280
- Button.VERSION = '3.3.1'
195
+ Button.VERSION = '3.3.2'
281
196
 
282
197
  Button.DEFAULTS = {
283
198
  loadingText: 'loading...'
@@ -374,10 +289,10 @@
374
289
  }(jQuery);
375
290
 
376
291
  /* ========================================================================
377
- * Bootstrap: carousel.js v3.3.1
292
+ * Bootstrap: carousel.js v3.3.2
378
293
  * http://getbootstrap.com/javascript/#carousel
379
294
  * ========================================================================
380
- * Copyright 2011-2014 Twitter, Inc.
295
+ * Copyright 2011-2015 Twitter, Inc.
381
296
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
382
297
  * ======================================================================== */
383
298
 
@@ -405,7 +320,7 @@
405
320
  .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
406
321
  }
407
322
 
408
- Carousel.VERSION = '3.3.1'
323
+ Carousel.VERSION = '3.3.2'
409
324
 
410
325
  Carousel.TRANSITION_DURATION = 600
411
326
 
@@ -445,8 +360,11 @@
445
360
  }
446
361
 
447
362
  Carousel.prototype.getItemForDirection = function (direction, active) {
448
- var delta = direction == 'prev' ? -1 : 1
449
363
  var activeIndex = this.getItemIndex(active)
364
+ var willWrap = (direction == 'prev' && activeIndex === 0)
365
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
366
+ if (willWrap && !this.options.wrap) return active
367
+ var delta = direction == 'prev' ? -1 : 1
450
368
  var itemIndex = (activeIndex + delta) % this.$items.length
451
369
  return this.$items.eq(itemIndex)
452
370
  }
@@ -491,14 +409,8 @@
491
409
  var $next = next || this.getItemForDirection(type, $active)
492
410
  var isCycling = this.interval
493
411
  var direction = type == 'next' ? 'left' : 'right'
494
- var fallback = type == 'next' ? 'first' : 'last'
495
412
  var that = this
496
413
 
497
- if (!$next.length) {
498
- if (!this.options.wrap) return
499
- $next = this.$element.find('.item')[fallback]()
500
- }
501
-
502
414
  if ($next.hasClass('active')) return (this.sliding = false)
503
415
 
504
416
  var relatedTarget = $next[0]
@@ -615,10 +527,10 @@
615
527
  }(jQuery);
616
528
 
617
529
  /* ========================================================================
618
- * Bootstrap: collapse.js v3.3.1
530
+ * Bootstrap: collapse.js v3.3.2
619
531
  * http://getbootstrap.com/javascript/#collapse
620
532
  * ========================================================================
621
- * Copyright 2011-2014 Twitter, Inc.
533
+ * Copyright 2011-2015 Twitter, Inc.
622
534
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
623
535
  * ======================================================================== */
624
536
 
@@ -644,7 +556,7 @@
644
556
  if (this.options.toggle) this.toggle()
645
557
  }
646
558
 
647
- Collapse.VERSION = '3.3.1'
559
+ Collapse.VERSION = '3.3.2'
648
560
 
649
561
  Collapse.TRANSITION_DURATION = 350
650
562
 
@@ -662,7 +574,7 @@
662
574
  if (this.transitioning || this.$element.hasClass('in')) return
663
575
 
664
576
  var activesData
665
- var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
577
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
666
578
 
667
579
  if (actives && actives.length) {
668
580
  activesData = actives.data('bs.collapse')
@@ -827,10 +739,10 @@
827
739
  }(jQuery);
828
740
 
829
741
  /* ========================================================================
830
- * Bootstrap: dropdown.js v3.3.1
742
+ * Bootstrap: dropdown.js v3.3.2
831
743
  * http://getbootstrap.com/javascript/#dropdowns
832
744
  * ========================================================================
833
- * Copyright 2011-2014 Twitter, Inc.
745
+ * Copyright 2011-2015 Twitter, Inc.
834
746
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
835
747
  * ======================================================================== */
836
748
 
@@ -847,7 +759,7 @@
847
759
  $(element).on('click.bs.dropdown', this.toggle)
848
760
  }
849
761
 
850
- Dropdown.VERSION = '3.3.1'
762
+ Dropdown.VERSION = '3.3.2'
851
763
 
852
764
  Dropdown.prototype.toggle = function (e) {
853
765
  var $this = $(this)
@@ -989,10 +901,10 @@
989
901
  }(jQuery);
990
902
 
991
903
  /* ========================================================================
992
- * Bootstrap: tab.js v3.3.1
993
- * http://getbootstrap.com/javascript/#tabs
904
+ * Bootstrap: modal.js v3.3.2
905
+ * http://getbootstrap.com/javascript/#modals
994
906
  * ========================================================================
995
- * Copyright 2011-2014 Twitter, Inc.
907
+ * Copyright 2011-2015 Twitter, Inc.
996
908
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
997
909
  * ======================================================================== */
998
910
 
@@ -1000,213 +912,325 @@
1000
912
  +function ($) {
1001
913
  'use strict';
1002
914
 
1003
- // TAB CLASS DEFINITION
1004
- // ====================
915
+ // MODAL CLASS DEFINITION
916
+ // ======================
1005
917
 
1006
- var Tab = function (element) {
1007
- this.element = $(element)
918
+ var Modal = function (element, options) {
919
+ this.options = options
920
+ this.$body = $(document.body)
921
+ this.$element = $(element)
922
+ this.$backdrop =
923
+ this.isShown = null
924
+ this.scrollbarWidth = 0
925
+
926
+ if (this.options.remote) {
927
+ this.$element
928
+ .find('.modal-content')
929
+ .load(this.options.remote, $.proxy(function () {
930
+ this.$element.trigger('loaded.bs.modal')
931
+ }, this))
932
+ }
1008
933
  }
1009
934
 
1010
- Tab.VERSION = '3.3.1'
935
+ Modal.VERSION = '3.3.2'
1011
936
 
1012
- Tab.TRANSITION_DURATION = 150
937
+ Modal.TRANSITION_DURATION = 300
938
+ Modal.BACKDROP_TRANSITION_DURATION = 150
1013
939
 
1014
- Tab.prototype.show = function () {
1015
- var $this = this.element
1016
- var $ul = $this.closest('ul:not(.dropdown-menu)')
1017
- var selector = $this.data('target')
940
+ Modal.DEFAULTS = {
941
+ backdrop: true,
942
+ keyboard: true,
943
+ show: true
944
+ }
1018
945
 
1019
- if (!selector) {
1020
- selector = $this.attr('href')
1021
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
1022
- }
946
+ Modal.prototype.toggle = function (_relatedTarget) {
947
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
948
+ }
1023
949
 
1024
- if ($this.parent('li').hasClass('active')) return
950
+ Modal.prototype.show = function (_relatedTarget) {
951
+ var that = this
952
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
1025
953
 
1026
- var $previous = $ul.find('.active:last a')
1027
- var hideEvent = $.Event('hide.bs.tab', {
1028
- relatedTarget: $this[0]
1029
- })
1030
- var showEvent = $.Event('show.bs.tab', {
1031
- relatedTarget: $previous[0]
1032
- })
954
+ this.$element.trigger(e)
1033
955
 
1034
- $previous.trigger(hideEvent)
1035
- $this.trigger(showEvent)
956
+ if (this.isShown || e.isDefaultPrevented()) return
1036
957
 
1037
- if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
958
+ this.isShown = true
1038
959
 
1039
- var $target = $(selector)
960
+ this.checkScrollbar()
961
+ this.setScrollbar()
962
+ this.$body.addClass('modal-open')
1040
963
 
1041
- this.activate($this.closest('li'), $ul)
1042
- this.activate($target, $target.parent(), function () {
1043
- $previous.trigger({
1044
- type: 'hidden.bs.tab',
1045
- relatedTarget: $this[0]
1046
- })
1047
- $this.trigger({
1048
- type: 'shown.bs.tab',
1049
- relatedTarget: $previous[0]
1050
- })
1051
- })
1052
- }
964
+ this.escape()
965
+ this.resize()
1053
966
 
1054
- Tab.prototype.activate = function (element, container, callback) {
1055
- var $active = container.find('> .active')
1056
- var transition = callback
1057
- && $.support.transition
1058
- && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
967
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
1059
968
 
1060
- function next() {
1061
- $active
1062
- .removeClass('active')
1063
- .find('> .dropdown-menu > .active')
1064
- .removeClass('active')
1065
- .end()
1066
- .find('[data-toggle="tab"]')
1067
- .attr('aria-expanded', false)
969
+ this.backdrop(function () {
970
+ var transition = $.support.transition && that.$element.hasClass('fade')
1068
971
 
1069
- element
1070
- .addClass('active')
1071
- .find('[data-toggle="tab"]')
1072
- .attr('aria-expanded', true)
972
+ if (!that.$element.parent().length) {
973
+ that.$element.appendTo(that.$body) // don't move modals dom position
974
+ }
975
+
976
+ that.$element
977
+ .show()
978
+ .scrollTop(0)
979
+
980
+ if (that.options.backdrop) that.adjustBackdrop()
981
+ that.adjustDialog()
1073
982
 
1074
983
  if (transition) {
1075
- element[0].offsetWidth // reflow for transition
1076
- element.addClass('in')
1077
- } else {
1078
- element.removeClass('fade')
984
+ that.$element[0].offsetWidth // force reflow
1079
985
  }
1080
986
 
1081
- if (element.parent('.dropdown-menu')) {
1082
- element
1083
- .closest('li.dropdown')
1084
- .addClass('active')
1085
- .end()
1086
- .find('[data-toggle="tab"]')
1087
- .attr('aria-expanded', true)
1088
- }
987
+ that.$element
988
+ .addClass('in')
989
+ .attr('aria-hidden', false)
1089
990
 
1090
- callback && callback()
1091
- }
991
+ that.enforceFocus()
1092
992
 
1093
- $active.length && transition ?
1094
- $active
1095
- .one('bsTransitionEnd', next)
1096
- .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
1097
- next()
993
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
1098
994
 
1099
- $active.removeClass('in')
995
+ transition ?
996
+ that.$element.find('.modal-dialog') // wait for modal to slide in
997
+ .one('bsTransitionEnd', function () {
998
+ that.$element.trigger('focus').trigger(e)
999
+ })
1000
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1001
+ that.$element.trigger('focus').trigger(e)
1002
+ })
1100
1003
  }
1101
1004
 
1005
+ Modal.prototype.hide = function (e) {
1006
+ if (e) e.preventDefault()
1102
1007
 
1103
- // TAB PLUGIN DEFINITION
1104
- // =====================
1008
+ e = $.Event('hide.bs.modal')
1105
1009
 
1106
- function Plugin(option) {
1107
- return this.each(function () {
1108
- var $this = $(this)
1109
- var data = $this.data('bs.tab')
1010
+ this.$element.trigger(e)
1110
1011
 
1111
- if (!data) $this.data('bs.tab', (data = new Tab(this)))
1112
- if (typeof option == 'string') data[option]()
1113
- })
1114
- }
1012
+ if (!this.isShown || e.isDefaultPrevented()) return
1115
1013
 
1116
- var old = $.fn.tab
1014
+ this.isShown = false
1117
1015
 
1118
- $.fn.tab = Plugin
1119
- $.fn.tab.Constructor = Tab
1016
+ this.escape()
1017
+ this.resize()
1120
1018
 
1019
+ $(document).off('focusin.bs.modal')
1121
1020
 
1122
- // TAB NO CONFLICT
1123
- // ===============
1021
+ this.$element
1022
+ .removeClass('in')
1023
+ .attr('aria-hidden', true)
1024
+ .off('click.dismiss.bs.modal')
1124
1025
 
1125
- $.fn.tab.noConflict = function () {
1126
- $.fn.tab = old
1127
- return this
1026
+ $.support.transition && this.$element.hasClass('fade') ?
1027
+ this.$element
1028
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1029
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1030
+ this.hideModal()
1128
1031
  }
1129
1032
 
1033
+ Modal.prototype.enforceFocus = function () {
1034
+ $(document)
1035
+ .off('focusin.bs.modal') // guard against infinite focus loop
1036
+ .on('focusin.bs.modal', $.proxy(function (e) {
1037
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
1038
+ this.$element.trigger('focus')
1039
+ }
1040
+ }, this))
1041
+ }
1130
1042
 
1131
- // TAB DATA-API
1132
- // ============
1043
+ Modal.prototype.escape = function () {
1044
+ if (this.isShown && this.options.keyboard) {
1045
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1046
+ e.which == 27 && this.hide()
1047
+ }, this))
1048
+ } else if (!this.isShown) {
1049
+ this.$element.off('keydown.dismiss.bs.modal')
1050
+ }
1051
+ }
1133
1052
 
1134
- var clickHandler = function (e) {
1135
- e.preventDefault()
1136
- Plugin.call($(this), 'show')
1053
+ Modal.prototype.resize = function () {
1054
+ if (this.isShown) {
1055
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1056
+ } else {
1057
+ $(window).off('resize.bs.modal')
1058
+ }
1137
1059
  }
1138
1060
 
1139
- $(document)
1140
- .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
1141
- .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
1061
+ Modal.prototype.hideModal = function () {
1062
+ var that = this
1063
+ this.$element.hide()
1064
+ this.backdrop(function () {
1065
+ that.$body.removeClass('modal-open')
1066
+ that.resetAdjustments()
1067
+ that.resetScrollbar()
1068
+ that.$element.trigger('hidden.bs.modal')
1069
+ })
1070
+ }
1142
1071
 
1143
- }(jQuery);
1072
+ Modal.prototype.removeBackdrop = function () {
1073
+ this.$backdrop && this.$backdrop.remove()
1074
+ this.$backdrop = null
1075
+ }
1144
1076
 
1145
- /* ========================================================================
1146
- * Bootstrap: transition.js v3.3.1
1147
- * http://getbootstrap.com/javascript/#transitions
1148
- * ========================================================================
1149
- * Copyright 2011-2014 Twitter, Inc.
1150
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1151
- * ======================================================================== */
1077
+ Modal.prototype.backdrop = function (callback) {
1078
+ var that = this
1079
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
1152
1080
 
1081
+ if (this.isShown && this.options.backdrop) {
1082
+ var doAnimate = $.support.transition && animate
1153
1083
 
1154
- +function ($) {
1155
- 'use strict';
1084
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
1085
+ .prependTo(this.$element)
1086
+ .on('click.dismiss.bs.modal', $.proxy(function (e) {
1087
+ if (e.target !== e.currentTarget) return
1088
+ this.options.backdrop == 'static'
1089
+ ? this.$element[0].focus.call(this.$element[0])
1090
+ : this.hide.call(this)
1091
+ }, this))
1156
1092
 
1157
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
1158
- // ============================================================
1093
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1159
1094
 
1160
- function transitionEnd() {
1161
- var el = document.createElement('bootstrap')
1095
+ this.$backdrop.addClass('in')
1162
1096
 
1163
- var transEndEventNames = {
1164
- WebkitTransition : 'webkitTransitionEnd',
1165
- MozTransition : 'transitionend',
1166
- OTransition : 'oTransitionEnd otransitionend',
1167
- transition : 'transitionend'
1168
- }
1097
+ if (!callback) return
1169
1098
 
1170
- for (var name in transEndEventNames) {
1171
- if (el.style[name] !== undefined) {
1172
- return { end: transEndEventNames[name] }
1099
+ doAnimate ?
1100
+ this.$backdrop
1101
+ .one('bsTransitionEnd', callback)
1102
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1103
+ callback()
1104
+
1105
+ } else if (!this.isShown && this.$backdrop) {
1106
+ this.$backdrop.removeClass('in')
1107
+
1108
+ var callbackRemove = function () {
1109
+ that.removeBackdrop()
1110
+ callback && callback()
1173
1111
  }
1112
+ $.support.transition && this.$element.hasClass('fade') ?
1113
+ this.$backdrop
1114
+ .one('bsTransitionEnd', callbackRemove)
1115
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1116
+ callbackRemove()
1117
+
1118
+ } else if (callback) {
1119
+ callback()
1174
1120
  }
1121
+ }
1175
1122
 
1176
- return false // explicit for ie8 ( ._.)
1123
+ // these following methods are used to handle overflowing modals
1124
+
1125
+ Modal.prototype.handleUpdate = function () {
1126
+ if (this.options.backdrop) this.adjustBackdrop()
1127
+ this.adjustDialog()
1177
1128
  }
1178
1129
 
1179
- // http://blog.alexmaccaw.com/css-transitions
1180
- $.fn.emulateTransitionEnd = function (duration) {
1181
- var called = false
1182
- var $el = this
1183
- $(this).one('bsTransitionEnd', function () { called = true })
1184
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
1185
- setTimeout(callback, duration)
1130
+ Modal.prototype.adjustBackdrop = function () {
1131
+ this.$backdrop
1132
+ .css('height', 0)
1133
+ .css('height', this.$element[0].scrollHeight)
1134
+ }
1135
+
1136
+ Modal.prototype.adjustDialog = function () {
1137
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1138
+
1139
+ this.$element.css({
1140
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1141
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1142
+ })
1143
+ }
1144
+
1145
+ Modal.prototype.resetAdjustments = function () {
1146
+ this.$element.css({
1147
+ paddingLeft: '',
1148
+ paddingRight: ''
1149
+ })
1150
+ }
1151
+
1152
+ Modal.prototype.checkScrollbar = function () {
1153
+ this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
1154
+ this.scrollbarWidth = this.measureScrollbar()
1155
+ }
1156
+
1157
+ Modal.prototype.setScrollbar = function () {
1158
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1159
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1160
+ }
1161
+
1162
+ Modal.prototype.resetScrollbar = function () {
1163
+ this.$body.css('padding-right', '')
1164
+ }
1165
+
1166
+ Modal.prototype.measureScrollbar = function () { // thx walsh
1167
+ var scrollDiv = document.createElement('div')
1168
+ scrollDiv.className = 'modal-scrollbar-measure'
1169
+ this.$body.append(scrollDiv)
1170
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1171
+ this.$body[0].removeChild(scrollDiv)
1172
+ return scrollbarWidth
1173
+ }
1174
+
1175
+
1176
+ // MODAL PLUGIN DEFINITION
1177
+ // =======================
1178
+
1179
+ function Plugin(option, _relatedTarget) {
1180
+ return this.each(function () {
1181
+ var $this = $(this)
1182
+ var data = $this.data('bs.modal')
1183
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1184
+
1185
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1186
+ if (typeof option == 'string') data[option](_relatedTarget)
1187
+ else if (options.show) data.show(_relatedTarget)
1188
+ })
1189
+ }
1190
+
1191
+ var old = $.fn.modal
1192
+
1193
+ $.fn.modal = Plugin
1194
+ $.fn.modal.Constructor = Modal
1195
+
1196
+
1197
+ // MODAL NO CONFLICT
1198
+ // =================
1199
+
1200
+ $.fn.modal.noConflict = function () {
1201
+ $.fn.modal = old
1186
1202
  return this
1187
1203
  }
1188
1204
 
1189
- $(function () {
1190
- $.support.transition = transitionEnd()
1191
1205
 
1192
- if (!$.support.transition) return
1206
+ // MODAL DATA-API
1207
+ // ==============
1193
1208
 
1194
- $.event.special.bsTransitionEnd = {
1195
- bindType: $.support.transition.end,
1196
- delegateType: $.support.transition.end,
1197
- handle: function (e) {
1198
- if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
1199
- }
1200
- }
1209
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1210
+ var $this = $(this)
1211
+ var href = $this.attr('href')
1212
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1213
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1214
+
1215
+ if ($this.is('a')) e.preventDefault()
1216
+
1217
+ $target.one('show.bs.modal', function (showEvent) {
1218
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1219
+ $target.one('hidden.bs.modal', function () {
1220
+ $this.is(':visible') && $this.trigger('focus')
1221
+ })
1222
+ })
1223
+ Plugin.call($target, option, this)
1201
1224
  })
1202
1225
 
1203
1226
  }(jQuery);
1204
1227
 
1205
1228
  /* ========================================================================
1206
- * Bootstrap: scrollspy.js v3.3.1
1207
- * http://getbootstrap.com/javascript/#scrollspy
1229
+ * Bootstrap: tooltip.js v3.3.2
1230
+ * http://getbootstrap.com/javascript/#tooltip
1231
+ * Inspired by the original jQuery.tipsy by Jason Frame
1208
1232
  * ========================================================================
1209
- * Copyright 2011-2014 Twitter, Inc.
1233
+ * Copyright 2011-2015 Twitter, Inc.
1210
1234
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1211
1235
  * ======================================================================== */
1212
1236
 
@@ -1214,501 +1238,471 @@
1214
1238
  +function ($) {
1215
1239
  'use strict';
1216
1240
 
1217
- // SCROLLSPY CLASS DEFINITION
1218
- // ==========================
1219
-
1220
- function ScrollSpy(element, options) {
1221
- var process = $.proxy(this.process, this)
1241
+ // TOOLTIP PUBLIC CLASS DEFINITION
1242
+ // ===============================
1222
1243
 
1223
- this.$body = $('body')
1224
- this.$scrollElement = $(element).is('body') ? $(window) : $(element)
1225
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1226
- this.selector = (this.options.target || '') + ' .nav li > a'
1227
- this.offsets = []
1228
- this.targets = []
1229
- this.activeTarget = null
1230
- this.scrollHeight = 0
1244
+ var Tooltip = function (element, options) {
1245
+ this.type =
1246
+ this.options =
1247
+ this.enabled =
1248
+ this.timeout =
1249
+ this.hoverState =
1250
+ this.$element = null
1231
1251
 
1232
- this.$scrollElement.on('scroll.bs.scrollspy', process)
1233
- this.refresh()
1234
- this.process()
1252
+ this.init('tooltip', element, options)
1235
1253
  }
1236
1254
 
1237
- ScrollSpy.VERSION = '3.3.1'
1255
+ Tooltip.VERSION = '3.3.2'
1238
1256
 
1239
- ScrollSpy.DEFAULTS = {
1240
- offset: 10
1241
- }
1257
+ Tooltip.TRANSITION_DURATION = 150
1242
1258
 
1243
- ScrollSpy.prototype.getScrollHeight = function () {
1244
- return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1259
+ Tooltip.DEFAULTS = {
1260
+ animation: true,
1261
+ placement: 'top',
1262
+ selector: false,
1263
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1264
+ trigger: 'hover focus',
1265
+ title: '',
1266
+ delay: 0,
1267
+ html: false,
1268
+ container: false,
1269
+ viewport: {
1270
+ selector: 'body',
1271
+ padding: 0
1272
+ }
1245
1273
  }
1246
1274
 
1247
- ScrollSpy.prototype.refresh = function () {
1248
- var offsetMethod = 'offset'
1249
- var offsetBase = 0
1275
+ Tooltip.prototype.init = function (type, element, options) {
1276
+ this.enabled = true
1277
+ this.type = type
1278
+ this.$element = $(element)
1279
+ this.options = this.getOptions(options)
1280
+ this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1250
1281
 
1251
- if (!$.isWindow(this.$scrollElement[0])) {
1252
- offsetMethod = 'position'
1253
- offsetBase = this.$scrollElement.scrollTop()
1254
- }
1282
+ var triggers = this.options.trigger.split(' ')
1255
1283
 
1256
- this.offsets = []
1257
- this.targets = []
1258
- this.scrollHeight = this.getScrollHeight()
1284
+ for (var i = triggers.length; i--;) {
1285
+ var trigger = triggers[i]
1259
1286
 
1260
- var self = this
1287
+ if (trigger == 'click') {
1288
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1289
+ } else if (trigger != 'manual') {
1290
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1291
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1261
1292
 
1262
- this.$body
1263
- .find(this.selector)
1264
- .map(function () {
1265
- var $el = $(this)
1266
- var href = $el.data('target') || $el.attr('href')
1267
- var $href = /^#./.test(href) && $(href)
1293
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1294
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1295
+ }
1296
+ }
1268
1297
 
1269
- return ($href
1270
- && $href.length
1271
- && $href.is(':visible')
1272
- && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1273
- })
1274
- .sort(function (a, b) { return a[0] - b[0] })
1275
- .each(function () {
1276
- self.offsets.push(this[0])
1277
- self.targets.push(this[1])
1278
- })
1298
+ this.options.selector ?
1299
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1300
+ this.fixTitle()
1279
1301
  }
1280
1302
 
1281
- ScrollSpy.prototype.process = function () {
1282
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1283
- var scrollHeight = this.getScrollHeight()
1284
- var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1285
- var offsets = this.offsets
1286
- var targets = this.targets
1287
- var activeTarget = this.activeTarget
1288
- var i
1289
-
1290
- if (this.scrollHeight != scrollHeight) {
1291
- this.refresh()
1292
- }
1303
+ Tooltip.prototype.getDefaults = function () {
1304
+ return Tooltip.DEFAULTS
1305
+ }
1293
1306
 
1294
- if (scrollTop >= maxScroll) {
1295
- return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1296
- }
1307
+ Tooltip.prototype.getOptions = function (options) {
1308
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1297
1309
 
1298
- if (activeTarget && scrollTop < offsets[0]) {
1299
- this.activeTarget = null
1300
- return this.clear()
1310
+ if (options.delay && typeof options.delay == 'number') {
1311
+ options.delay = {
1312
+ show: options.delay,
1313
+ hide: options.delay
1314
+ }
1301
1315
  }
1302
1316
 
1303
- for (i = offsets.length; i--;) {
1304
- activeTarget != targets[i]
1305
- && scrollTop >= offsets[i]
1306
- && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1307
- && this.activate(targets[i])
1308
- }
1317
+ return options
1309
1318
  }
1310
1319
 
1311
- ScrollSpy.prototype.activate = function (target) {
1312
- this.activeTarget = target
1320
+ Tooltip.prototype.getDelegateOptions = function () {
1321
+ var options = {}
1322
+ var defaults = this.getDefaults()
1313
1323
 
1314
- this.clear()
1324
+ this._options && $.each(this._options, function (key, value) {
1325
+ if (defaults[key] != value) options[key] = value
1326
+ })
1315
1327
 
1316
- var selector = this.selector +
1317
- '[data-target="' + target + '"],' +
1318
- this.selector + '[href="' + target + '"]'
1328
+ return options
1329
+ }
1319
1330
 
1320
- var active = $(selector)
1321
- .parents('li')
1322
- .addClass('active')
1331
+ Tooltip.prototype.enter = function (obj) {
1332
+ var self = obj instanceof this.constructor ?
1333
+ obj : $(obj.currentTarget).data('bs.' + this.type)
1323
1334
 
1324
- if (active.parent('.dropdown-menu').length) {
1325
- active = active
1326
- .closest('li.dropdown')
1327
- .addClass('active')
1335
+ if (self && self.$tip && self.$tip.is(':visible')) {
1336
+ self.hoverState = 'in'
1337
+ return
1328
1338
  }
1329
1339
 
1330
- active.trigger('activate.bs.scrollspy')
1331
- }
1332
-
1333
- ScrollSpy.prototype.clear = function () {
1334
- $(this.selector)
1335
- .parentsUntil(this.options.target, '.active')
1336
- .removeClass('active')
1337
- }
1340
+ if (!self) {
1341
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1342
+ $(obj.currentTarget).data('bs.' + this.type, self)
1343
+ }
1338
1344
 
1345
+ clearTimeout(self.timeout)
1339
1346
 
1340
- // SCROLLSPY PLUGIN DEFINITION
1341
- // ===========================
1347
+ self.hoverState = 'in'
1342
1348
 
1343
- function Plugin(option) {
1344
- return this.each(function () {
1345
- var $this = $(this)
1346
- var data = $this.data('bs.scrollspy')
1347
- var options = typeof option == 'object' && option
1349
+ if (!self.options.delay || !self.options.delay.show) return self.show()
1348
1350
 
1349
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1350
- if (typeof option == 'string') data[option]()
1351
- })
1351
+ self.timeout = setTimeout(function () {
1352
+ if (self.hoverState == 'in') self.show()
1353
+ }, self.options.delay.show)
1352
1354
  }
1353
1355
 
1354
- var old = $.fn.scrollspy
1356
+ Tooltip.prototype.leave = function (obj) {
1357
+ var self = obj instanceof this.constructor ?
1358
+ obj : $(obj.currentTarget).data('bs.' + this.type)
1359
+
1360
+ if (!self) {
1361
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1362
+ $(obj.currentTarget).data('bs.' + this.type, self)
1363
+ }
1355
1364
 
1356
- $.fn.scrollspy = Plugin
1357
- $.fn.scrollspy.Constructor = ScrollSpy
1365
+ clearTimeout(self.timeout)
1358
1366
 
1367
+ self.hoverState = 'out'
1359
1368
 
1360
- // SCROLLSPY NO CONFLICT
1361
- // =====================
1369
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
1362
1370
 
1363
- $.fn.scrollspy.noConflict = function () {
1364
- $.fn.scrollspy = old
1365
- return this
1371
+ self.timeout = setTimeout(function () {
1372
+ if (self.hoverState == 'out') self.hide()
1373
+ }, self.options.delay.hide)
1366
1374
  }
1367
1375
 
1376
+ Tooltip.prototype.show = function () {
1377
+ var e = $.Event('show.bs.' + this.type)
1368
1378
 
1369
- // SCROLLSPY DATA-API
1370
- // ==================
1379
+ if (this.hasContent() && this.enabled) {
1380
+ this.$element.trigger(e)
1371
1381
 
1372
- $(window).on('load.bs.scrollspy.data-api', function () {
1373
- $('[data-spy="scroll"]').each(function () {
1374
- var $spy = $(this)
1375
- Plugin.call($spy, $spy.data())
1376
- })
1377
- })
1382
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1383
+ if (e.isDefaultPrevented() || !inDom) return
1384
+ var that = this
1378
1385
 
1379
- }(jQuery);
1386
+ var $tip = this.tip()
1380
1387
 
1381
- /* ========================================================================
1382
- * Bootstrap: modal.js v3.3.1
1383
- * http://getbootstrap.com/javascript/#modals
1384
- * ========================================================================
1385
- * Copyright 2011-2014 Twitter, Inc.
1386
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1387
- * ======================================================================== */
1388
+ var tipId = this.getUID(this.type)
1388
1389
 
1390
+ this.setContent()
1391
+ $tip.attr('id', tipId)
1392
+ this.$element.attr('aria-describedby', tipId)
1389
1393
 
1390
- +function ($) {
1391
- 'use strict';
1394
+ if (this.options.animation) $tip.addClass('fade')
1392
1395
 
1393
- // MODAL CLASS DEFINITION
1394
- // ======================
1396
+ var placement = typeof this.options.placement == 'function' ?
1397
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
1398
+ this.options.placement
1395
1399
 
1396
- var Modal = function (element, options) {
1397
- this.options = options
1398
- this.$body = $(document.body)
1399
- this.$element = $(element)
1400
- this.$backdrop =
1401
- this.isShown = null
1402
- this.scrollbarWidth = 0
1400
+ var autoToken = /\s?auto?\s?/i
1401
+ var autoPlace = autoToken.test(placement)
1402
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1403
1403
 
1404
- if (this.options.remote) {
1405
- this.$element
1406
- .find('.modal-content')
1407
- .load(this.options.remote, $.proxy(function () {
1408
- this.$element.trigger('loaded.bs.modal')
1409
- }, this))
1410
- }
1411
- }
1404
+ $tip
1405
+ .detach()
1406
+ .css({ top: 0, left: 0, display: 'block' })
1407
+ .addClass(placement)
1408
+ .data('bs.' + this.type, this)
1412
1409
 
1413
- Modal.VERSION = '3.3.1'
1410
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1414
1411
 
1415
- Modal.TRANSITION_DURATION = 300
1416
- Modal.BACKDROP_TRANSITION_DURATION = 150
1412
+ var pos = this.getPosition()
1413
+ var actualWidth = $tip[0].offsetWidth
1414
+ var actualHeight = $tip[0].offsetHeight
1417
1415
 
1418
- Modal.DEFAULTS = {
1419
- backdrop: true,
1420
- keyboard: true,
1421
- show: true
1422
- }
1416
+ if (autoPlace) {
1417
+ var orgPlacement = placement
1418
+ var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1419
+ var containerDim = this.getPosition($container)
1423
1420
 
1424
- Modal.prototype.toggle = function (_relatedTarget) {
1425
- return this.isShown ? this.hide() : this.show(_relatedTarget)
1426
- }
1421
+ placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1422
+ placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1423
+ placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1424
+ placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1425
+ placement
1427
1426
 
1428
- Modal.prototype.show = function (_relatedTarget) {
1429
- var that = this
1430
- var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
1427
+ $tip
1428
+ .removeClass(orgPlacement)
1429
+ .addClass(placement)
1430
+ }
1431
1431
 
1432
- this.$element.trigger(e)
1432
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1433
1433
 
1434
- if (this.isShown || e.isDefaultPrevented()) return
1434
+ this.applyPlacement(calculatedOffset, placement)
1435
1435
 
1436
- this.isShown = true
1436
+ var complete = function () {
1437
+ var prevHoverState = that.hoverState
1438
+ that.$element.trigger('shown.bs.' + that.type)
1439
+ that.hoverState = null
1437
1440
 
1438
- this.checkScrollbar()
1439
- this.setScrollbar()
1440
- this.$body.addClass('modal-open')
1441
+ if (prevHoverState == 'out') that.leave(that)
1442
+ }
1441
1443
 
1442
- this.escape()
1443
- this.resize()
1444
+ $.support.transition && this.$tip.hasClass('fade') ?
1445
+ $tip
1446
+ .one('bsTransitionEnd', complete)
1447
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1448
+ complete()
1449
+ }
1450
+ }
1444
1451
 
1445
- this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
1452
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
1453
+ var $tip = this.tip()
1454
+ var width = $tip[0].offsetWidth
1455
+ var height = $tip[0].offsetHeight
1446
1456
 
1447
- this.backdrop(function () {
1448
- var transition = $.support.transition && that.$element.hasClass('fade')
1457
+ // manually read margins because getBoundingClientRect includes difference
1458
+ var marginTop = parseInt($tip.css('margin-top'), 10)
1459
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
1449
1460
 
1450
- if (!that.$element.parent().length) {
1451
- that.$element.appendTo(that.$body) // don't move modals dom position
1461
+ // we must check for NaN for ie 8/9
1462
+ if (isNaN(marginTop)) marginTop = 0
1463
+ if (isNaN(marginLeft)) marginLeft = 0
1464
+
1465
+ offset.top = offset.top + marginTop
1466
+ offset.left = offset.left + marginLeft
1467
+
1468
+ // $.fn.offset doesn't round pixel values
1469
+ // so we use setOffset directly with our own function B-0
1470
+ $.offset.setOffset($tip[0], $.extend({
1471
+ using: function (props) {
1472
+ $tip.css({
1473
+ top: Math.round(props.top),
1474
+ left: Math.round(props.left)
1475
+ })
1452
1476
  }
1477
+ }, offset), 0)
1453
1478
 
1454
- that.$element
1455
- .show()
1456
- .scrollTop(0)
1479
+ $tip.addClass('in')
1457
1480
 
1458
- if (that.options.backdrop) that.adjustBackdrop()
1459
- that.adjustDialog()
1481
+ // check to see if placing tip in new offset caused the tip to resize itself
1482
+ var actualWidth = $tip[0].offsetWidth
1483
+ var actualHeight = $tip[0].offsetHeight
1460
1484
 
1461
- if (transition) {
1462
- that.$element[0].offsetWidth // force reflow
1463
- }
1485
+ if (placement == 'top' && actualHeight != height) {
1486
+ offset.top = offset.top + height - actualHeight
1487
+ }
1464
1488
 
1465
- that.$element
1466
- .addClass('in')
1467
- .attr('aria-hidden', false)
1489
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1468
1490
 
1469
- that.enforceFocus()
1491
+ if (delta.left) offset.left += delta.left
1492
+ else offset.top += delta.top
1470
1493
 
1471
- var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
1494
+ var isVertical = /top|bottom/.test(placement)
1495
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1496
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1472
1497
 
1473
- transition ?
1474
- that.$element.find('.modal-dialog') // wait for modal to slide in
1475
- .one('bsTransitionEnd', function () {
1476
- that.$element.trigger('focus').trigger(e)
1477
- })
1478
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1479
- that.$element.trigger('focus').trigger(e)
1480
- })
1498
+ $tip.offset(offset)
1499
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1481
1500
  }
1482
1501
 
1483
- Modal.prototype.hide = function (e) {
1484
- if (e) e.preventDefault()
1485
-
1486
- e = $.Event('hide.bs.modal')
1502
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
1503
+ this.arrow()
1504
+ .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1505
+ .css(isHorizontal ? 'top' : 'left', '')
1506
+ }
1487
1507
 
1488
- this.$element.trigger(e)
1508
+ Tooltip.prototype.setContent = function () {
1509
+ var $tip = this.tip()
1510
+ var title = this.getTitle()
1489
1511
 
1490
- if (!this.isShown || e.isDefaultPrevented()) return
1512
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1513
+ $tip.removeClass('fade in top bottom left right')
1514
+ }
1491
1515
 
1492
- this.isShown = false
1516
+ Tooltip.prototype.hide = function (callback) {
1517
+ var that = this
1518
+ var $tip = this.tip()
1519
+ var e = $.Event('hide.bs.' + this.type)
1493
1520
 
1494
- this.escape()
1495
- this.resize()
1521
+ function complete() {
1522
+ if (that.hoverState != 'in') $tip.detach()
1523
+ that.$element
1524
+ .removeAttr('aria-describedby')
1525
+ .trigger('hidden.bs.' + that.type)
1526
+ callback && callback()
1527
+ }
1496
1528
 
1497
- $(document).off('focusin.bs.modal')
1529
+ this.$element.trigger(e)
1498
1530
 
1499
- this.$element
1500
- .removeClass('in')
1501
- .attr('aria-hidden', true)
1502
- .off('click.dismiss.bs.modal')
1531
+ if (e.isDefaultPrevented()) return
1503
1532
 
1504
- $.support.transition && this.$element.hasClass('fade') ?
1505
- this.$element
1506
- .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1507
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1508
- this.hideModal()
1509
- }
1533
+ $tip.removeClass('in')
1510
1534
 
1511
- Modal.prototype.enforceFocus = function () {
1512
- $(document)
1513
- .off('focusin.bs.modal') // guard against infinite focus loop
1514
- .on('focusin.bs.modal', $.proxy(function (e) {
1515
- if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
1516
- this.$element.trigger('focus')
1517
- }
1518
- }, this))
1519
- }
1535
+ $.support.transition && this.$tip.hasClass('fade') ?
1536
+ $tip
1537
+ .one('bsTransitionEnd', complete)
1538
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1539
+ complete()
1520
1540
 
1521
- Modal.prototype.escape = function () {
1522
- if (this.isShown && this.options.keyboard) {
1523
- this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1524
- e.which == 27 && this.hide()
1525
- }, this))
1526
- } else if (!this.isShown) {
1527
- this.$element.off('keydown.dismiss.bs.modal')
1528
- }
1529
- }
1541
+ this.hoverState = null
1530
1542
 
1531
- Modal.prototype.resize = function () {
1532
- if (this.isShown) {
1533
- $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1534
- } else {
1535
- $(window).off('resize.bs.modal')
1536
- }
1543
+ return this
1537
1544
  }
1538
1545
 
1539
- Modal.prototype.hideModal = function () {
1540
- var that = this
1541
- this.$element.hide()
1542
- this.backdrop(function () {
1543
- that.$body.removeClass('modal-open')
1544
- that.resetAdjustments()
1545
- that.resetScrollbar()
1546
- that.$element.trigger('hidden.bs.modal')
1547
- })
1546
+ Tooltip.prototype.fixTitle = function () {
1547
+ var $e = this.$element
1548
+ if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1549
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1550
+ }
1548
1551
  }
1549
1552
 
1550
- Modal.prototype.removeBackdrop = function () {
1551
- this.$backdrop && this.$backdrop.remove()
1552
- this.$backdrop = null
1553
+ Tooltip.prototype.hasContent = function () {
1554
+ return this.getTitle()
1553
1555
  }
1554
1556
 
1555
- Modal.prototype.backdrop = function (callback) {
1556
- var that = this
1557
- var animate = this.$element.hasClass('fade') ? 'fade' : ''
1557
+ Tooltip.prototype.getPosition = function ($element) {
1558
+ $element = $element || this.$element
1558
1559
 
1559
- if (this.isShown && this.options.backdrop) {
1560
- var doAnimate = $.support.transition && animate
1560
+ var el = $element[0]
1561
+ var isBody = el.tagName == 'BODY'
1561
1562
 
1562
- this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
1563
- .prependTo(this.$element)
1564
- .on('click.dismiss.bs.modal', $.proxy(function (e) {
1565
- if (e.target !== e.currentTarget) return
1566
- this.options.backdrop == 'static'
1567
- ? this.$element[0].focus.call(this.$element[0])
1568
- : this.hide.call(this)
1569
- }, this))
1563
+ var elRect = el.getBoundingClientRect()
1564
+ if (elRect.width == null) {
1565
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1566
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1567
+ }
1568
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1569
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1570
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1570
1571
 
1571
- if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1572
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
1573
+ }
1572
1574
 
1573
- this.$backdrop.addClass('in')
1575
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1576
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1577
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1578
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1579
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1574
1580
 
1575
- if (!callback) return
1581
+ }
1576
1582
 
1577
- doAnimate ?
1578
- this.$backdrop
1579
- .one('bsTransitionEnd', callback)
1580
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1581
- callback()
1583
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1584
+ var delta = { top: 0, left: 0 }
1585
+ if (!this.$viewport) return delta
1582
1586
 
1583
- } else if (!this.isShown && this.$backdrop) {
1584
- this.$backdrop.removeClass('in')
1587
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1588
+ var viewportDimensions = this.getPosition(this.$viewport)
1585
1589
 
1586
- var callbackRemove = function () {
1587
- that.removeBackdrop()
1588
- callback && callback()
1590
+ if (/right|left/.test(placement)) {
1591
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1592
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1593
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
1594
+ delta.top = viewportDimensions.top - topEdgeOffset
1595
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1596
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1597
+ }
1598
+ } else {
1599
+ var leftEdgeOffset = pos.left - viewportPadding
1600
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1601
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1602
+ delta.left = viewportDimensions.left - leftEdgeOffset
1603
+ } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1604
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1589
1605
  }
1590
- $.support.transition && this.$element.hasClass('fade') ?
1591
- this.$backdrop
1592
- .one('bsTransitionEnd', callbackRemove)
1593
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1594
- callbackRemove()
1595
-
1596
- } else if (callback) {
1597
- callback()
1598
1606
  }
1607
+
1608
+ return delta
1599
1609
  }
1600
1610
 
1601
- // these following methods are used to handle overflowing modals
1611
+ Tooltip.prototype.getTitle = function () {
1612
+ var title
1613
+ var $e = this.$element
1614
+ var o = this.options
1602
1615
 
1603
- Modal.prototype.handleUpdate = function () {
1604
- if (this.options.backdrop) this.adjustBackdrop()
1605
- this.adjustDialog()
1616
+ title = $e.attr('data-original-title')
1617
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1618
+
1619
+ return title
1606
1620
  }
1607
1621
 
1608
- Modal.prototype.adjustBackdrop = function () {
1609
- this.$backdrop
1610
- .css('height', 0)
1611
- .css('height', this.$element[0].scrollHeight)
1622
+ Tooltip.prototype.getUID = function (prefix) {
1623
+ do prefix += ~~(Math.random() * 1000000)
1624
+ while (document.getElementById(prefix))
1625
+ return prefix
1612
1626
  }
1613
1627
 
1614
- Modal.prototype.adjustDialog = function () {
1615
- var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1628
+ Tooltip.prototype.tip = function () {
1629
+ return (this.$tip = this.$tip || $(this.options.template))
1630
+ }
1616
1631
 
1617
- this.$element.css({
1618
- paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1619
- paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1620
- })
1632
+ Tooltip.prototype.arrow = function () {
1633
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1621
1634
  }
1622
1635
 
1623
- Modal.prototype.resetAdjustments = function () {
1624
- this.$element.css({
1625
- paddingLeft: '',
1626
- paddingRight: ''
1627
- })
1636
+ Tooltip.prototype.enable = function () {
1637
+ this.enabled = true
1628
1638
  }
1629
1639
 
1630
- Modal.prototype.checkScrollbar = function () {
1631
- this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
1632
- this.scrollbarWidth = this.measureScrollbar()
1640
+ Tooltip.prototype.disable = function () {
1641
+ this.enabled = false
1633
1642
  }
1634
1643
 
1635
- Modal.prototype.setScrollbar = function () {
1636
- var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1637
- if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1644
+ Tooltip.prototype.toggleEnabled = function () {
1645
+ this.enabled = !this.enabled
1638
1646
  }
1639
1647
 
1640
- Modal.prototype.resetScrollbar = function () {
1641
- this.$body.css('padding-right', '')
1648
+ Tooltip.prototype.toggle = function (e) {
1649
+ var self = this
1650
+ if (e) {
1651
+ self = $(e.currentTarget).data('bs.' + this.type)
1652
+ if (!self) {
1653
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1654
+ $(e.currentTarget).data('bs.' + this.type, self)
1655
+ }
1656
+ }
1657
+
1658
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1642
1659
  }
1643
1660
 
1644
- Modal.prototype.measureScrollbar = function () { // thx walsh
1645
- var scrollDiv = document.createElement('div')
1646
- scrollDiv.className = 'modal-scrollbar-measure'
1647
- this.$body.append(scrollDiv)
1648
- var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1649
- this.$body[0].removeChild(scrollDiv)
1650
- return scrollbarWidth
1661
+ Tooltip.prototype.destroy = function () {
1662
+ var that = this
1663
+ clearTimeout(this.timeout)
1664
+ this.hide(function () {
1665
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
1666
+ })
1651
1667
  }
1652
1668
 
1653
1669
 
1654
- // MODAL PLUGIN DEFINITION
1655
- // =======================
1670
+ // TOOLTIP PLUGIN DEFINITION
1671
+ // =========================
1656
1672
 
1657
- function Plugin(option, _relatedTarget) {
1673
+ function Plugin(option) {
1658
1674
  return this.each(function () {
1659
1675
  var $this = $(this)
1660
- var data = $this.data('bs.modal')
1661
- var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1676
+ var data = $this.data('bs.tooltip')
1677
+ var options = typeof option == 'object' && option
1662
1678
 
1663
- if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1664
- if (typeof option == 'string') data[option](_relatedTarget)
1665
- else if (options.show) data.show(_relatedTarget)
1679
+ if (!data && option == 'destroy') return
1680
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1681
+ if (typeof option == 'string') data[option]()
1666
1682
  })
1667
1683
  }
1668
1684
 
1669
- var old = $.fn.modal
1685
+ var old = $.fn.tooltip
1670
1686
 
1671
- $.fn.modal = Plugin
1672
- $.fn.modal.Constructor = Modal
1687
+ $.fn.tooltip = Plugin
1688
+ $.fn.tooltip.Constructor = Tooltip
1673
1689
 
1674
1690
 
1675
- // MODAL NO CONFLICT
1676
- // =================
1691
+ // TOOLTIP NO CONFLICT
1692
+ // ===================
1677
1693
 
1678
- $.fn.modal.noConflict = function () {
1679
- $.fn.modal = old
1694
+ $.fn.tooltip.noConflict = function () {
1695
+ $.fn.tooltip = old
1680
1696
  return this
1681
1697
  }
1682
1698
 
1683
-
1684
- // MODAL DATA-API
1685
- // ==============
1686
-
1687
- $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1688
- var $this = $(this)
1689
- var href = $this.attr('href')
1690
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1691
- var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1692
-
1693
- if ($this.is('a')) e.preventDefault()
1694
-
1695
- $target.one('show.bs.modal', function (showEvent) {
1696
- if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1697
- $target.one('hidden.bs.modal', function () {
1698
- $this.is(':visible') && $this.trigger('focus')
1699
- })
1700
- })
1701
- Plugin.call($target, option, this)
1702
- })
1703
-
1704
1699
  }(jQuery);
1705
1700
 
1706
1701
  /* ========================================================================
1707
- * Bootstrap: tooltip.js v3.3.1
1708
- * http://getbootstrap.com/javascript/#tooltip
1709
- * Inspired by the original jQuery.tipsy by Jason Frame
1702
+ * Bootstrap: popover.js v3.3.2
1703
+ * http://getbootstrap.com/javascript/#popovers
1710
1704
  * ========================================================================
1711
- * Copyright 2011-2014 Twitter, Inc.
1705
+ * Copyright 2011-2015 Twitter, Inc.
1712
1706
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1713
1707
  * ======================================================================== */
1714
1708
 
@@ -1716,477 +1710,443 @@
1716
1710
  +function ($) {
1717
1711
  'use strict';
1718
1712
 
1719
- // TOOLTIP PUBLIC CLASS DEFINITION
1713
+ // POPOVER PUBLIC CLASS DEFINITION
1720
1714
  // ===============================
1721
1715
 
1722
- var Tooltip = function (element, options) {
1723
- this.type =
1724
- this.options =
1725
- this.enabled =
1726
- this.timeout =
1727
- this.hoverState =
1728
- this.$element = null
1729
-
1730
- this.init('tooltip', element, options)
1731
- }
1732
-
1733
- Tooltip.VERSION = '3.3.1'
1734
-
1735
- Tooltip.TRANSITION_DURATION = 150
1736
-
1737
- Tooltip.DEFAULTS = {
1738
- animation: true,
1739
- placement: 'top',
1740
- selector: false,
1741
- template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1742
- trigger: 'hover focus',
1743
- title: '',
1744
- delay: 0,
1745
- html: false,
1746
- container: false,
1747
- viewport: {
1748
- selector: 'body',
1749
- padding: 0
1750
- }
1716
+ var Popover = function (element, options) {
1717
+ this.init('popover', element, options)
1751
1718
  }
1752
1719
 
1753
- Tooltip.prototype.init = function (type, element, options) {
1754
- this.enabled = true
1755
- this.type = type
1756
- this.$element = $(element)
1757
- this.options = this.getOptions(options)
1758
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1720
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1759
1721
 
1760
- var triggers = this.options.trigger.split(' ')
1722
+ Popover.VERSION = '3.3.2'
1761
1723
 
1762
- for (var i = triggers.length; i--;) {
1763
- var trigger = triggers[i]
1724
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1725
+ placement: 'right',
1726
+ trigger: 'click',
1727
+ content: '',
1728
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1729
+ })
1764
1730
 
1765
- if (trigger == 'click') {
1766
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1767
- } else if (trigger != 'manual') {
1768
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1769
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1770
1731
 
1771
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1772
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1773
- }
1774
- }
1732
+ // NOTE: POPOVER EXTENDS tooltip.js
1733
+ // ================================
1775
1734
 
1776
- this.options.selector ?
1777
- (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1778
- this.fixTitle()
1779
- }
1735
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1780
1736
 
1781
- Tooltip.prototype.getDefaults = function () {
1782
- return Tooltip.DEFAULTS
1737
+ Popover.prototype.constructor = Popover
1738
+
1739
+ Popover.prototype.getDefaults = function () {
1740
+ return Popover.DEFAULTS
1783
1741
  }
1784
1742
 
1785
- Tooltip.prototype.getOptions = function (options) {
1786
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1743
+ Popover.prototype.setContent = function () {
1744
+ var $tip = this.tip()
1745
+ var title = this.getTitle()
1746
+ var content = this.getContent()
1787
1747
 
1788
- if (options.delay && typeof options.delay == 'number') {
1789
- options.delay = {
1790
- show: options.delay,
1791
- hide: options.delay
1792
- }
1793
- }
1748
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1749
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1750
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1751
+ ](content)
1794
1752
 
1795
- return options
1753
+ $tip.removeClass('fade top bottom left right in')
1754
+
1755
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1756
+ // this manually by checking the contents.
1757
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1796
1758
  }
1797
1759
 
1798
- Tooltip.prototype.getDelegateOptions = function () {
1799
- var options = {}
1800
- var defaults = this.getDefaults()
1760
+ Popover.prototype.hasContent = function () {
1761
+ return this.getTitle() || this.getContent()
1762
+ }
1801
1763
 
1802
- this._options && $.each(this._options, function (key, value) {
1803
- if (defaults[key] != value) options[key] = value
1804
- })
1764
+ Popover.prototype.getContent = function () {
1765
+ var $e = this.$element
1766
+ var o = this.options
1805
1767
 
1806
- return options
1768
+ return $e.attr('data-content')
1769
+ || (typeof o.content == 'function' ?
1770
+ o.content.call($e[0]) :
1771
+ o.content)
1807
1772
  }
1808
1773
 
1809
- Tooltip.prototype.enter = function (obj) {
1810
- var self = obj instanceof this.constructor ?
1811
- obj : $(obj.currentTarget).data('bs.' + this.type)
1812
-
1813
- if (self && self.$tip && self.$tip.is(':visible')) {
1814
- self.hoverState = 'in'
1815
- return
1816
- }
1774
+ Popover.prototype.arrow = function () {
1775
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1776
+ }
1817
1777
 
1818
- if (!self) {
1819
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1820
- $(obj.currentTarget).data('bs.' + this.type, self)
1821
- }
1778
+ Popover.prototype.tip = function () {
1779
+ if (!this.$tip) this.$tip = $(this.options.template)
1780
+ return this.$tip
1781
+ }
1822
1782
 
1823
- clearTimeout(self.timeout)
1824
1783
 
1825
- self.hoverState = 'in'
1784
+ // POPOVER PLUGIN DEFINITION
1785
+ // =========================
1826
1786
 
1827
- if (!self.options.delay || !self.options.delay.show) return self.show()
1787
+ function Plugin(option) {
1788
+ return this.each(function () {
1789
+ var $this = $(this)
1790
+ var data = $this.data('bs.popover')
1791
+ var options = typeof option == 'object' && option
1828
1792
 
1829
- self.timeout = setTimeout(function () {
1830
- if (self.hoverState == 'in') self.show()
1831
- }, self.options.delay.show)
1793
+ if (!data && option == 'destroy') return
1794
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1795
+ if (typeof option == 'string') data[option]()
1796
+ })
1832
1797
  }
1833
1798
 
1834
- Tooltip.prototype.leave = function (obj) {
1835
- var self = obj instanceof this.constructor ?
1836
- obj : $(obj.currentTarget).data('bs.' + this.type)
1837
-
1838
- if (!self) {
1839
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1840
- $(obj.currentTarget).data('bs.' + this.type, self)
1841
- }
1799
+ var old = $.fn.popover
1842
1800
 
1843
- clearTimeout(self.timeout)
1801
+ $.fn.popover = Plugin
1802
+ $.fn.popover.Constructor = Popover
1844
1803
 
1845
- self.hoverState = 'out'
1846
1804
 
1847
- if (!self.options.delay || !self.options.delay.hide) return self.hide()
1805
+ // POPOVER NO CONFLICT
1806
+ // ===================
1848
1807
 
1849
- self.timeout = setTimeout(function () {
1850
- if (self.hoverState == 'out') self.hide()
1851
- }, self.options.delay.hide)
1808
+ $.fn.popover.noConflict = function () {
1809
+ $.fn.popover = old
1810
+ return this
1852
1811
  }
1853
1812
 
1854
- Tooltip.prototype.show = function () {
1855
- var e = $.Event('show.bs.' + this.type)
1856
-
1857
- if (this.hasContent() && this.enabled) {
1858
- this.$element.trigger(e)
1813
+ }(jQuery);
1859
1814
 
1860
- var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1861
- if (e.isDefaultPrevented() || !inDom) return
1862
- var that = this
1815
+ /* ========================================================================
1816
+ * Bootstrap: scrollspy.js v3.3.2
1817
+ * http://getbootstrap.com/javascript/#scrollspy
1818
+ * ========================================================================
1819
+ * Copyright 2011-2015 Twitter, Inc.
1820
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1821
+ * ======================================================================== */
1863
1822
 
1864
- var $tip = this.tip()
1865
1823
 
1866
- var tipId = this.getUID(this.type)
1824
+ +function ($) {
1825
+ 'use strict';
1867
1826
 
1868
- this.setContent()
1869
- $tip.attr('id', tipId)
1870
- this.$element.attr('aria-describedby', tipId)
1827
+ // SCROLLSPY CLASS DEFINITION
1828
+ // ==========================
1871
1829
 
1872
- if (this.options.animation) $tip.addClass('fade')
1830
+ function ScrollSpy(element, options) {
1831
+ var process = $.proxy(this.process, this)
1873
1832
 
1874
- var placement = typeof this.options.placement == 'function' ?
1875
- this.options.placement.call(this, $tip[0], this.$element[0]) :
1876
- this.options.placement
1833
+ this.$body = $('body')
1834
+ this.$scrollElement = $(element).is('body') ? $(window) : $(element)
1835
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1836
+ this.selector = (this.options.target || '') + ' .nav li > a'
1837
+ this.offsets = []
1838
+ this.targets = []
1839
+ this.activeTarget = null
1840
+ this.scrollHeight = 0
1877
1841
 
1878
- var autoToken = /\s?auto?\s?/i
1879
- var autoPlace = autoToken.test(placement)
1880
- if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1842
+ this.$scrollElement.on('scroll.bs.scrollspy', process)
1843
+ this.refresh()
1844
+ this.process()
1845
+ }
1881
1846
 
1882
- $tip
1883
- .detach()
1884
- .css({ top: 0, left: 0, display: 'block' })
1885
- .addClass(placement)
1886
- .data('bs.' + this.type, this)
1847
+ ScrollSpy.VERSION = '3.3.2'
1887
1848
 
1888
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1849
+ ScrollSpy.DEFAULTS = {
1850
+ offset: 10
1851
+ }
1889
1852
 
1890
- var pos = this.getPosition()
1891
- var actualWidth = $tip[0].offsetWidth
1892
- var actualHeight = $tip[0].offsetHeight
1853
+ ScrollSpy.prototype.getScrollHeight = function () {
1854
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1855
+ }
1893
1856
 
1894
- if (autoPlace) {
1895
- var orgPlacement = placement
1896
- var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1897
- var containerDim = this.getPosition($container)
1857
+ ScrollSpy.prototype.refresh = function () {
1858
+ var offsetMethod = 'offset'
1859
+ var offsetBase = 0
1898
1860
 
1899
- placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1900
- placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1901
- placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1902
- placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1903
- placement
1861
+ if (!$.isWindow(this.$scrollElement[0])) {
1862
+ offsetMethod = 'position'
1863
+ offsetBase = this.$scrollElement.scrollTop()
1864
+ }
1904
1865
 
1905
- $tip
1906
- .removeClass(orgPlacement)
1907
- .addClass(placement)
1908
- }
1866
+ this.offsets = []
1867
+ this.targets = []
1868
+ this.scrollHeight = this.getScrollHeight()
1909
1869
 
1910
- var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1870
+ var self = this
1911
1871
 
1912
- this.applyPlacement(calculatedOffset, placement)
1872
+ this.$body
1873
+ .find(this.selector)
1874
+ .map(function () {
1875
+ var $el = $(this)
1876
+ var href = $el.data('target') || $el.attr('href')
1877
+ var $href = /^#./.test(href) && $(href)
1913
1878
 
1914
- var complete = function () {
1915
- var prevHoverState = that.hoverState
1916
- that.$element.trigger('shown.bs.' + that.type)
1917
- that.hoverState = null
1879
+ return ($href
1880
+ && $href.length
1881
+ && $href.is(':visible')
1882
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1883
+ })
1884
+ .sort(function (a, b) { return a[0] - b[0] })
1885
+ .each(function () {
1886
+ self.offsets.push(this[0])
1887
+ self.targets.push(this[1])
1888
+ })
1889
+ }
1918
1890
 
1919
- if (prevHoverState == 'out') that.leave(that)
1920
- }
1891
+ ScrollSpy.prototype.process = function () {
1892
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1893
+ var scrollHeight = this.getScrollHeight()
1894
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1895
+ var offsets = this.offsets
1896
+ var targets = this.targets
1897
+ var activeTarget = this.activeTarget
1898
+ var i
1921
1899
 
1922
- $.support.transition && this.$tip.hasClass('fade') ?
1923
- $tip
1924
- .one('bsTransitionEnd', complete)
1925
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1926
- complete()
1900
+ if (this.scrollHeight != scrollHeight) {
1901
+ this.refresh()
1927
1902
  }
1928
- }
1929
1903
 
1930
- Tooltip.prototype.applyPlacement = function (offset, placement) {
1931
- var $tip = this.tip()
1932
- var width = $tip[0].offsetWidth
1933
- var height = $tip[0].offsetHeight
1904
+ if (scrollTop >= maxScroll) {
1905
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1906
+ }
1934
1907
 
1935
- // manually read margins because getBoundingClientRect includes difference
1936
- var marginTop = parseInt($tip.css('margin-top'), 10)
1937
- var marginLeft = parseInt($tip.css('margin-left'), 10)
1908
+ if (activeTarget && scrollTop < offsets[0]) {
1909
+ this.activeTarget = null
1910
+ return this.clear()
1911
+ }
1938
1912
 
1939
- // we must check for NaN for ie 8/9
1940
- if (isNaN(marginTop)) marginTop = 0
1941
- if (isNaN(marginLeft)) marginLeft = 0
1913
+ for (i = offsets.length; i--;) {
1914
+ activeTarget != targets[i]
1915
+ && scrollTop >= offsets[i]
1916
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1917
+ && this.activate(targets[i])
1918
+ }
1919
+ }
1942
1920
 
1943
- offset.top = offset.top + marginTop
1944
- offset.left = offset.left + marginLeft
1921
+ ScrollSpy.prototype.activate = function (target) {
1922
+ this.activeTarget = target
1945
1923
 
1946
- // $.fn.offset doesn't round pixel values
1947
- // so we use setOffset directly with our own function B-0
1948
- $.offset.setOffset($tip[0], $.extend({
1949
- using: function (props) {
1950
- $tip.css({
1951
- top: Math.round(props.top),
1952
- left: Math.round(props.left)
1953
- })
1954
- }
1955
- }, offset), 0)
1924
+ this.clear()
1956
1925
 
1957
- $tip.addClass('in')
1926
+ var selector = this.selector +
1927
+ '[data-target="' + target + '"],' +
1928
+ this.selector + '[href="' + target + '"]'
1958
1929
 
1959
- // check to see if placing tip in new offset caused the tip to resize itself
1960
- var actualWidth = $tip[0].offsetWidth
1961
- var actualHeight = $tip[0].offsetHeight
1930
+ var active = $(selector)
1931
+ .parents('li')
1932
+ .addClass('active')
1962
1933
 
1963
- if (placement == 'top' && actualHeight != height) {
1964
- offset.top = offset.top + height - actualHeight
1934
+ if (active.parent('.dropdown-menu').length) {
1935
+ active = active
1936
+ .closest('li.dropdown')
1937
+ .addClass('active')
1965
1938
  }
1966
1939
 
1967
- var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1968
-
1969
- if (delta.left) offset.left += delta.left
1970
- else offset.top += delta.top
1971
-
1972
- var isVertical = /top|bottom/.test(placement)
1973
- var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1974
- var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1975
-
1976
- $tip.offset(offset)
1977
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1940
+ active.trigger('activate.bs.scrollspy')
1978
1941
  }
1979
1942
 
1980
- Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
1981
- this.arrow()
1982
- .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1983
- .css(isHorizontal ? 'top' : 'left', '')
1943
+ ScrollSpy.prototype.clear = function () {
1944
+ $(this.selector)
1945
+ .parentsUntil(this.options.target, '.active')
1946
+ .removeClass('active')
1984
1947
  }
1985
1948
 
1986
- Tooltip.prototype.setContent = function () {
1987
- var $tip = this.tip()
1988
- var title = this.getTitle()
1989
-
1990
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1991
- $tip.removeClass('fade in top bottom left right')
1992
- }
1993
1949
 
1994
- Tooltip.prototype.hide = function (callback) {
1995
- var that = this
1996
- var $tip = this.tip()
1997
- var e = $.Event('hide.bs.' + this.type)
1950
+ // SCROLLSPY PLUGIN DEFINITION
1951
+ // ===========================
1998
1952
 
1999
- function complete() {
2000
- if (that.hoverState != 'in') $tip.detach()
2001
- that.$element
2002
- .removeAttr('aria-describedby')
2003
- .trigger('hidden.bs.' + that.type)
2004
- callback && callback()
2005
- }
1953
+ function Plugin(option) {
1954
+ return this.each(function () {
1955
+ var $this = $(this)
1956
+ var data = $this.data('bs.scrollspy')
1957
+ var options = typeof option == 'object' && option
2006
1958
 
2007
- this.$element.trigger(e)
1959
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1960
+ if (typeof option == 'string') data[option]()
1961
+ })
1962
+ }
2008
1963
 
2009
- if (e.isDefaultPrevented()) return
1964
+ var old = $.fn.scrollspy
2010
1965
 
2011
- $tip.removeClass('in')
1966
+ $.fn.scrollspy = Plugin
1967
+ $.fn.scrollspy.Constructor = ScrollSpy
2012
1968
 
2013
- $.support.transition && this.$tip.hasClass('fade') ?
2014
- $tip
2015
- .one('bsTransitionEnd', complete)
2016
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
2017
- complete()
2018
1969
 
2019
- this.hoverState = null
1970
+ // SCROLLSPY NO CONFLICT
1971
+ // =====================
2020
1972
 
1973
+ $.fn.scrollspy.noConflict = function () {
1974
+ $.fn.scrollspy = old
2021
1975
  return this
2022
1976
  }
2023
1977
 
2024
- Tooltip.prototype.fixTitle = function () {
2025
- var $e = this.$element
2026
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
2027
- $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
2028
- }
2029
- }
2030
1978
 
2031
- Tooltip.prototype.hasContent = function () {
2032
- return this.getTitle()
2033
- }
1979
+ // SCROLLSPY DATA-API
1980
+ // ==================
2034
1981
 
2035
- Tooltip.prototype.getPosition = function ($element) {
2036
- $element = $element || this.$element
1982
+ $(window).on('load.bs.scrollspy.data-api', function () {
1983
+ $('[data-spy="scroll"]').each(function () {
1984
+ var $spy = $(this)
1985
+ Plugin.call($spy, $spy.data())
1986
+ })
1987
+ })
2037
1988
 
2038
- var el = $element[0]
2039
- var isBody = el.tagName == 'BODY'
1989
+ }(jQuery);
2040
1990
 
2041
- var elRect = el.getBoundingClientRect()
2042
- if (elRect.width == null) {
2043
- // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
2044
- elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
2045
- }
2046
- var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
2047
- var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
2048
- var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1991
+ /* ========================================================================
1992
+ * Bootstrap: tab.js v3.3.2
1993
+ * http://getbootstrap.com/javascript/#tabs
1994
+ * ========================================================================
1995
+ * Copyright 2011-2015 Twitter, Inc.
1996
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1997
+ * ======================================================================== */
2049
1998
 
2050
- return $.extend({}, elRect, scroll, outerDims, elOffset)
2051
- }
2052
1999
 
2053
- Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
2054
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
2055
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
2056
- placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
2057
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
2000
+ +function ($) {
2001
+ 'use strict';
2058
2002
 
2003
+ // TAB CLASS DEFINITION
2004
+ // ====================
2005
+
2006
+ var Tab = function (element) {
2007
+ this.element = $(element)
2059
2008
  }
2060
2009
 
2061
- Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
2062
- var delta = { top: 0, left: 0 }
2063
- if (!this.$viewport) return delta
2010
+ Tab.VERSION = '3.3.2'
2064
2011
 
2065
- var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
2066
- var viewportDimensions = this.getPosition(this.$viewport)
2012
+ Tab.TRANSITION_DURATION = 150
2067
2013
 
2068
- if (/right|left/.test(placement)) {
2069
- var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
2070
- var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
2071
- if (topEdgeOffset < viewportDimensions.top) { // top overflow
2072
- delta.top = viewportDimensions.top - topEdgeOffset
2073
- } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
2074
- delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
2075
- }
2076
- } else {
2077
- var leftEdgeOffset = pos.left - viewportPadding
2078
- var rightEdgeOffset = pos.left + viewportPadding + actualWidth
2079
- if (leftEdgeOffset < viewportDimensions.left) { // left overflow
2080
- delta.left = viewportDimensions.left - leftEdgeOffset
2081
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
2082
- delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
2083
- }
2014
+ Tab.prototype.show = function () {
2015
+ var $this = this.element
2016
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
2017
+ var selector = $this.data('target')
2018
+
2019
+ if (!selector) {
2020
+ selector = $this.attr('href')
2021
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2084
2022
  }
2085
2023
 
2086
- return delta
2087
- }
2024
+ if ($this.parent('li').hasClass('active')) return
2088
2025
 
2089
- Tooltip.prototype.getTitle = function () {
2090
- var title
2091
- var $e = this.$element
2092
- var o = this.options
2026
+ var $previous = $ul.find('.active:last a')
2027
+ var hideEvent = $.Event('hide.bs.tab', {
2028
+ relatedTarget: $this[0]
2029
+ })
2030
+ var showEvent = $.Event('show.bs.tab', {
2031
+ relatedTarget: $previous[0]
2032
+ })
2093
2033
 
2094
- title = $e.attr('data-original-title')
2095
- || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
2034
+ $previous.trigger(hideEvent)
2035
+ $this.trigger(showEvent)
2096
2036
 
2097
- return title
2098
- }
2037
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2099
2038
 
2100
- Tooltip.prototype.getUID = function (prefix) {
2101
- do prefix += ~~(Math.random() * 1000000)
2102
- while (document.getElementById(prefix))
2103
- return prefix
2104
- }
2039
+ var $target = $(selector)
2105
2040
 
2106
- Tooltip.prototype.tip = function () {
2107
- return (this.$tip = this.$tip || $(this.options.template))
2041
+ this.activate($this.closest('li'), $ul)
2042
+ this.activate($target, $target.parent(), function () {
2043
+ $previous.trigger({
2044
+ type: 'hidden.bs.tab',
2045
+ relatedTarget: $this[0]
2046
+ })
2047
+ $this.trigger({
2048
+ type: 'shown.bs.tab',
2049
+ relatedTarget: $previous[0]
2050
+ })
2051
+ })
2108
2052
  }
2109
2053
 
2110
- Tooltip.prototype.arrow = function () {
2111
- return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
2112
- }
2054
+ Tab.prototype.activate = function (element, container, callback) {
2055
+ var $active = container.find('> .active')
2056
+ var transition = callback
2057
+ && $.support.transition
2058
+ && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
2113
2059
 
2114
- Tooltip.prototype.enable = function () {
2115
- this.enabled = true
2116
- }
2060
+ function next() {
2061
+ $active
2062
+ .removeClass('active')
2063
+ .find('> .dropdown-menu > .active')
2064
+ .removeClass('active')
2065
+ .end()
2066
+ .find('[data-toggle="tab"]')
2067
+ .attr('aria-expanded', false)
2117
2068
 
2118
- Tooltip.prototype.disable = function () {
2119
- this.enabled = false
2120
- }
2069
+ element
2070
+ .addClass('active')
2071
+ .find('[data-toggle="tab"]')
2072
+ .attr('aria-expanded', true)
2121
2073
 
2122
- Tooltip.prototype.toggleEnabled = function () {
2123
- this.enabled = !this.enabled
2124
- }
2074
+ if (transition) {
2075
+ element[0].offsetWidth // reflow for transition
2076
+ element.addClass('in')
2077
+ } else {
2078
+ element.removeClass('fade')
2079
+ }
2125
2080
 
2126
- Tooltip.prototype.toggle = function (e) {
2127
- var self = this
2128
- if (e) {
2129
- self = $(e.currentTarget).data('bs.' + this.type)
2130
- if (!self) {
2131
- self = new this.constructor(e.currentTarget, this.getDelegateOptions())
2132
- $(e.currentTarget).data('bs.' + this.type, self)
2081
+ if (element.parent('.dropdown-menu')) {
2082
+ element
2083
+ .closest('li.dropdown')
2084
+ .addClass('active')
2085
+ .end()
2086
+ .find('[data-toggle="tab"]')
2087
+ .attr('aria-expanded', true)
2133
2088
  }
2089
+
2090
+ callback && callback()
2134
2091
  }
2135
2092
 
2136
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
2137
- }
2093
+ $active.length && transition ?
2094
+ $active
2095
+ .one('bsTransitionEnd', next)
2096
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
2097
+ next()
2138
2098
 
2139
- Tooltip.prototype.destroy = function () {
2140
- var that = this
2141
- clearTimeout(this.timeout)
2142
- this.hide(function () {
2143
- that.$element.off('.' + that.type).removeData('bs.' + that.type)
2144
- })
2099
+ $active.removeClass('in')
2145
2100
  }
2146
2101
 
2147
2102
 
2148
- // TOOLTIP PLUGIN DEFINITION
2149
- // =========================
2103
+ // TAB PLUGIN DEFINITION
2104
+ // =====================
2150
2105
 
2151
2106
  function Plugin(option) {
2152
2107
  return this.each(function () {
2153
- var $this = $(this)
2154
- var data = $this.data('bs.tooltip')
2155
- var options = typeof option == 'object' && option
2156
- var selector = options && options.selector
2108
+ var $this = $(this)
2109
+ var data = $this.data('bs.tab')
2157
2110
 
2158
- if (!data && option == 'destroy') return
2159
- if (selector) {
2160
- if (!data) $this.data('bs.tooltip', (data = {}))
2161
- if (!data[selector]) data[selector] = new Tooltip(this, options)
2162
- } else {
2163
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
2164
- }
2111
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
2165
2112
  if (typeof option == 'string') data[option]()
2166
2113
  })
2167
2114
  }
2168
2115
 
2169
- var old = $.fn.tooltip
2116
+ var old = $.fn.tab
2170
2117
 
2171
- $.fn.tooltip = Plugin
2172
- $.fn.tooltip.Constructor = Tooltip
2118
+ $.fn.tab = Plugin
2119
+ $.fn.tab.Constructor = Tab
2173
2120
 
2174
2121
 
2175
- // TOOLTIP NO CONFLICT
2176
- // ===================
2122
+ // TAB NO CONFLICT
2123
+ // ===============
2177
2124
 
2178
- $.fn.tooltip.noConflict = function () {
2179
- $.fn.tooltip = old
2125
+ $.fn.tab.noConflict = function () {
2126
+ $.fn.tab = old
2180
2127
  return this
2181
2128
  }
2182
2129
 
2130
+
2131
+ // TAB DATA-API
2132
+ // ============
2133
+
2134
+ var clickHandler = function (e) {
2135
+ e.preventDefault()
2136
+ Plugin.call($(this), 'show')
2137
+ }
2138
+
2139
+ $(document)
2140
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
2141
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
2142
+
2183
2143
  }(jQuery);
2184
2144
 
2185
2145
  /* ========================================================================
2186
- * Bootstrap: popover.js v3.3.1
2187
- * http://getbootstrap.com/javascript/#popovers
2146
+ * Bootstrap: affix.js v3.3.2
2147
+ * http://getbootstrap.com/javascript/#affix
2188
2148
  * ========================================================================
2189
- * Copyright 2011-2014 Twitter, Inc.
2149
+ * Copyright 2011-2015 Twitter, Inc.
2190
2150
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2191
2151
  * ======================================================================== */
2192
2152
 
@@ -2194,111 +2154,153 @@
2194
2154
  +function ($) {
2195
2155
  'use strict';
2196
2156
 
2197
- // POPOVER PUBLIC CLASS DEFINITION
2198
- // ===============================
2157
+ // AFFIX CLASS DEFINITION
2158
+ // ======================
2199
2159
 
2200
- var Popover = function (element, options) {
2201
- this.init('popover', element, options)
2202
- }
2160
+ var Affix = function (element, options) {
2161
+ this.options = $.extend({}, Affix.DEFAULTS, options)
2203
2162
 
2204
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
2163
+ this.$target = $(this.options.target)
2164
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2165
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
2205
2166
 
2206
- Popover.VERSION = '3.3.1'
2167
+ this.$element = $(element)
2168
+ this.affixed =
2169
+ this.unpin =
2170
+ this.pinnedOffset = null
2207
2171
 
2208
- Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
2209
- placement: 'right',
2210
- trigger: 'click',
2211
- content: '',
2212
- template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
2213
- })
2172
+ this.checkPosition()
2173
+ }
2214
2174
 
2175
+ Affix.VERSION = '3.3.2'
2215
2176
 
2216
- // NOTE: POPOVER EXTENDS tooltip.js
2217
- // ================================
2177
+ Affix.RESET = 'affix affix-top affix-bottom'
2218
2178
 
2219
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
2179
+ Affix.DEFAULTS = {
2180
+ offset: 0,
2181
+ target: window
2182
+ }
2220
2183
 
2221
- Popover.prototype.constructor = Popover
2184
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
2185
+ var scrollTop = this.$target.scrollTop()
2186
+ var position = this.$element.offset()
2187
+ var targetHeight = this.$target.height()
2222
2188
 
2223
- Popover.prototype.getDefaults = function () {
2224
- return Popover.DEFAULTS
2225
- }
2189
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
2226
2190
 
2227
- Popover.prototype.setContent = function () {
2228
- var $tip = this.tip()
2229
- var title = this.getTitle()
2230
- var content = this.getContent()
2191
+ if (this.affixed == 'bottom') {
2192
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
2193
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
2194
+ }
2231
2195
 
2232
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
2233
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
2234
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
2235
- ](content)
2196
+ var initializing = this.affixed == null
2197
+ var colliderTop = initializing ? scrollTop : position.top
2198
+ var colliderHeight = initializing ? targetHeight : height
2236
2199
 
2237
- $tip.removeClass('fade top bottom left right in')
2200
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
2201
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
2238
2202
 
2239
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
2240
- // this manually by checking the contents.
2241
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
2203
+ return false
2242
2204
  }
2243
2205
 
2244
- Popover.prototype.hasContent = function () {
2245
- return this.getTitle() || this.getContent()
2206
+ Affix.prototype.getPinnedOffset = function () {
2207
+ if (this.pinnedOffset) return this.pinnedOffset
2208
+ this.$element.removeClass(Affix.RESET).addClass('affix')
2209
+ var scrollTop = this.$target.scrollTop()
2210
+ var position = this.$element.offset()
2211
+ return (this.pinnedOffset = position.top - scrollTop)
2246
2212
  }
2247
2213
 
2248
- Popover.prototype.getContent = function () {
2249
- var $e = this.$element
2250
- var o = this.options
2251
-
2252
- return $e.attr('data-content')
2253
- || (typeof o.content == 'function' ?
2254
- o.content.call($e[0]) :
2255
- o.content)
2214
+ Affix.prototype.checkPositionWithEventLoop = function () {
2215
+ setTimeout($.proxy(this.checkPosition, this), 1)
2256
2216
  }
2257
2217
 
2258
- Popover.prototype.arrow = function () {
2259
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
2260
- }
2218
+ Affix.prototype.checkPosition = function () {
2219
+ if (!this.$element.is(':visible')) return
2261
2220
 
2262
- Popover.prototype.tip = function () {
2263
- if (!this.$tip) this.$tip = $(this.options.template)
2264
- return this.$tip
2221
+ var height = this.$element.height()
2222
+ var offset = this.options.offset
2223
+ var offsetTop = offset.top
2224
+ var offsetBottom = offset.bottom
2225
+ var scrollHeight = $('body').height()
2226
+
2227
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
2228
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2229
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2230
+
2231
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2232
+
2233
+ if (this.affixed != affix) {
2234
+ if (this.unpin != null) this.$element.css('top', '')
2235
+
2236
+ var affixType = 'affix' + (affix ? '-' + affix : '')
2237
+ var e = $.Event(affixType + '.bs.affix')
2238
+
2239
+ this.$element.trigger(e)
2240
+
2241
+ if (e.isDefaultPrevented()) return
2242
+
2243
+ this.affixed = affix
2244
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2245
+
2246
+ this.$element
2247
+ .removeClass(Affix.RESET)
2248
+ .addClass(affixType)
2249
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2250
+ }
2251
+
2252
+ if (affix == 'bottom') {
2253
+ this.$element.offset({
2254
+ top: scrollHeight - height - offsetBottom
2255
+ })
2256
+ }
2265
2257
  }
2266
2258
 
2267
2259
 
2268
- // POPOVER PLUGIN DEFINITION
2269
- // =========================
2260
+ // AFFIX PLUGIN DEFINITION
2261
+ // =======================
2270
2262
 
2271
2263
  function Plugin(option) {
2272
2264
  return this.each(function () {
2273
- var $this = $(this)
2274
- var data = $this.data('bs.popover')
2275
- var options = typeof option == 'object' && option
2276
- var selector = options && options.selector
2265
+ var $this = $(this)
2266
+ var data = $this.data('bs.affix')
2267
+ var options = typeof option == 'object' && option
2277
2268
 
2278
- if (!data && option == 'destroy') return
2279
- if (selector) {
2280
- if (!data) $this.data('bs.popover', (data = {}))
2281
- if (!data[selector]) data[selector] = new Popover(this, options)
2282
- } else {
2283
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
2284
- }
2269
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
2285
2270
  if (typeof option == 'string') data[option]()
2286
2271
  })
2287
2272
  }
2288
2273
 
2289
- var old = $.fn.popover
2274
+ var old = $.fn.affix
2290
2275
 
2291
- $.fn.popover = Plugin
2292
- $.fn.popover.Constructor = Popover
2276
+ $.fn.affix = Plugin
2277
+ $.fn.affix.Constructor = Affix
2293
2278
 
2294
2279
 
2295
- // POPOVER NO CONFLICT
2296
- // ===================
2280
+ // AFFIX NO CONFLICT
2281
+ // =================
2297
2282
 
2298
- $.fn.popover.noConflict = function () {
2299
- $.fn.popover = old
2283
+ $.fn.affix.noConflict = function () {
2284
+ $.fn.affix = old
2300
2285
  return this
2301
2286
  }
2302
2287
 
2303
- }(jQuery);
2304
2288
 
2289
+ // AFFIX DATA-API
2290
+ // ==============
2291
+
2292
+ $(window).on('load', function () {
2293
+ $('[data-spy="affix"]').each(function () {
2294
+ var $spy = $(this)
2295
+ var data = $spy.data()
2296
+
2297
+ data.offset = data.offset || {}
2298
+
2299
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2300
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
2301
+
2302
+ Plugin.call($spy, data)
2303
+ })
2304
+ })
2305
+
2306
+ }(jQuery);