bootstrap-sass 3.3.1.0 → 3.3.6

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