blazer 1.7.7 → 2.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +242 -33
  3. data/CONTRIBUTING.md +42 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +621 -211
  6. data/app/assets/fonts/blazer/glyphicons-halflings-regular.eot +0 -0
  7. data/app/assets/fonts/blazer/glyphicons-halflings-regular.svg +0 -0
  8. data/app/assets/fonts/blazer/glyphicons-halflings-regular.ttf +0 -0
  9. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff +0 -0
  10. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff2 +0 -0
  11. data/app/assets/images/blazer/favicon.png +0 -0
  12. data/app/assets/javascripts/blazer/Chart.js +15658 -10011
  13. data/app/assets/javascripts/blazer/Sortable.js +3413 -848
  14. data/app/assets/javascripts/blazer/ace/ace.js +21294 -4
  15. data/app/assets/javascripts/blazer/ace/ext-language_tools.js +1991 -3
  16. data/app/assets/javascripts/blazer/ace/mode-sql.js +110 -1
  17. data/app/assets/javascripts/blazer/ace/snippets/sql.js +40 -1
  18. data/app/assets/javascripts/blazer/ace/snippets/text.js +14 -1
  19. data/app/assets/javascripts/blazer/ace/theme-twilight.js +116 -1
  20. data/app/assets/javascripts/blazer/application.js +5 -3
  21. data/app/assets/javascripts/blazer/bootstrap.js +842 -628
  22. data/app/assets/javascripts/blazer/chartkick.js +2015 -1244
  23. data/app/assets/javascripts/blazer/daterangepicker.js +372 -299
  24. data/app/assets/javascripts/blazer/highlight.min.js +3 -0
  25. data/app/assets/javascripts/blazer/{jquery_ujs.js → jquery-ujs.js} +161 -75
  26. data/app/assets/javascripts/blazer/jquery.js +10126 -9562
  27. data/app/assets/javascripts/blazer/jquery.stickytableheaders.js +321 -259
  28. data/app/assets/javascripts/blazer/moment-timezone-with-data.js +1546 -0
  29. data/app/assets/javascripts/blazer/moment.js +5085 -2460
  30. data/app/assets/javascripts/blazer/queries.js +18 -4
  31. data/app/assets/javascripts/blazer/routes.js +3 -0
  32. data/app/assets/javascripts/blazer/selectize.js +3828 -3604
  33. data/app/assets/javascripts/blazer/stupidtable-custom-settings.js +13 -0
  34. data/app/assets/javascripts/blazer/stupidtable.js +254 -87
  35. data/app/assets/javascripts/blazer/vue.js +11175 -6676
  36. data/app/assets/stylesheets/blazer/application.css +51 -6
  37. data/app/assets/stylesheets/blazer/bootstrap-propshaft.css +10 -0
  38. data/app/assets/stylesheets/blazer/bootstrap-sprockets.css.erb +10 -0
  39. data/app/assets/stylesheets/blazer/{bootstrap.css.erb → bootstrap.css} +1337 -711
  40. data/app/assets/stylesheets/blazer/{daterangepicker-bs3.css → daterangepicker.css} +207 -172
  41. data/app/assets/stylesheets/blazer/{selectize.default.css → selectize.css} +26 -10
  42. data/app/controllers/blazer/base_controller.rb +73 -46
  43. data/app/controllers/blazer/checks_controller.rb +1 -1
  44. data/app/controllers/blazer/dashboards_controller.rb +7 -13
  45. data/app/controllers/blazer/queries_controller.rb +171 -51
  46. data/app/controllers/blazer/uploads_controller.rb +147 -0
  47. data/app/helpers/blazer/base_helper.rb +6 -16
  48. data/app/models/blazer/audit.rb +3 -3
  49. data/app/models/blazer/check.rb +31 -5
  50. data/app/models/blazer/dashboard.rb +6 -2
  51. data/app/models/blazer/dashboard_query.rb +1 -1
  52. data/app/models/blazer/query.rb +30 -4
  53. data/app/models/blazer/record.rb +5 -0
  54. data/app/models/blazer/upload.rb +11 -0
  55. data/app/models/blazer/uploads_connection.rb +7 -0
  56. data/app/views/blazer/_nav.html.erb +3 -1
  57. data/app/views/blazer/_variables.html.erb +48 -23
  58. data/app/views/blazer/check_mailer/failing_checks.html.erb +1 -0
  59. data/app/views/blazer/check_mailer/state_change.html.erb +1 -0
  60. data/app/views/blazer/checks/_form.html.erb +17 -9
  61. data/app/views/blazer/checks/edit.html.erb +2 -0
  62. data/app/views/blazer/checks/index.html.erb +37 -5
  63. data/app/views/blazer/checks/new.html.erb +2 -0
  64. data/app/views/blazer/dashboards/_form.html.erb +5 -5
  65. data/app/views/blazer/dashboards/edit.html.erb +2 -0
  66. data/app/views/blazer/dashboards/new.html.erb +2 -0
  67. data/app/views/blazer/dashboards/show.html.erb +13 -7
  68. data/app/views/blazer/queries/_caching.html.erb +16 -0
  69. data/app/views/blazer/queries/_cohorts.html.erb +48 -0
  70. data/app/views/blazer/queries/_form.html.erb +23 -13
  71. data/app/views/blazer/queries/docs.html.erb +137 -0
  72. data/app/views/blazer/queries/home.html.erb +21 -7
  73. data/app/views/blazer/queries/run.html.erb +64 -29
  74. data/app/views/blazer/queries/schema.html.erb +44 -7
  75. data/app/views/blazer/queries/show.html.erb +15 -8
  76. data/app/views/blazer/uploads/_form.html.erb +27 -0
  77. data/app/views/blazer/uploads/edit.html.erb +3 -0
  78. data/app/views/blazer/uploads/index.html.erb +55 -0
  79. data/app/views/blazer/uploads/new.html.erb +3 -0
  80. data/app/views/layouts/blazer/application.html.erb +10 -5
  81. data/config/routes.rb +10 -1
  82. data/lib/blazer/adapters/athena_adapter.rb +182 -0
  83. data/lib/blazer/adapters/base_adapter.rb +24 -1
  84. data/lib/blazer/adapters/bigquery_adapter.rb +79 -0
  85. data/lib/blazer/adapters/cassandra_adapter.rb +70 -0
  86. data/lib/blazer/adapters/drill_adapter.rb +38 -0
  87. data/lib/blazer/adapters/druid_adapter.rb +102 -0
  88. data/lib/blazer/adapters/elasticsearch_adapter.rb +30 -18
  89. data/lib/blazer/adapters/hive_adapter.rb +55 -0
  90. data/lib/blazer/adapters/ignite_adapter.rb +64 -0
  91. data/lib/blazer/adapters/influxdb_adapter.rb +57 -0
  92. data/lib/blazer/adapters/mongodb_adapter.rb +5 -1
  93. data/lib/blazer/adapters/neo4j_adapter.rb +62 -0
  94. data/lib/blazer/adapters/opensearch_adapter.rb +52 -0
  95. data/lib/blazer/adapters/presto_adapter.rb +9 -0
  96. data/lib/blazer/adapters/salesforce_adapter.rb +50 -0
  97. data/lib/blazer/adapters/snowflake_adapter.rb +82 -0
  98. data/lib/blazer/adapters/soda_adapter.rb +105 -0
  99. data/lib/blazer/adapters/spark_adapter.rb +14 -0
  100. data/lib/blazer/adapters/sql_adapter.rb +187 -20
  101. data/{app/mailers → lib}/blazer/check_mailer.rb +0 -0
  102. data/lib/blazer/data_source.rb +107 -30
  103. data/lib/blazer/engine.rb +21 -23
  104. data/lib/blazer/result.rb +95 -29
  105. data/lib/blazer/run_statement.rb +8 -4
  106. data/lib/blazer/run_statement_job.rb +8 -9
  107. data/lib/blazer/slack_notifier.rb +94 -0
  108. data/lib/blazer/statement.rb +75 -0
  109. data/lib/blazer/version.rb +1 -1
  110. data/lib/blazer.rb +154 -26
  111. data/lib/generators/blazer/install_generator.rb +7 -18
  112. data/lib/generators/blazer/templates/{config.yml → config.yml.tt} +26 -3
  113. data/lib/generators/blazer/templates/{install.rb → install.rb.tt} +6 -4
  114. data/lib/generators/blazer/templates/uploads.rb.tt +10 -0
  115. data/lib/generators/blazer/uploads_generator.rb +18 -0
  116. data/lib/tasks/blazer.rake +11 -1
  117. data/licenses/LICENSE-ace.txt +24 -0
  118. data/licenses/LICENSE-bootstrap.txt +21 -0
  119. data/licenses/LICENSE-chart.js.txt +9 -0
  120. data/licenses/LICENSE-chartkick.js.txt +22 -0
  121. data/licenses/LICENSE-daterangepicker.txt +21 -0
  122. data/licenses/LICENSE-fuzzysearch.txt +20 -0
  123. data/licenses/LICENSE-highlight.js.txt +29 -0
  124. data/licenses/LICENSE-jquery-ujs.txt +20 -0
  125. data/licenses/LICENSE-jquery.txt +20 -0
  126. data/licenses/LICENSE-moment-timezone.txt +20 -0
  127. data/licenses/LICENSE-moment.txt +22 -0
  128. data/licenses/LICENSE-selectize.txt +202 -0
  129. data/licenses/LICENSE-sortable.txt +21 -0
  130. data/licenses/LICENSE-stickytableheaders.txt +20 -0
  131. data/licenses/LICENSE-stupidtable.txt +19 -0
  132. data/licenses/LICENSE-vue.txt +21 -0
  133. metadata +83 -53
  134. data/.gitignore +0 -14
  135. data/Gemfile +0 -4
  136. data/Rakefile +0 -1
  137. data/app/assets/javascripts/blazer/highlight.pack.js +0 -1
  138. data/app/assets/javascripts/blazer/moment-timezone.js +0 -1007
  139. data/blazer.gemspec +0 -26
@@ -1,29 +1,86 @@
1
1
  /*!
2
- * Bootstrap v3.3.5 (http://getbootstrap.com)
3
- * Copyright 2011-2015 Twitter, Inc.
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2
+ * Bootstrap v3.4.1 (https://getbootstrap.com/)
3
+ * Copyright 2011-2019 Twitter, Inc.
4
+ * Licensed under the MIT license
5
5
  */
6
6
 
7
- /*!
8
- * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=d036843dd9c06213abe3)
9
- * Config saved to config.json and https://gist.github.com/d036843dd9c06213abe3
10
- */
11
7
  if (typeof jQuery === 'undefined') {
12
8
  throw new Error('Bootstrap\'s JavaScript requires jQuery')
13
9
  }
10
+
14
11
  +function ($) {
15
12
  'use strict';
16
13
  var version = $.fn.jquery.split(' ')[0].split('.')
17
- if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
18
- throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
14
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
15
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
16
+ }
17
+ }(jQuery);
18
+
19
+ /* ========================================================================
20
+ * Bootstrap: transition.js v3.4.1
21
+ * https://getbootstrap.com/docs/3.4/javascript/#transitions
22
+ * ========================================================================
23
+ * Copyright 2011-2019 Twitter, Inc.
24
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
+ * ======================================================================== */
26
+
27
+
28
+ +function ($) {
29
+ 'use strict';
30
+
31
+ // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
32
+ // ============================================================
33
+
34
+ function transitionEnd() {
35
+ var el = document.createElement('bootstrap')
36
+
37
+ var transEndEventNames = {
38
+ WebkitTransition : 'webkitTransitionEnd',
39
+ MozTransition : 'transitionend',
40
+ OTransition : 'oTransitionEnd otransitionend',
41
+ transition : 'transitionend'
42
+ }
43
+
44
+ for (var name in transEndEventNames) {
45
+ if (el.style[name] !== undefined) {
46
+ return { end: transEndEventNames[name] }
47
+ }
48
+ }
49
+
50
+ return false // explicit for ie8 ( ._.)
51
+ }
52
+
53
+ // https://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)
60
+ return this
19
61
  }
62
+
63
+ $(function () {
64
+ $.support.transition = transitionEnd()
65
+
66
+ if (!$.support.transition) return
67
+
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
+ }
75
+ })
76
+
20
77
  }(jQuery);
21
78
 
22
79
  /* ========================================================================
23
- * Bootstrap: alert.js v3.3.5
24
- * http://getbootstrap.com/javascript/#alerts
80
+ * Bootstrap: alert.js v3.4.1
81
+ * https://getbootstrap.com/docs/3.4/javascript/#alerts
25
82
  * ========================================================================
26
- * Copyright 2011-2015 Twitter, Inc.
83
+ * Copyright 2011-2019 Twitter, Inc.
27
84
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
28
85
  * ======================================================================== */
29
86
 
@@ -39,7 +96,7 @@ if (typeof jQuery === 'undefined') {
39
96
  $(el).on('click', dismiss, this.close)
40
97
  }
41
98
 
42
- Alert.VERSION = '3.3.5'
99
+ Alert.VERSION = '3.4.1'
43
100
 
44
101
  Alert.TRANSITION_DURATION = 150
45
102
 
@@ -52,7 +109,8 @@ if (typeof jQuery === 'undefined') {
52
109
  selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
53
110
  }
54
111
 
55
- var $parent = $(selector)
112
+ selector = selector === '#' ? [] : selector
113
+ var $parent = $(document).find(selector)
56
114
 
57
115
  if (e) e.preventDefault()
58
116
 
@@ -115,10 +173,10 @@ if (typeof jQuery === 'undefined') {
115
173
  }(jQuery);
116
174
 
117
175
  /* ========================================================================
118
- * Bootstrap: button.js v3.3.5
119
- * http://getbootstrap.com/javascript/#buttons
176
+ * Bootstrap: button.js v3.4.1
177
+ * https://getbootstrap.com/docs/3.4/javascript/#buttons
120
178
  * ========================================================================
121
- * Copyright 2011-2015 Twitter, Inc.
179
+ * Copyright 2011-2019 Twitter, Inc.
122
180
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
123
181
  * ======================================================================== */
124
182
 
@@ -135,7 +193,7 @@ if (typeof jQuery === 'undefined') {
135
193
  this.isLoading = false
136
194
  }
137
195
 
138
- Button.VERSION = '3.3.5'
196
+ Button.VERSION = '3.4.1'
139
197
 
140
198
  Button.DEFAULTS = {
141
199
  loadingText: 'loading...'
@@ -157,10 +215,10 @@ if (typeof jQuery === 'undefined') {
157
215
 
158
216
  if (state == 'loadingText') {
159
217
  this.isLoading = true
160
- $el.addClass(d).attr(d, d)
218
+ $el.addClass(d).attr(d, d).prop(d, true)
161
219
  } else if (this.isLoading) {
162
220
  this.isLoading = false
163
- $el.removeClass(d).removeAttr(d)
221
+ $el.removeClass(d).removeAttr(d).prop(d, false)
164
222
  }
165
223
  }, this), 0)
166
224
  }
@@ -224,10 +282,15 @@ if (typeof jQuery === 'undefined') {
224
282
 
225
283
  $(document)
226
284
  .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
227
- var $btn = $(e.target)
228
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
285
+ var $btn = $(e.target).closest('.btn')
229
286
  Plugin.call($btn, 'toggle')
230
- if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
287
+ if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
288
+ // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
289
+ e.preventDefault()
290
+ // The target component still receive the focus
291
+ if ($btn.is('input,button')) $btn.trigger('focus')
292
+ else $btn.find('input:visible,button:visible').first().trigger('focus')
293
+ }
231
294
  })
232
295
  .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
233
296
  $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
@@ -236,10 +299,10 @@ if (typeof jQuery === 'undefined') {
236
299
  }(jQuery);
237
300
 
238
301
  /* ========================================================================
239
- * Bootstrap: carousel.js v3.3.5
240
- * http://getbootstrap.com/javascript/#carousel
302
+ * Bootstrap: carousel.js v3.4.1
303
+ * https://getbootstrap.com/docs/3.4/javascript/#carousel
241
304
  * ========================================================================
242
- * Copyright 2011-2015 Twitter, Inc.
305
+ * Copyright 2011-2019 Twitter, Inc.
243
306
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
244
307
  * ======================================================================== */
245
308
 
@@ -267,7 +330,7 @@ if (typeof jQuery === 'undefined') {
267
330
  .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
268
331
  }
269
332
 
270
- Carousel.VERSION = '3.3.5'
333
+ Carousel.VERSION = '3.4.1'
271
334
 
272
335
  Carousel.TRANSITION_DURATION = 600
273
336
 
@@ -381,7 +444,9 @@ if (typeof jQuery === 'undefined') {
381
444
  var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
382
445
  if ($.support.transition && this.$element.hasClass('slide')) {
383
446
  $next.addClass(type)
384
- $next[0].offsetWidth // force reflow
447
+ if (typeof $next === 'object' && $next.length) {
448
+ $next[0].offsetWidth // force reflow
449
+ }
385
450
  $active.addClass(direction)
386
451
  $next.addClass(direction)
387
452
  $active
@@ -443,10 +508,17 @@ if (typeof jQuery === 'undefined') {
443
508
  // =================
444
509
 
445
510
  var clickHandler = function (e) {
446
- var href
447
511
  var $this = $(this)
448
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
512
+ var href = $this.attr('href')
513
+ if (href) {
514
+ href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
515
+ }
516
+
517
+ var target = $this.attr('data-target') || href
518
+ var $target = $(document).find(target)
519
+
449
520
  if (!$target.hasClass('carousel')) return
521
+
450
522
  var options = $.extend({}, $target.data(), $this.data())
451
523
  var slideIndex = $this.attr('data-slide-to')
452
524
  if (slideIndex) options.interval = false
@@ -474,139 +546,352 @@ if (typeof jQuery === 'undefined') {
474
546
  }(jQuery);
475
547
 
476
548
  /* ========================================================================
477
- * Bootstrap: dropdown.js v3.3.5
478
- * http://getbootstrap.com/javascript/#dropdowns
549
+ * Bootstrap: collapse.js v3.4.1
550
+ * https://getbootstrap.com/docs/3.4/javascript/#collapse
479
551
  * ========================================================================
480
- * Copyright 2011-2015 Twitter, Inc.
552
+ * Copyright 2011-2019 Twitter, Inc.
481
553
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
482
554
  * ======================================================================== */
483
555
 
556
+ /* jshint latedef: false */
484
557
 
485
558
  +function ($) {
486
559
  'use strict';
487
560
 
488
- // DROPDOWN CLASS DEFINITION
489
- // =========================
561
+ // COLLAPSE PUBLIC CLASS DEFINITION
562
+ // ================================
490
563
 
491
- var backdrop = '.dropdown-backdrop'
492
- var toggle = '[data-toggle="dropdown"]'
493
- var Dropdown = function (element) {
494
- $(element).on('click.bs.dropdown', this.toggle)
495
- }
564
+ var Collapse = function (element, options) {
565
+ this.$element = $(element)
566
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
567
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
568
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
569
+ this.transitioning = null
496
570
 
497
- Dropdown.VERSION = '3.3.5'
571
+ if (this.options.parent) {
572
+ this.$parent = this.getParent()
573
+ } else {
574
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
575
+ }
498
576
 
499
- function getParent($this) {
500
- var selector = $this.attr('data-target')
577
+ if (this.options.toggle) this.toggle()
578
+ }
501
579
 
502
- if (!selector) {
503
- selector = $this.attr('href')
504
- selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
505
- }
580
+ Collapse.VERSION = '3.4.1'
506
581
 
507
- var $parent = selector && $(selector)
582
+ Collapse.TRANSITION_DURATION = 350
508
583
 
509
- return $parent && $parent.length ? $parent : $this.parent()
584
+ Collapse.DEFAULTS = {
585
+ toggle: true
510
586
  }
511
587
 
512
- function clearMenus(e) {
513
- if (e && e.which === 3) return
514
- $(backdrop).remove()
515
- $(toggle).each(function () {
516
- var $this = $(this)
517
- var $parent = getParent($this)
518
- var relatedTarget = { relatedTarget: this }
588
+ Collapse.prototype.dimension = function () {
589
+ var hasWidth = this.$element.hasClass('width')
590
+ return hasWidth ? 'width' : 'height'
591
+ }
519
592
 
520
- if (!$parent.hasClass('open')) return
593
+ Collapse.prototype.show = function () {
594
+ if (this.transitioning || this.$element.hasClass('in')) return
521
595
 
522
- if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
596
+ var activesData
597
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
523
598
 
524
- $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
599
+ if (actives && actives.length) {
600
+ activesData = actives.data('bs.collapse')
601
+ if (activesData && activesData.transitioning) return
602
+ }
525
603
 
526
- if (e.isDefaultPrevented()) return
604
+ var startEvent = $.Event('show.bs.collapse')
605
+ this.$element.trigger(startEvent)
606
+ if (startEvent.isDefaultPrevented()) return
527
607
 
528
- $this.attr('aria-expanded', 'false')
529
- $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
530
- })
531
- }
608
+ if (actives && actives.length) {
609
+ Plugin.call(actives, 'hide')
610
+ activesData || actives.data('bs.collapse', null)
611
+ }
532
612
 
533
- Dropdown.prototype.toggle = function (e) {
534
- var $this = $(this)
613
+ var dimension = this.dimension()
535
614
 
536
- if ($this.is('.disabled, :disabled')) return
615
+ this.$element
616
+ .removeClass('collapse')
617
+ .addClass('collapsing')[dimension](0)
618
+ .attr('aria-expanded', true)
537
619
 
538
- var $parent = getParent($this)
539
- var isActive = $parent.hasClass('open')
620
+ this.$trigger
621
+ .removeClass('collapsed')
622
+ .attr('aria-expanded', true)
540
623
 
541
- clearMenus()
624
+ this.transitioning = 1
542
625
 
543
- if (!isActive) {
544
- if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
545
- // if mobile we use a backdrop because click events don't delegate
546
- $(document.createElement('div'))
547
- .addClass('dropdown-backdrop')
548
- .insertAfter($(this))
549
- .on('click', clearMenus)
550
- }
626
+ var complete = function () {
627
+ this.$element
628
+ .removeClass('collapsing')
629
+ .addClass('collapse in')[dimension]('')
630
+ this.transitioning = 0
631
+ this.$element
632
+ .trigger('shown.bs.collapse')
633
+ }
551
634
 
552
- var relatedTarget = { relatedTarget: this }
553
- $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
635
+ if (!$.support.transition) return complete.call(this)
554
636
 
555
- if (e.isDefaultPrevented()) return
637
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
556
638
 
557
- $this
558
- .trigger('focus')
559
- .attr('aria-expanded', 'true')
639
+ this.$element
640
+ .one('bsTransitionEnd', $.proxy(complete, this))
641
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
642
+ }
560
643
 
561
- $parent
562
- .toggleClass('open')
563
- .trigger('shown.bs.dropdown', relatedTarget)
564
- }
644
+ Collapse.prototype.hide = function () {
645
+ if (this.transitioning || !this.$element.hasClass('in')) return
565
646
 
566
- return false
567
- }
647
+ var startEvent = $.Event('hide.bs.collapse')
648
+ this.$element.trigger(startEvent)
649
+ if (startEvent.isDefaultPrevented()) return
568
650
 
569
- Dropdown.prototype.keydown = function (e) {
570
- if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
651
+ var dimension = this.dimension()
571
652
 
572
- var $this = $(this)
653
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
573
654
 
574
- e.preventDefault()
575
- e.stopPropagation()
655
+ this.$element
656
+ .addClass('collapsing')
657
+ .removeClass('collapse in')
658
+ .attr('aria-expanded', false)
576
659
 
577
- if ($this.is('.disabled, :disabled')) return
660
+ this.$trigger
661
+ .addClass('collapsed')
662
+ .attr('aria-expanded', false)
578
663
 
579
- var $parent = getParent($this)
580
- var isActive = $parent.hasClass('open')
664
+ this.transitioning = 1
581
665
 
582
- if (!isActive && e.which != 27 || isActive && e.which == 27) {
583
- if (e.which == 27) $parent.find(toggle).trigger('focus')
584
- return $this.trigger('click')
666
+ var complete = function () {
667
+ this.transitioning = 0
668
+ this.$element
669
+ .removeClass('collapsing')
670
+ .addClass('collapse')
671
+ .trigger('hidden.bs.collapse')
585
672
  }
586
673
 
587
- var desc = ' li:not(.disabled):visible a'
588
- var $items = $parent.find('.dropdown-menu' + desc)
674
+ if (!$.support.transition) return complete.call(this)
589
675
 
590
- if (!$items.length) return
676
+ this.$element
677
+ [dimension](0)
678
+ .one('bsTransitionEnd', $.proxy(complete, this))
679
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
680
+ }
591
681
 
592
- var index = $items.index(e.target)
682
+ Collapse.prototype.toggle = function () {
683
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
684
+ }
593
685
 
594
- if (e.which == 38 && index > 0) index-- // up
595
- if (e.which == 40 && index < $items.length - 1) index++ // down
596
- if (!~index) index = 0
686
+ Collapse.prototype.getParent = function () {
687
+ return $(document).find(this.options.parent)
688
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
689
+ .each($.proxy(function (i, element) {
690
+ var $element = $(element)
691
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
692
+ }, this))
693
+ .end()
694
+ }
597
695
 
598
- $items.eq(index).trigger('focus')
696
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
697
+ var isOpen = $element.hasClass('in')
698
+
699
+ $element.attr('aria-expanded', isOpen)
700
+ $trigger
701
+ .toggleClass('collapsed', !isOpen)
702
+ .attr('aria-expanded', isOpen)
703
+ }
704
+
705
+ function getTargetFromTrigger($trigger) {
706
+ var href
707
+ var target = $trigger.attr('data-target')
708
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
709
+
710
+ return $(document).find(target)
599
711
  }
600
712
 
601
713
 
602
- // DROPDOWN PLUGIN DEFINITION
714
+ // COLLAPSE PLUGIN DEFINITION
603
715
  // ==========================
604
716
 
605
717
  function Plugin(option) {
606
718
  return this.each(function () {
607
- var $this = $(this)
608
- var data = $this.data('bs.dropdown')
609
-
719
+ var $this = $(this)
720
+ var data = $this.data('bs.collapse')
721
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
722
+
723
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
724
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
725
+ if (typeof option == 'string') data[option]()
726
+ })
727
+ }
728
+
729
+ var old = $.fn.collapse
730
+
731
+ $.fn.collapse = Plugin
732
+ $.fn.collapse.Constructor = Collapse
733
+
734
+
735
+ // COLLAPSE NO CONFLICT
736
+ // ====================
737
+
738
+ $.fn.collapse.noConflict = function () {
739
+ $.fn.collapse = old
740
+ return this
741
+ }
742
+
743
+
744
+ // COLLAPSE DATA-API
745
+ // =================
746
+
747
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
748
+ var $this = $(this)
749
+
750
+ if (!$this.attr('data-target')) e.preventDefault()
751
+
752
+ var $target = getTargetFromTrigger($this)
753
+ var data = $target.data('bs.collapse')
754
+ var option = data ? 'toggle' : $this.data()
755
+
756
+ Plugin.call($target, option)
757
+ })
758
+
759
+ }(jQuery);
760
+
761
+ /* ========================================================================
762
+ * Bootstrap: dropdown.js v3.4.1
763
+ * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
764
+ * ========================================================================
765
+ * Copyright 2011-2019 Twitter, Inc.
766
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
767
+ * ======================================================================== */
768
+
769
+
770
+ +function ($) {
771
+ 'use strict';
772
+
773
+ // DROPDOWN CLASS DEFINITION
774
+ // =========================
775
+
776
+ var backdrop = '.dropdown-backdrop'
777
+ var toggle = '[data-toggle="dropdown"]'
778
+ var Dropdown = function (element) {
779
+ $(element).on('click.bs.dropdown', this.toggle)
780
+ }
781
+
782
+ Dropdown.VERSION = '3.4.1'
783
+
784
+ function getParent($this) {
785
+ var selector = $this.attr('data-target')
786
+
787
+ if (!selector) {
788
+ selector = $this.attr('href')
789
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
790
+ }
791
+
792
+ var $parent = selector !== '#' ? $(document).find(selector) : null
793
+
794
+ return $parent && $parent.length ? $parent : $this.parent()
795
+ }
796
+
797
+ function clearMenus(e) {
798
+ if (e && e.which === 3) return
799
+ $(backdrop).remove()
800
+ $(toggle).each(function () {
801
+ var $this = $(this)
802
+ var $parent = getParent($this)
803
+ var relatedTarget = { relatedTarget: this }
804
+
805
+ if (!$parent.hasClass('open')) return
806
+
807
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
808
+
809
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
810
+
811
+ if (e.isDefaultPrevented()) return
812
+
813
+ $this.attr('aria-expanded', 'false')
814
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
815
+ })
816
+ }
817
+
818
+ Dropdown.prototype.toggle = function (e) {
819
+ var $this = $(this)
820
+
821
+ if ($this.is('.disabled, :disabled')) return
822
+
823
+ var $parent = getParent($this)
824
+ var isActive = $parent.hasClass('open')
825
+
826
+ clearMenus()
827
+
828
+ if (!isActive) {
829
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
830
+ // if mobile we use a backdrop because click events don't delegate
831
+ $(document.createElement('div'))
832
+ .addClass('dropdown-backdrop')
833
+ .insertAfter($(this))
834
+ .on('click', clearMenus)
835
+ }
836
+
837
+ var relatedTarget = { relatedTarget: this }
838
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
839
+
840
+ if (e.isDefaultPrevented()) return
841
+
842
+ $this
843
+ .trigger('focus')
844
+ .attr('aria-expanded', 'true')
845
+
846
+ $parent
847
+ .toggleClass('open')
848
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
849
+ }
850
+
851
+ return false
852
+ }
853
+
854
+ Dropdown.prototype.keydown = function (e) {
855
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
856
+
857
+ var $this = $(this)
858
+
859
+ e.preventDefault()
860
+ e.stopPropagation()
861
+
862
+ if ($this.is('.disabled, :disabled')) return
863
+
864
+ var $parent = getParent($this)
865
+ var isActive = $parent.hasClass('open')
866
+
867
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
868
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
869
+ return $this.trigger('click')
870
+ }
871
+
872
+ var desc = ' li:not(.disabled):visible a'
873
+ var $items = $parent.find('.dropdown-menu' + desc)
874
+
875
+ if (!$items.length) return
876
+
877
+ var index = $items.index(e.target)
878
+
879
+ if (e.which == 38 && index > 0) index-- // up
880
+ if (e.which == 40 && index < $items.length - 1) index++ // down
881
+ if (!~index) index = 0
882
+
883
+ $items.eq(index).trigger('focus')
884
+ }
885
+
886
+
887
+ // DROPDOWN PLUGIN DEFINITION
888
+ // ==========================
889
+
890
+ function Plugin(option) {
891
+ return this.each(function () {
892
+ var $this = $(this)
893
+ var data = $this.data('bs.dropdown')
894
+
610
895
  if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
611
896
  if (typeof option == 'string') data[option].call($this)
612
897
  })
@@ -640,10 +925,10 @@ if (typeof jQuery === 'undefined') {
640
925
  }(jQuery);
641
926
 
642
927
  /* ========================================================================
643
- * Bootstrap: modal.js v3.3.5
644
- * http://getbootstrap.com/javascript/#modals
928
+ * Bootstrap: modal.js v3.4.1
929
+ * https://getbootstrap.com/docs/3.4/javascript/#modals
645
930
  * ========================================================================
646
- * Copyright 2011-2015 Twitter, Inc.
931
+ * Copyright 2011-2019 Twitter, Inc.
647
932
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
648
933
  * ======================================================================== */
649
934
 
@@ -655,15 +940,16 @@ if (typeof jQuery === 'undefined') {
655
940
  // ======================
656
941
 
657
942
  var Modal = function (element, options) {
658
- this.options = options
659
- this.$body = $(document.body)
660
- this.$element = $(element)
661
- this.$dialog = this.$element.find('.modal-dialog')
662
- this.$backdrop = null
663
- this.isShown = null
664
- this.originalBodyPad = null
665
- this.scrollbarWidth = 0
943
+ this.options = options
944
+ this.$body = $(document.body)
945
+ this.$element = $(element)
946
+ this.$dialog = this.$element.find('.modal-dialog')
947
+ this.$backdrop = null
948
+ this.isShown = null
949
+ this.originalBodyPad = null
950
+ this.scrollbarWidth = 0
666
951
  this.ignoreBackdropClick = false
952
+ this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
667
953
 
668
954
  if (this.options.remote) {
669
955
  this.$element
@@ -674,7 +960,7 @@ if (typeof jQuery === 'undefined') {
674
960
  }
675
961
  }
676
962
 
677
- Modal.VERSION = '3.3.5'
963
+ Modal.VERSION = '3.4.1'
678
964
 
679
965
  Modal.TRANSITION_DURATION = 300
680
966
  Modal.BACKDROP_TRANSITION_DURATION = 150
@@ -691,7 +977,7 @@ if (typeof jQuery === 'undefined') {
691
977
 
692
978
  Modal.prototype.show = function (_relatedTarget) {
693
979
  var that = this
694
- var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
980
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
695
981
 
696
982
  this.$element.trigger(e)
697
983
 
@@ -781,7 +1067,9 @@ if (typeof jQuery === 'undefined') {
781
1067
  $(document)
782
1068
  .off('focusin.bs.modal') // guard against infinite focus loop
783
1069
  .on('focusin.bs.modal', $.proxy(function (e) {
784
- if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
1070
+ if (document !== e.target &&
1071
+ this.$element[0] !== e.target &&
1072
+ !this.$element.has(e.target).length) {
785
1073
  this.$element.trigger('focus')
786
1074
  }
787
1075
  }, this))
@@ -883,7 +1171,7 @@ if (typeof jQuery === 'undefined') {
883
1171
  var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
884
1172
 
885
1173
  this.$element.css({
886
- paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1174
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
887
1175
  paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
888
1176
  })
889
1177
  }
@@ -908,11 +1196,26 @@ if (typeof jQuery === 'undefined') {
908
1196
  Modal.prototype.setScrollbar = function () {
909
1197
  var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
910
1198
  this.originalBodyPad = document.body.style.paddingRight || ''
911
- if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1199
+ var scrollbarWidth = this.scrollbarWidth
1200
+ if (this.bodyIsOverflowing) {
1201
+ this.$body.css('padding-right', bodyPad + scrollbarWidth)
1202
+ $(this.fixedContent).each(function (index, element) {
1203
+ var actualPadding = element.style.paddingRight
1204
+ var calculatedPadding = $(element).css('padding-right')
1205
+ $(element)
1206
+ .data('padding-right', actualPadding)
1207
+ .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
1208
+ })
1209
+ }
912
1210
  }
913
1211
 
914
1212
  Modal.prototype.resetScrollbar = function () {
915
1213
  this.$body.css('padding-right', this.originalBodyPad)
1214
+ $(this.fixedContent).each(function (index, element) {
1215
+ var padding = $(element).data('padding-right')
1216
+ $(element).removeData('padding-right')
1217
+ element.style.paddingRight = padding ? padding : ''
1218
+ })
916
1219
  }
917
1220
 
918
1221
  Modal.prototype.measureScrollbar = function () { // thx walsh
@@ -930,8 +1233,8 @@ if (typeof jQuery === 'undefined') {
930
1233
 
931
1234
  function Plugin(option, _relatedTarget) {
932
1235
  return this.each(function () {
933
- var $this = $(this)
934
- var data = $this.data('bs.modal')
1236
+ var $this = $(this)
1237
+ var data = $this.data('bs.modal')
935
1238
  var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
936
1239
 
937
1240
  if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
@@ -942,7 +1245,7 @@ if (typeof jQuery === 'undefined') {
942
1245
 
943
1246
  var old = $.fn.modal
944
1247
 
945
- $.fn.modal = Plugin
1248
+ $.fn.modal = Plugin
946
1249
  $.fn.modal.Constructor = Modal
947
1250
 
948
1251
 
@@ -959,10 +1262,13 @@ if (typeof jQuery === 'undefined') {
959
1262
  // ==============
960
1263
 
961
1264
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
962
- var $this = $(this)
963
- var href = $this.attr('href')
964
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
965
- var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1265
+ var $this = $(this)
1266
+ var href = $this.attr('href')
1267
+ var target = $this.attr('data-target') ||
1268
+ (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
1269
+
1270
+ var $target = $(document).find(target)
1271
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
966
1272
 
967
1273
  if ($this.is('a')) e.preventDefault()
968
1274
 
@@ -978,18 +1284,148 @@ if (typeof jQuery === 'undefined') {
978
1284
  }(jQuery);
979
1285
 
980
1286
  /* ========================================================================
981
- * Bootstrap: tooltip.js v3.3.5
982
- * http://getbootstrap.com/javascript/#tooltip
1287
+ * Bootstrap: tooltip.js v3.4.1
1288
+ * https://getbootstrap.com/docs/3.4/javascript/#tooltip
983
1289
  * Inspired by the original jQuery.tipsy by Jason Frame
984
1290
  * ========================================================================
985
- * Copyright 2011-2015 Twitter, Inc.
1291
+ * Copyright 2011-2019 Twitter, Inc.
986
1292
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
987
1293
  * ======================================================================== */
988
1294
 
989
-
990
1295
  +function ($) {
991
1296
  'use strict';
992
1297
 
1298
+ var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
1299
+
1300
+ var uriAttrs = [
1301
+ 'background',
1302
+ 'cite',
1303
+ 'href',
1304
+ 'itemtype',
1305
+ 'longdesc',
1306
+ 'poster',
1307
+ 'src',
1308
+ 'xlink:href'
1309
+ ]
1310
+
1311
+ var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
1312
+
1313
+ var DefaultWhitelist = {
1314
+ // Global attributes allowed on any supplied element below.
1315
+ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
1316
+ a: ['target', 'href', 'title', 'rel'],
1317
+ area: [],
1318
+ b: [],
1319
+ br: [],
1320
+ col: [],
1321
+ code: [],
1322
+ div: [],
1323
+ em: [],
1324
+ hr: [],
1325
+ h1: [],
1326
+ h2: [],
1327
+ h3: [],
1328
+ h4: [],
1329
+ h5: [],
1330
+ h6: [],
1331
+ i: [],
1332
+ img: ['src', 'alt', 'title', 'width', 'height'],
1333
+ li: [],
1334
+ ol: [],
1335
+ p: [],
1336
+ pre: [],
1337
+ s: [],
1338
+ small: [],
1339
+ span: [],
1340
+ sub: [],
1341
+ sup: [],
1342
+ strong: [],
1343
+ u: [],
1344
+ ul: []
1345
+ }
1346
+
1347
+ /**
1348
+ * A pattern that recognizes a commonly useful subset of URLs that are safe.
1349
+ *
1350
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
1351
+ */
1352
+ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
1353
+
1354
+ /**
1355
+ * A pattern that matches safe data URLs. Only matches image, video and audio types.
1356
+ *
1357
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
1358
+ */
1359
+ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
1360
+
1361
+ function allowedAttribute(attr, allowedAttributeList) {
1362
+ var attrName = attr.nodeName.toLowerCase()
1363
+
1364
+ if ($.inArray(attrName, allowedAttributeList) !== -1) {
1365
+ if ($.inArray(attrName, uriAttrs) !== -1) {
1366
+ return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
1367
+ }
1368
+
1369
+ return true
1370
+ }
1371
+
1372
+ var regExp = $(allowedAttributeList).filter(function (index, value) {
1373
+ return value instanceof RegExp
1374
+ })
1375
+
1376
+ // Check if a regular expression validates the attribute.
1377
+ for (var i = 0, l = regExp.length; i < l; i++) {
1378
+ if (attrName.match(regExp[i])) {
1379
+ return true
1380
+ }
1381
+ }
1382
+
1383
+ return false
1384
+ }
1385
+
1386
+ function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
1387
+ if (unsafeHtml.length === 0) {
1388
+ return unsafeHtml
1389
+ }
1390
+
1391
+ if (sanitizeFn && typeof sanitizeFn === 'function') {
1392
+ return sanitizeFn(unsafeHtml)
1393
+ }
1394
+
1395
+ // IE 8 and below don't support createHTMLDocument
1396
+ if (!document.implementation || !document.implementation.createHTMLDocument) {
1397
+ return unsafeHtml
1398
+ }
1399
+
1400
+ var createdDocument = document.implementation.createHTMLDocument('sanitization')
1401
+ createdDocument.body.innerHTML = unsafeHtml
1402
+
1403
+ var whitelistKeys = $.map(whiteList, function (el, i) { return i })
1404
+ var elements = $(createdDocument.body).find('*')
1405
+
1406
+ for (var i = 0, len = elements.length; i < len; i++) {
1407
+ var el = elements[i]
1408
+ var elName = el.nodeName.toLowerCase()
1409
+
1410
+ if ($.inArray(elName, whitelistKeys) === -1) {
1411
+ el.parentNode.removeChild(el)
1412
+
1413
+ continue
1414
+ }
1415
+
1416
+ var attributeList = $.map(el.attributes, function (el) { return el })
1417
+ var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
1418
+
1419
+ for (var j = 0, len2 = attributeList.length; j < len2; j++) {
1420
+ if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
1421
+ el.removeAttribute(attributeList[j].nodeName)
1422
+ }
1423
+ }
1424
+ }
1425
+
1426
+ return createdDocument.body.innerHTML
1427
+ }
1428
+
993
1429
  // TOOLTIP PUBLIC CLASS DEFINITION
994
1430
  // ===============================
995
1431
 
@@ -1005,7 +1441,7 @@ if (typeof jQuery === 'undefined') {
1005
1441
  this.init('tooltip', element, options)
1006
1442
  }
1007
1443
 
1008
- Tooltip.VERSION = '3.3.5'
1444
+ Tooltip.VERSION = '3.4.1'
1009
1445
 
1010
1446
  Tooltip.TRANSITION_DURATION = 150
1011
1447
 
@@ -1022,7 +1458,10 @@ if (typeof jQuery === 'undefined') {
1022
1458
  viewport: {
1023
1459
  selector: 'body',
1024
1460
  padding: 0
1025
- }
1461
+ },
1462
+ sanitize : true,
1463
+ sanitizeFn : null,
1464
+ whiteList : DefaultWhitelist
1026
1465
  }
1027
1466
 
1028
1467
  Tooltip.prototype.init = function (type, element, options) {
@@ -1030,7 +1469,7 @@ if (typeof jQuery === 'undefined') {
1030
1469
  this.type = type
1031
1470
  this.$element = $(element)
1032
1471
  this.options = this.getOptions(options)
1033
- this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1472
+ this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1034
1473
  this.inState = { click: false, hover: false, focus: false }
1035
1474
 
1036
1475
  if (this.$element[0] instanceof document.constructor && !this.options.selector) {
@@ -1063,7 +1502,15 @@ if (typeof jQuery === 'undefined') {
1063
1502
  }
1064
1503
 
1065
1504
  Tooltip.prototype.getOptions = function (options) {
1066
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1505
+ var dataAttributes = this.$element.data()
1506
+
1507
+ for (var dataAttr in dataAttributes) {
1508
+ if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
1509
+ delete dataAttributes[dataAttr]
1510
+ }
1511
+ }
1512
+
1513
+ options = $.extend({}, this.getDefaults(), dataAttributes, options)
1067
1514
 
1068
1515
  if (options.delay && typeof options.delay == 'number') {
1069
1516
  options.delay = {
@@ -1072,6 +1519,10 @@ if (typeof jQuery === 'undefined') {
1072
1519
  }
1073
1520
  }
1074
1521
 
1522
+ if (options.sanitize) {
1523
+ options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
1524
+ }
1525
+
1075
1526
  return options
1076
1527
  }
1077
1528
 
@@ -1183,7 +1634,7 @@ if (typeof jQuery === 'undefined') {
1183
1634
  .addClass(placement)
1184
1635
  .data('bs.' + this.type, this)
1185
1636
 
1186
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1637
+ this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
1187
1638
  this.$element.trigger('inserted.bs.' + this.type)
1188
1639
 
1189
1640
  var pos = this.getPosition()
@@ -1285,7 +1736,16 @@ if (typeof jQuery === 'undefined') {
1285
1736
  var $tip = this.tip()
1286
1737
  var title = this.getTitle()
1287
1738
 
1288
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1739
+ if (this.options.html) {
1740
+ if (this.options.sanitize) {
1741
+ title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
1742
+ }
1743
+
1744
+ $tip.find('.tooltip-inner').html(title)
1745
+ } else {
1746
+ $tip.find('.tooltip-inner').text(title)
1747
+ }
1748
+
1289
1749
  $tip.removeClass('fade in top bottom left right')
1290
1750
  }
1291
1751
 
@@ -1296,9 +1756,11 @@ if (typeof jQuery === 'undefined') {
1296
1756
 
1297
1757
  function complete() {
1298
1758
  if (that.hoverState != 'in') $tip.detach()
1299
- that.$element
1300
- .removeAttr('aria-describedby')
1301
- .trigger('hidden.bs.' + that.type)
1759
+ if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
1760
+ that.$element
1761
+ .removeAttr('aria-describedby')
1762
+ .trigger('hidden.bs.' + that.type)
1763
+ }
1302
1764
  callback && callback()
1303
1765
  }
1304
1766
 
@@ -1341,7 +1803,10 @@ if (typeof jQuery === 'undefined') {
1341
1803
  // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1342
1804
  elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1343
1805
  }
1344
- var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1806
+ var isSvg = window.SVGElement && el instanceof window.SVGElement
1807
+ // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
1808
+ // See https://github.com/twbs/bootstrap/issues/20280
1809
+ var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
1345
1810
  var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1346
1811
  var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1347
1812
 
@@ -1457,9 +1922,13 @@ if (typeof jQuery === 'undefined') {
1457
1922
  that.$tip = null
1458
1923
  that.$arrow = null
1459
1924
  that.$viewport = null
1925
+ that.$element = null
1460
1926
  })
1461
1927
  }
1462
1928
 
1929
+ Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
1930
+ return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
1931
+ }
1463
1932
 
1464
1933
  // TOOLTIP PLUGIN DEFINITION
1465
1934
  // =========================
@@ -1493,10 +1962,10 @@ if (typeof jQuery === 'undefined') {
1493
1962
  }(jQuery);
1494
1963
 
1495
1964
  /* ========================================================================
1496
- * Bootstrap: popover.js v3.3.5
1497
- * http://getbootstrap.com/javascript/#popovers
1965
+ * Bootstrap: popover.js v3.4.1
1966
+ * https://getbootstrap.com/docs/3.4/javascript/#popovers
1498
1967
  * ========================================================================
1499
- * Copyright 2011-2015 Twitter, Inc.
1968
+ * Copyright 2011-2019 Twitter, Inc.
1500
1969
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1501
1970
  * ======================================================================== */
1502
1971
 
@@ -1513,7 +1982,7 @@ if (typeof jQuery === 'undefined') {
1513
1982
 
1514
1983
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1515
1984
 
1516
- Popover.VERSION = '3.3.5'
1985
+ Popover.VERSION = '3.4.1'
1517
1986
 
1518
1987
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1519
1988
  placement: 'right',
@@ -1539,10 +2008,25 @@ if (typeof jQuery === 'undefined') {
1539
2008
  var title = this.getTitle()
1540
2009
  var content = this.getContent()
1541
2010
 
1542
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1543
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1544
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1545
- ](content)
2011
+ if (this.options.html) {
2012
+ var typeContent = typeof content
2013
+
2014
+ if (this.options.sanitize) {
2015
+ title = this.sanitizeHtml(title)
2016
+
2017
+ if (typeContent === 'string') {
2018
+ content = this.sanitizeHtml(content)
2019
+ }
2020
+ }
2021
+
2022
+ $tip.find('.popover-title').html(title)
2023
+ $tip.find('.popover-content').children().detach().end()[
2024
+ typeContent === 'string' ? 'html' : 'append'
2025
+ ](content)
2026
+ } else {
2027
+ $tip.find('.popover-title').text(title)
2028
+ $tip.find('.popover-content').children().detach().end().text(content)
2029
+ }
1546
2030
 
1547
2031
  $tip.removeClass('fade top bottom left right in')
1548
2032
 
@@ -1561,8 +2045,8 @@ if (typeof jQuery === 'undefined') {
1561
2045
 
1562
2046
  return $e.attr('data-content')
1563
2047
  || (typeof o.content == 'function' ?
1564
- o.content.call($e[0]) :
1565
- o.content)
2048
+ o.content.call($e[0]) :
2049
+ o.content)
1566
2050
  }
1567
2051
 
1568
2052
  Popover.prototype.arrow = function () {
@@ -1602,10 +2086,10 @@ if (typeof jQuery === 'undefined') {
1602
2086
  }(jQuery);
1603
2087
 
1604
2088
  /* ========================================================================
1605
- * Bootstrap: tab.js v3.3.5
1606
- * http://getbootstrap.com/javascript/#tabs
2089
+ * Bootstrap: scrollspy.js v3.4.1
2090
+ * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
1607
2091
  * ========================================================================
1608
- * Copyright 2011-2015 Twitter, Inc.
2092
+ * Copyright 2011-2019 Twitter, Inc.
1609
2093
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1610
2094
  * ======================================================================== */
1611
2095
 
@@ -1613,18 +2097,191 @@ if (typeof jQuery === 'undefined') {
1613
2097
  +function ($) {
1614
2098
  'use strict';
1615
2099
 
1616
- // TAB CLASS DEFINITION
1617
- // ====================
2100
+ // SCROLLSPY CLASS DEFINITION
2101
+ // ==========================
1618
2102
 
1619
- var Tab = function (element) {
1620
- // jscs:disable requireDollarBeforejQueryAssignment
1621
- this.element = $(element)
1622
- // jscs:enable requireDollarBeforejQueryAssignment
1623
- }
2103
+ function ScrollSpy(element, options) {
2104
+ this.$body = $(document.body)
2105
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
2106
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
2107
+ this.selector = (this.options.target || '') + ' .nav li > a'
2108
+ this.offsets = []
2109
+ this.targets = []
2110
+ this.activeTarget = null
2111
+ this.scrollHeight = 0
1624
2112
 
1625
- Tab.VERSION = '3.3.5'
2113
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
2114
+ this.refresh()
2115
+ this.process()
2116
+ }
1626
2117
 
1627
- Tab.TRANSITION_DURATION = 150
2118
+ ScrollSpy.VERSION = '3.4.1'
2119
+
2120
+ ScrollSpy.DEFAULTS = {
2121
+ offset: 10
2122
+ }
2123
+
2124
+ ScrollSpy.prototype.getScrollHeight = function () {
2125
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
2126
+ }
2127
+
2128
+ ScrollSpy.prototype.refresh = function () {
2129
+ var that = this
2130
+ var offsetMethod = 'offset'
2131
+ var offsetBase = 0
2132
+
2133
+ this.offsets = []
2134
+ this.targets = []
2135
+ this.scrollHeight = this.getScrollHeight()
2136
+
2137
+ if (!$.isWindow(this.$scrollElement[0])) {
2138
+ offsetMethod = 'position'
2139
+ offsetBase = this.$scrollElement.scrollTop()
2140
+ }
2141
+
2142
+ this.$body
2143
+ .find(this.selector)
2144
+ .map(function () {
2145
+ var $el = $(this)
2146
+ var href = $el.data('target') || $el.attr('href')
2147
+ var $href = /^#./.test(href) && $(href)
2148
+
2149
+ return ($href
2150
+ && $href.length
2151
+ && $href.is(':visible')
2152
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
2153
+ })
2154
+ .sort(function (a, b) { return a[0] - b[0] })
2155
+ .each(function () {
2156
+ that.offsets.push(this[0])
2157
+ that.targets.push(this[1])
2158
+ })
2159
+ }
2160
+
2161
+ ScrollSpy.prototype.process = function () {
2162
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
2163
+ var scrollHeight = this.getScrollHeight()
2164
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
2165
+ var offsets = this.offsets
2166
+ var targets = this.targets
2167
+ var activeTarget = this.activeTarget
2168
+ var i
2169
+
2170
+ if (this.scrollHeight != scrollHeight) {
2171
+ this.refresh()
2172
+ }
2173
+
2174
+ if (scrollTop >= maxScroll) {
2175
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
2176
+ }
2177
+
2178
+ if (activeTarget && scrollTop < offsets[0]) {
2179
+ this.activeTarget = null
2180
+ return this.clear()
2181
+ }
2182
+
2183
+ for (i = offsets.length; i--;) {
2184
+ activeTarget != targets[i]
2185
+ && scrollTop >= offsets[i]
2186
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
2187
+ && this.activate(targets[i])
2188
+ }
2189
+ }
2190
+
2191
+ ScrollSpy.prototype.activate = function (target) {
2192
+ this.activeTarget = target
2193
+
2194
+ this.clear()
2195
+
2196
+ var selector = this.selector +
2197
+ '[data-target="' + target + '"],' +
2198
+ this.selector + '[href="' + target + '"]'
2199
+
2200
+ var active = $(selector)
2201
+ .parents('li')
2202
+ .addClass('active')
2203
+
2204
+ if (active.parent('.dropdown-menu').length) {
2205
+ active = active
2206
+ .closest('li.dropdown')
2207
+ .addClass('active')
2208
+ }
2209
+
2210
+ active.trigger('activate.bs.scrollspy')
2211
+ }
2212
+
2213
+ ScrollSpy.prototype.clear = function () {
2214
+ $(this.selector)
2215
+ .parentsUntil(this.options.target, '.active')
2216
+ .removeClass('active')
2217
+ }
2218
+
2219
+
2220
+ // SCROLLSPY PLUGIN DEFINITION
2221
+ // ===========================
2222
+
2223
+ function Plugin(option) {
2224
+ return this.each(function () {
2225
+ var $this = $(this)
2226
+ var data = $this.data('bs.scrollspy')
2227
+ var options = typeof option == 'object' && option
2228
+
2229
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
2230
+ if (typeof option == 'string') data[option]()
2231
+ })
2232
+ }
2233
+
2234
+ var old = $.fn.scrollspy
2235
+
2236
+ $.fn.scrollspy = Plugin
2237
+ $.fn.scrollspy.Constructor = ScrollSpy
2238
+
2239
+
2240
+ // SCROLLSPY NO CONFLICT
2241
+ // =====================
2242
+
2243
+ $.fn.scrollspy.noConflict = function () {
2244
+ $.fn.scrollspy = old
2245
+ return this
2246
+ }
2247
+
2248
+
2249
+ // SCROLLSPY DATA-API
2250
+ // ==================
2251
+
2252
+ $(window).on('load.bs.scrollspy.data-api', function () {
2253
+ $('[data-spy="scroll"]').each(function () {
2254
+ var $spy = $(this)
2255
+ Plugin.call($spy, $spy.data())
2256
+ })
2257
+ })
2258
+
2259
+ }(jQuery);
2260
+
2261
+ /* ========================================================================
2262
+ * Bootstrap: tab.js v3.4.1
2263
+ * https://getbootstrap.com/docs/3.4/javascript/#tabs
2264
+ * ========================================================================
2265
+ * Copyright 2011-2019 Twitter, Inc.
2266
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2267
+ * ======================================================================== */
2268
+
2269
+
2270
+ +function ($) {
2271
+ 'use strict';
2272
+
2273
+ // TAB CLASS DEFINITION
2274
+ // ====================
2275
+
2276
+ var Tab = function (element) {
2277
+ // jscs:disable requireDollarBeforejQueryAssignment
2278
+ this.element = $(element)
2279
+ // jscs:enable requireDollarBeforejQueryAssignment
2280
+ }
2281
+
2282
+ Tab.VERSION = '3.4.1'
2283
+
2284
+ Tab.TRANSITION_DURATION = 150
1628
2285
 
1629
2286
  Tab.prototype.show = function () {
1630
2287
  var $this = this.element
@@ -1651,7 +2308,7 @@ if (typeof jQuery === 'undefined') {
1651
2308
 
1652
2309
  if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
1653
2310
 
1654
- var $target = $(selector)
2311
+ var $target = $(document).find(selector)
1655
2312
 
1656
2313
  this.activate($this.closest('li'), $ul)
1657
2314
  this.activate($target, $target.parent(), function () {
@@ -1676,15 +2333,15 @@ if (typeof jQuery === 'undefined') {
1676
2333
  $active
1677
2334
  .removeClass('active')
1678
2335
  .find('> .dropdown-menu > .active')
1679
- .removeClass('active')
2336
+ .removeClass('active')
1680
2337
  .end()
1681
2338
  .find('[data-toggle="tab"]')
1682
- .attr('aria-expanded', false)
2339
+ .attr('aria-expanded', false)
1683
2340
 
1684
2341
  element
1685
2342
  .addClass('active')
1686
2343
  .find('[data-toggle="tab"]')
1687
- .attr('aria-expanded', true)
2344
+ .attr('aria-expanded', true)
1688
2345
 
1689
2346
  if (transition) {
1690
2347
  element[0].offsetWidth // reflow for transition
@@ -1696,10 +2353,10 @@ if (typeof jQuery === 'undefined') {
1696
2353
  if (element.parent('.dropdown-menu').length) {
1697
2354
  element
1698
2355
  .closest('li.dropdown')
1699
- .addClass('active')
2356
+ .addClass('active')
1700
2357
  .end()
1701
2358
  .find('[data-toggle="tab"]')
1702
- .attr('aria-expanded', true)
2359
+ .attr('aria-expanded', true)
1703
2360
  }
1704
2361
 
1705
2362
  callback && callback()
@@ -1758,10 +2415,10 @@ if (typeof jQuery === 'undefined') {
1758
2415
  }(jQuery);
1759
2416
 
1760
2417
  /* ========================================================================
1761
- * Bootstrap: affix.js v3.3.5
1762
- * http://getbootstrap.com/javascript/#affix
2418
+ * Bootstrap: affix.js v3.4.1
2419
+ * https://getbootstrap.com/docs/3.4/javascript/#affix
1763
2420
  * ========================================================================
1764
- * Copyright 2011-2015 Twitter, Inc.
2421
+ * Copyright 2011-2019 Twitter, Inc.
1765
2422
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1766
2423
  * ======================================================================== */
1767
2424
 
@@ -1775,7 +2432,9 @@ if (typeof jQuery === 'undefined') {
1775
2432
  var Affix = function (element, options) {
1776
2433
  this.options = $.extend({}, Affix.DEFAULTS, options)
1777
2434
 
1778
- this.$target = $(this.options.target)
2435
+ var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
2436
+
2437
+ this.$target = target
1779
2438
  .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
1780
2439
  .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1781
2440
 
@@ -1787,7 +2446,7 @@ if (typeof jQuery === 'undefined') {
1787
2446
  this.checkPosition()
1788
2447
  }
1789
2448
 
1790
- Affix.VERSION = '3.3.5'
2449
+ Affix.VERSION = '3.4.1'
1791
2450
 
1792
2451
  Affix.RESET = 'affix affix-top affix-bottom'
1793
2452
 
@@ -1919,448 +2578,3 @@ if (typeof jQuery === 'undefined') {
1919
2578
  })
1920
2579
 
1921
2580
  }(jQuery);
1922
-
1923
- /* ========================================================================
1924
- * Bootstrap: collapse.js v3.3.5
1925
- * http://getbootstrap.com/javascript/#collapse
1926
- * ========================================================================
1927
- * Copyright 2011-2015 Twitter, Inc.
1928
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1929
- * ======================================================================== */
1930
-
1931
-
1932
- +function ($) {
1933
- 'use strict';
1934
-
1935
- // COLLAPSE PUBLIC CLASS DEFINITION
1936
- // ================================
1937
-
1938
- var Collapse = function (element, options) {
1939
- this.$element = $(element)
1940
- this.options = $.extend({}, Collapse.DEFAULTS, options)
1941
- this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
1942
- '[data-toggle="collapse"][data-target="#' + element.id + '"]')
1943
- this.transitioning = null
1944
-
1945
- if (this.options.parent) {
1946
- this.$parent = this.getParent()
1947
- } else {
1948
- this.addAriaAndCollapsedClass(this.$element, this.$trigger)
1949
- }
1950
-
1951
- if (this.options.toggle) this.toggle()
1952
- }
1953
-
1954
- Collapse.VERSION = '3.3.5'
1955
-
1956
- Collapse.TRANSITION_DURATION = 350
1957
-
1958
- Collapse.DEFAULTS = {
1959
- toggle: true
1960
- }
1961
-
1962
- Collapse.prototype.dimension = function () {
1963
- var hasWidth = this.$element.hasClass('width')
1964
- return hasWidth ? 'width' : 'height'
1965
- }
1966
-
1967
- Collapse.prototype.show = function () {
1968
- if (this.transitioning || this.$element.hasClass('in')) return
1969
-
1970
- var activesData
1971
- var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
1972
-
1973
- if (actives && actives.length) {
1974
- activesData = actives.data('bs.collapse')
1975
- if (activesData && activesData.transitioning) return
1976
- }
1977
-
1978
- var startEvent = $.Event('show.bs.collapse')
1979
- this.$element.trigger(startEvent)
1980
- if (startEvent.isDefaultPrevented()) return
1981
-
1982
- if (actives && actives.length) {
1983
- Plugin.call(actives, 'hide')
1984
- activesData || actives.data('bs.collapse', null)
1985
- }
1986
-
1987
- var dimension = this.dimension()
1988
-
1989
- this.$element
1990
- .removeClass('collapse')
1991
- .addClass('collapsing')[dimension](0)
1992
- .attr('aria-expanded', true)
1993
-
1994
- this.$trigger
1995
- .removeClass('collapsed')
1996
- .attr('aria-expanded', true)
1997
-
1998
- this.transitioning = 1
1999
-
2000
- var complete = function () {
2001
- this.$element
2002
- .removeClass('collapsing')
2003
- .addClass('collapse in')[dimension]('')
2004
- this.transitioning = 0
2005
- this.$element
2006
- .trigger('shown.bs.collapse')
2007
- }
2008
-
2009
- if (!$.support.transition) return complete.call(this)
2010
-
2011
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
2012
-
2013
- this.$element
2014
- .one('bsTransitionEnd', $.proxy(complete, this))
2015
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
2016
- }
2017
-
2018
- Collapse.prototype.hide = function () {
2019
- if (this.transitioning || !this.$element.hasClass('in')) return
2020
-
2021
- var startEvent = $.Event('hide.bs.collapse')
2022
- this.$element.trigger(startEvent)
2023
- if (startEvent.isDefaultPrevented()) return
2024
-
2025
- var dimension = this.dimension()
2026
-
2027
- this.$element[dimension](this.$element[dimension]())[0].offsetHeight
2028
-
2029
- this.$element
2030
- .addClass('collapsing')
2031
- .removeClass('collapse in')
2032
- .attr('aria-expanded', false)
2033
-
2034
- this.$trigger
2035
- .addClass('collapsed')
2036
- .attr('aria-expanded', false)
2037
-
2038
- this.transitioning = 1
2039
-
2040
- var complete = function () {
2041
- this.transitioning = 0
2042
- this.$element
2043
- .removeClass('collapsing')
2044
- .addClass('collapse')
2045
- .trigger('hidden.bs.collapse')
2046
- }
2047
-
2048
- if (!$.support.transition) return complete.call(this)
2049
-
2050
- this.$element
2051
- [dimension](0)
2052
- .one('bsTransitionEnd', $.proxy(complete, this))
2053
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
2054
- }
2055
-
2056
- Collapse.prototype.toggle = function () {
2057
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
2058
- }
2059
-
2060
- Collapse.prototype.getParent = function () {
2061
- return $(this.options.parent)
2062
- .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
2063
- .each($.proxy(function (i, element) {
2064
- var $element = $(element)
2065
- this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
2066
- }, this))
2067
- .end()
2068
- }
2069
-
2070
- Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
2071
- var isOpen = $element.hasClass('in')
2072
-
2073
- $element.attr('aria-expanded', isOpen)
2074
- $trigger
2075
- .toggleClass('collapsed', !isOpen)
2076
- .attr('aria-expanded', isOpen)
2077
- }
2078
-
2079
- function getTargetFromTrigger($trigger) {
2080
- var href
2081
- var target = $trigger.attr('data-target')
2082
- || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
2083
-
2084
- return $(target)
2085
- }
2086
-
2087
-
2088
- // COLLAPSE PLUGIN DEFINITION
2089
- // ==========================
2090
-
2091
- function Plugin(option) {
2092
- return this.each(function () {
2093
- var $this = $(this)
2094
- var data = $this.data('bs.collapse')
2095
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
2096
-
2097
- if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
2098
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
2099
- if (typeof option == 'string') data[option]()
2100
- })
2101
- }
2102
-
2103
- var old = $.fn.collapse
2104
-
2105
- $.fn.collapse = Plugin
2106
- $.fn.collapse.Constructor = Collapse
2107
-
2108
-
2109
- // COLLAPSE NO CONFLICT
2110
- // ====================
2111
-
2112
- $.fn.collapse.noConflict = function () {
2113
- $.fn.collapse = old
2114
- return this
2115
- }
2116
-
2117
-
2118
- // COLLAPSE DATA-API
2119
- // =================
2120
-
2121
- $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
2122
- var $this = $(this)
2123
-
2124
- if (!$this.attr('data-target')) e.preventDefault()
2125
-
2126
- var $target = getTargetFromTrigger($this)
2127
- var data = $target.data('bs.collapse')
2128
- var option = data ? 'toggle' : $this.data()
2129
-
2130
- Plugin.call($target, option)
2131
- })
2132
-
2133
- }(jQuery);
2134
-
2135
- /* ========================================================================
2136
- * Bootstrap: scrollspy.js v3.3.5
2137
- * http://getbootstrap.com/javascript/#scrollspy
2138
- * ========================================================================
2139
- * Copyright 2011-2015 Twitter, Inc.
2140
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2141
- * ======================================================================== */
2142
-
2143
-
2144
- +function ($) {
2145
- 'use strict';
2146
-
2147
- // SCROLLSPY CLASS DEFINITION
2148
- // ==========================
2149
-
2150
- function ScrollSpy(element, options) {
2151
- this.$body = $(document.body)
2152
- this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
2153
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
2154
- this.selector = (this.options.target || '') + ' .nav li > a'
2155
- this.offsets = []
2156
- this.targets = []
2157
- this.activeTarget = null
2158
- this.scrollHeight = 0
2159
-
2160
- this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
2161
- this.refresh()
2162
- this.process()
2163
- }
2164
-
2165
- ScrollSpy.VERSION = '3.3.5'
2166
-
2167
- ScrollSpy.DEFAULTS = {
2168
- offset: 10
2169
- }
2170
-
2171
- ScrollSpy.prototype.getScrollHeight = function () {
2172
- return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
2173
- }
2174
-
2175
- ScrollSpy.prototype.refresh = function () {
2176
- var that = this
2177
- var offsetMethod = 'offset'
2178
- var offsetBase = 0
2179
-
2180
- this.offsets = []
2181
- this.targets = []
2182
- this.scrollHeight = this.getScrollHeight()
2183
-
2184
- if (!$.isWindow(this.$scrollElement[0])) {
2185
- offsetMethod = 'position'
2186
- offsetBase = this.$scrollElement.scrollTop()
2187
- }
2188
-
2189
- this.$body
2190
- .find(this.selector)
2191
- .map(function () {
2192
- var $el = $(this)
2193
- var href = $el.data('target') || $el.attr('href')
2194
- var $href = /^#./.test(href) && $(href)
2195
-
2196
- return ($href
2197
- && $href.length
2198
- && $href.is(':visible')
2199
- && [[$href[offsetMethod]().top + offsetBase, href]]) || null
2200
- })
2201
- .sort(function (a, b) { return a[0] - b[0] })
2202
- .each(function () {
2203
- that.offsets.push(this[0])
2204
- that.targets.push(this[1])
2205
- })
2206
- }
2207
-
2208
- ScrollSpy.prototype.process = function () {
2209
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
2210
- var scrollHeight = this.getScrollHeight()
2211
- var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
2212
- var offsets = this.offsets
2213
- var targets = this.targets
2214
- var activeTarget = this.activeTarget
2215
- var i
2216
-
2217
- if (this.scrollHeight != scrollHeight) {
2218
- this.refresh()
2219
- }
2220
-
2221
- if (scrollTop >= maxScroll) {
2222
- return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
2223
- }
2224
-
2225
- if (activeTarget && scrollTop < offsets[0]) {
2226
- this.activeTarget = null
2227
- return this.clear()
2228
- }
2229
-
2230
- for (i = offsets.length; i--;) {
2231
- activeTarget != targets[i]
2232
- && scrollTop >= offsets[i]
2233
- && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
2234
- && this.activate(targets[i])
2235
- }
2236
- }
2237
-
2238
- ScrollSpy.prototype.activate = function (target) {
2239
- this.activeTarget = target
2240
-
2241
- this.clear()
2242
-
2243
- var selector = this.selector +
2244
- '[data-target="' + target + '"],' +
2245
- this.selector + '[href="' + target + '"]'
2246
-
2247
- var active = $(selector)
2248
- .parents('li')
2249
- .addClass('active')
2250
-
2251
- if (active.parent('.dropdown-menu').length) {
2252
- active = active
2253
- .closest('li.dropdown')
2254
- .addClass('active')
2255
- }
2256
-
2257
- active.trigger('activate.bs.scrollspy')
2258
- }
2259
-
2260
- ScrollSpy.prototype.clear = function () {
2261
- $(this.selector)
2262
- .parentsUntil(this.options.target, '.active')
2263
- .removeClass('active')
2264
- }
2265
-
2266
-
2267
- // SCROLLSPY PLUGIN DEFINITION
2268
- // ===========================
2269
-
2270
- function Plugin(option) {
2271
- return this.each(function () {
2272
- var $this = $(this)
2273
- var data = $this.data('bs.scrollspy')
2274
- var options = typeof option == 'object' && option
2275
-
2276
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
2277
- if (typeof option == 'string') data[option]()
2278
- })
2279
- }
2280
-
2281
- var old = $.fn.scrollspy
2282
-
2283
- $.fn.scrollspy = Plugin
2284
- $.fn.scrollspy.Constructor = ScrollSpy
2285
-
2286
-
2287
- // SCROLLSPY NO CONFLICT
2288
- // =====================
2289
-
2290
- $.fn.scrollspy.noConflict = function () {
2291
- $.fn.scrollspy = old
2292
- return this
2293
- }
2294
-
2295
-
2296
- // SCROLLSPY DATA-API
2297
- // ==================
2298
-
2299
- $(window).on('load.bs.scrollspy.data-api', function () {
2300
- $('[data-spy="scroll"]').each(function () {
2301
- var $spy = $(this)
2302
- Plugin.call($spy, $spy.data())
2303
- })
2304
- })
2305
-
2306
- }(jQuery);
2307
-
2308
- /* ========================================================================
2309
- * Bootstrap: transition.js v3.3.5
2310
- * http://getbootstrap.com/javascript/#transitions
2311
- * ========================================================================
2312
- * Copyright 2011-2015 Twitter, Inc.
2313
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2314
- * ======================================================================== */
2315
-
2316
-
2317
- +function ($) {
2318
- 'use strict';
2319
-
2320
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
2321
- // ============================================================
2322
-
2323
- function transitionEnd() {
2324
- var el = document.createElement('bootstrap')
2325
-
2326
- var transEndEventNames = {
2327
- WebkitTransition : 'webkitTransitionEnd',
2328
- MozTransition : 'transitionend',
2329
- OTransition : 'oTransitionEnd otransitionend',
2330
- transition : 'transitionend'
2331
- }
2332
-
2333
- for (var name in transEndEventNames) {
2334
- if (el.style[name] !== undefined) {
2335
- return { end: transEndEventNames[name] }
2336
- }
2337
- }
2338
-
2339
- return false // explicit for ie8 ( ._.)
2340
- }
2341
-
2342
- // http://blog.alexmaccaw.com/css-transitions
2343
- $.fn.emulateTransitionEnd = function (duration) {
2344
- var called = false
2345
- var $el = this
2346
- $(this).one('bsTransitionEnd', function () { called = true })
2347
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
2348
- setTimeout(callback, duration)
2349
- return this
2350
- }
2351
-
2352
- $(function () {
2353
- $.support.transition = transitionEnd()
2354
-
2355
- if (!$.support.transition) return
2356
-
2357
- $.event.special.bsTransitionEnd = {
2358
- bindType: $.support.transition.end,
2359
- delegateType: $.support.transition.end,
2360
- handle: function (e) {
2361
- if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
2362
- }
2363
- }
2364
- })
2365
-
2366
- }(jQuery);