2 * Bootstrap v3.4.1 (https://getbootstrap.com/)
3 * Copyright 2011-2019 Twitter, Inc.
4 * Licensed under the MIT license
7 if (typeof jQuery
=== 'undefined') {
8 throw new Error('Bootstrap\'s JavaScript requires jQuery')
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] > 3)) {
15 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
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 * ======================================================================== */
31 // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
32 // ============================================================
34 function transitionEnd() {
35 var el
= document
.createElement('bootstrap')
37 var transEndEventNames
= {
38 WebkitTransition : 'webkitTransitionEnd',
39 MozTransition : 'transitionend',
40 OTransition : 'oTransitionEnd otransitionend',
41 transition : 'transitionend'
44 for (var name
in transEndEventNames
) {
45 if (el
.style
[name
] !== undefined) {
46 return { end: transEndEventNames
[name
] }
50 return false // explicit for ie8 ( ._.)
53 // https://blog.alexmaccaw.com/css-transitions
54 $.fn
.emulateTransitionEnd = function (duration
) {
57 $(this).one('bsTransitionEnd', function () { called
= true })
58 var callback = function () { if (!called
) $($el
).trigger($.support
.transition
.end
) }
59 setTimeout(callback
, duration
)
64 $.support
.transition
= transitionEnd()
66 if (!$.support
.transition
) return
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
)
79 /* ========================================================================
80 * Bootstrap: alert.js v3.4.1
81 * https://getbootstrap.com/docs/3.4/javascript/#alerts
82 * ========================================================================
83 * Copyright 2011-2019 Twitter, Inc.
84 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
85 * ======================================================================== */
91 // ALERT CLASS DEFINITION
92 // ======================
94 var dismiss
= '[data-dismiss="alert"]'
95 var Alert = function (el
) {
96 $(el
).on('click', dismiss
, this.close
)
99 Alert
.VERSION
= '3.4.1'
101 Alert
.TRANSITION_DURATION
= 150
103 Alert
.prototype.close = function (e
) {
105 var selector
= $this.attr('data-target')
108 selector
= $this.attr('href')
109 selector
= selector
&& selector
.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
112 selector
= selector
=== '#' ? [] : selector
113 var $parent
= $(document
).find(selector
)
115 if (e
) e
.preventDefault()
117 if (!$parent
.length
) {
118 $parent
= $this.closest('.alert')
121 $parent
.trigger(e
= $.Event('close.bs.alert'))
123 if (e
.isDefaultPrevented()) return
125 $parent
.removeClass('in')
127 function removeElement() {
128 // detach from parent, fire event then clean up data
129 $parent
.detach().trigger('closed.bs.alert').remove()
132 $.support
.transition
&& $parent
.hasClass('fade') ?
134 .one('bsTransitionEnd', removeElement
)
135 .emulateTransitionEnd(Alert
.TRANSITION_DURATION
) :
140 // ALERT PLUGIN DEFINITION
141 // =======================
143 function Plugin(option
) {
144 return this.each(function () {
146 var data
= $this.data('bs.alert')
148 if (!data
) $this.data('bs.alert', (data
= new Alert(this)))
149 if (typeof option
== 'string') data
[option
].call($this)
156 $.fn
.alert
.Constructor
= Alert
162 $.fn
.alert
.noConflict = function () {
171 $(document
).on('click.bs.alert.data-api', dismiss
, Alert
.prototype.close
)
175 /* ========================================================================
176 * Bootstrap: button.js v3.4.1
177 * https://getbootstrap.com/docs/3.4/javascript/#buttons
178 * ========================================================================
179 * Copyright 2011-2019 Twitter, Inc.
180 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
181 * ======================================================================== */
187 // BUTTON PUBLIC CLASS DEFINITION
188 // ==============================
190 var Button = function (element
, options
) {
191 this.$element
= $(element
)
192 this.options
= $.extend({}, Button
.DEFAULTS
, options
)
193 this.isLoading
= false
196 Button
.VERSION
= '3.4.1'
199 loadingText: 'loading...'
202 Button
.prototype.setState = function (state
) {
204 var $el
= this.$element
205 var val
= $el
.is('input') ? 'val' : 'html'
206 var data
= $el
.data()
210 if (data
.resetText
== null) $el
.data('resetText', $el
[val
]())
212 // push to event loop to allow forms to submit
213 setTimeout($.proxy(function () {
214 $el
[val
](data
[state
] == null ? this.options
[state
] : data
[state
])
216 if (state
== 'loadingText') {
217 this.isLoading
= true
218 $el
.addClass(d
).attr(d
, d
).prop(d
, true)
219 } else if (this.isLoading
) {
220 this.isLoading
= false
221 $el
.removeClass(d
).removeAttr(d
).prop(d
, false)
226 Button
.prototype.toggle = function () {
228 var $parent
= this.$element
.closest('[data-toggle="buttons"]')
230 if ($parent
.length
) {
231 var $input
= this.$element
.find('input')
232 if ($input
.prop('type') == 'radio') {
233 if ($input
.prop('checked')) changed
= false
234 $parent
.find('.active').removeClass('active')
235 this.$element
.addClass('active')
236 } else if ($input
.prop('type') == 'checkbox') {
237 if (($input
.prop('checked')) !== this.$element
.hasClass('active')) changed
= false
238 this.$element
.toggleClass('active')
240 $input
.prop('checked', this.$element
.hasClass('active'))
241 if (changed
) $input
.trigger('change')
243 this.$element
.attr('aria-pressed', !this.$element
.hasClass('active'))
244 this.$element
.toggleClass('active')
249 // BUTTON PLUGIN DEFINITION
250 // ========================
252 function Plugin(option
) {
253 return this.each(function () {
255 var data
= $this.data('bs.button')
256 var options
= typeof option
== 'object' && option
258 if (!data
) $this.data('bs.button', (data
= new Button(this, options
)))
260 if (option
== 'toggle') data
.toggle()
261 else if (option
) data
.setState(option
)
265 var old
= $.fn
.button
268 $.fn
.button
.Constructor
= Button
271 // BUTTON NO CONFLICT
272 // ==================
274 $.fn
.button
.noConflict = function () {
284 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e
) {
285 var $btn
= $(e
.target
).closest('.btn')
286 Plugin
.call($btn
, 'toggle')
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
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')
295 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e
) {
296 $(e
.target
).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e
.type
))
301 /* ========================================================================
302 * Bootstrap: carousel.js v3.4.1
303 * https://getbootstrap.com/docs/3.4/javascript/#carousel
304 * ========================================================================
305 * Copyright 2011-2019 Twitter, Inc.
306 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
307 * ======================================================================== */
313 // CAROUSEL CLASS DEFINITION
314 // =========================
316 var Carousel = function (element
, options
) {
317 this.$element
= $(element
)
318 this.$indicators
= this.$element
.find('.carousel-indicators')
319 this.options
= options
326 this.options
.keyboard
&& this.$element
.on('keydown.bs.carousel', $.proxy(this.keydown
, this))
328 this.options
.pause
== 'hover' && !('ontouchstart' in document
.documentElement
) && this.$element
329 .on('mouseenter.bs.carousel', $.proxy(this.pause
, this))
330 .on('mouseleave.bs.carousel', $.proxy(this.cycle
, this))
333 Carousel
.VERSION
= '3.4.1'
335 Carousel
.TRANSITION_DURATION
= 600
337 Carousel
.DEFAULTS
= {
344 Carousel
.prototype.keydown = function (e
) {
345 if (/input|textarea/i.test(e
.target
.tagName
)) return
347 case 37: this.prev(); break
348 case 39: this.next(); break
355 Carousel
.prototype.cycle = function (e
) {
356 e
|| (this.paused
= false)
358 this.interval
&& clearInterval(this.interval
)
360 this.options
.interval
362 && (this.interval
= setInterval($.proxy(this.next
, this), this.options
.interval
))
367 Carousel
.prototype.getItemIndex = function (item
) {
368 this.$items
= item
.parent().children('.item')
369 return this.$items
.index(item
|| this.$active
)
372 Carousel
.prototype.getItemForDirection = function (direction
, active
) {
373 var activeIndex
= this.getItemIndex(active
)
374 var willWrap
= (direction
== 'prev' && activeIndex
=== 0)
375 || (direction
== 'next' && activeIndex
== (this.$items
.length
- 1))
376 if (willWrap
&& !this.options
.wrap
) return active
377 var delta
= direction
== 'prev' ? -1 : 1
378 var itemIndex
= (activeIndex
+ delta
) % this.$items
.length
379 return this.$items
.eq(itemIndex
)
382 Carousel
.prototype.to = function (pos
) {
384 var activeIndex
= this.getItemIndex(this.$active
= this.$element
.find('.item.active'))
386 if (pos
> (this.$items
.length
- 1) || pos
< 0) return
388 if (this.sliding
) return this.$element
.one('slid.bs.carousel', function () { that
.to(pos
) }) // yes, "slid"
389 if (activeIndex
== pos
) return this.pause().cycle()
391 return this.slide(pos
> activeIndex
? 'next' : 'prev', this.$items
.eq(pos
))
394 Carousel
.prototype.pause = function (e
) {
395 e
|| (this.paused
= true)
397 if (this.$element
.find('.next, .prev').length
&& $.support
.transition
) {
398 this.$element
.trigger($.support
.transition
.end
)
402 this.interval
= clearInterval(this.interval
)
407 Carousel
.prototype.next = function () {
408 if (this.sliding
) return
409 return this.slide('next')
412 Carousel
.prototype.prev = function () {
413 if (this.sliding
) return
414 return this.slide('prev')
417 Carousel
.prototype.slide = function (type
, next
) {
418 var $active
= this.$element
.find('.item.active')
419 var $next
= next
|| this.getItemForDirection(type
, $active
)
420 var isCycling
= this.interval
421 var direction
= type
== 'next' ? 'left' : 'right'
424 if ($next
.hasClass('active')) return (this.sliding
= false)
426 var relatedTarget
= $next
[0]
427 var slideEvent
= $.Event('slide.bs.carousel', {
428 relatedTarget: relatedTarget
,
431 this.$element
.trigger(slideEvent
)
432 if (slideEvent
.isDefaultPrevented()) return
436 isCycling
&& this.pause()
438 if (this.$indicators
.length
) {
439 this.$indicators
.find('.active').removeClass('active')
440 var $nextIndicator
= $(this.$indicators
.children()[this.getItemIndex($next
)])
441 $nextIndicator
&& $nextIndicator
.addClass('active')
444 var slidEvent
= $.Event('slid.bs.carousel', { relatedTarget: relatedTarget
, direction: direction
}) // yes, "slid"
445 if ($.support
.transition
&& this.$element
.hasClass('slide')) {
447 if (typeof $next
=== 'object' && $next
.length
) {
448 $next
[0].offsetWidth
// force reflow
450 $active
.addClass(direction
)
451 $next
.addClass(direction
)
453 .one('bsTransitionEnd', function () {
454 $next
.removeClass([type
, direction
].join(' ')).addClass('active')
455 $active
.removeClass(['active', direction
].join(' '))
457 setTimeout(function () {
458 that
.$element
.trigger(slidEvent
)
461 .emulateTransitionEnd(Carousel
.TRANSITION_DURATION
)
463 $active
.removeClass('active')
464 $next
.addClass('active')
466 this.$element
.trigger(slidEvent
)
469 isCycling
&& this.cycle()
475 // CAROUSEL PLUGIN DEFINITION
476 // ==========================
478 function Plugin(option
) {
479 return this.each(function () {
481 var data
= $this.data('bs.carousel')
482 var options
= $.extend({}, Carousel
.DEFAULTS
, $this.data(), typeof option
== 'object' && option
)
483 var action
= typeof option
== 'string' ? option : options
.slide
485 if (!data
) $this.data('bs.carousel', (data
= new Carousel(this, options
)))
486 if (typeof option
== 'number') data
.to(option
)
487 else if (action
) data
[action
]()
488 else if (options
.interval
) data
.pause().cycle()
492 var old
= $.fn
.carousel
494 $.fn
.carousel
= Plugin
495 $.fn
.carousel
.Constructor
= Carousel
498 // CAROUSEL NO CONFLICT
499 // ====================
501 $.fn
.carousel
.noConflict = function () {
510 var clickHandler = function (e
) {
512 var href
= $this.attr('href')
514 href
= href
.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
517 var target
= $this.attr('data-target') || href
518 var $target
= $(document
).find(target
)
520 if (!$target
.hasClass('carousel')) return
522 var options
= $.extend({}, $target
.data(), $this.data())
523 var slideIndex
= $this.attr('data-slide-to')
524 if (slideIndex
) options
.interval
= false
526 Plugin
.call($target
, options
)
529 $target
.data('bs.carousel').to(slideIndex
)
536 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler
)
537 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler
)
539 $(window
).on('load', function () {
540 $('[data-ride="carousel"]').each(function () {
541 var $carousel
= $(this)
542 Plugin
.call($carousel
, $carousel
.data())
548 /* ========================================================================
549 * Bootstrap: collapse.js v3.4.1
550 * https://getbootstrap.com/docs/3.4/javascript/#collapse
551 * ========================================================================
552 * Copyright 2011-2019 Twitter, Inc.
553 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
554 * ======================================================================== */
556 /* jshint latedef: false */
561 // COLLAPSE PUBLIC CLASS DEFINITION
562 // ================================
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
571 if (this.options
.parent
) {
572 this.$parent
= this.getParent()
574 this.addAriaAndCollapsedClass(this.$element
, this.$trigger
)
577 if (this.options
.toggle
) this.toggle()
580 Collapse
.VERSION
= '3.4.1'
582 Collapse
.TRANSITION_DURATION
= 350
584 Collapse
.DEFAULTS
= {
588 Collapse
.prototype.dimension = function () {
589 var hasWidth
= this.$element
.hasClass('width')
590 return hasWidth
? 'width' : 'height'
593 Collapse
.prototype.show = function () {
594 if (this.transitioning
|| this.$element
.hasClass('in')) return
597 var actives
= this.$parent
&& this.$parent
.children('.panel').children('.in, .collapsing')
599 if (actives
&& actives
.length
) {
600 activesData
= actives
.data('bs.collapse')
601 if (activesData
&& activesData
.transitioning
) return
604 var startEvent
= $.Event('show.bs.collapse')
605 this.$element
.trigger(startEvent
)
606 if (startEvent
.isDefaultPrevented()) return
608 if (actives
&& actives
.length
) {
609 Plugin
.call(actives
, 'hide')
610 activesData
|| actives
.data('bs.collapse', null)
613 var dimension
= this.dimension()
616 .removeClass('collapse')
617 .addClass('collapsing')[dimension
](0)
618 .attr('aria-expanded', true)
621 .removeClass('collapsed')
622 .attr('aria-expanded', true)
624 this.transitioning
= 1
626 var complete = function () {
628 .removeClass('collapsing')
629 .addClass('collapse in')[dimension
]('')
630 this.transitioning
= 0
632 .trigger('shown.bs.collapse')
635 if (!$.support
.transition
) return complete
.call(this)
637 var scrollSize
= $.camelCase(['scroll', dimension
].join('-'))
640 .one('bsTransitionEnd', $.proxy(complete
, this))
641 .emulateTransitionEnd(Collapse
.TRANSITION_DURATION
)[dimension
](this.$element
[0][scrollSize
])
644 Collapse
.prototype.hide = function () {
645 if (this.transitioning
|| !this.$element
.hasClass('in')) return
647 var startEvent
= $.Event('hide.bs.collapse')
648 this.$element
.trigger(startEvent
)
649 if (startEvent
.isDefaultPrevented()) return
651 var dimension
= this.dimension()
653 this.$element
[dimension
](this.$element
[dimension
]())[0].offsetHeight
656 .addClass('collapsing')
657 .removeClass('collapse in')
658 .attr('aria-expanded', false)
661 .addClass('collapsed')
662 .attr('aria-expanded', false)
664 this.transitioning
= 1
666 var complete = function () {
667 this.transitioning
= 0
669 .removeClass('collapsing')
670 .addClass('collapse')
671 .trigger('hidden.bs.collapse')
674 if (!$.support
.transition
) return complete
.call(this)
678 .one('bsTransitionEnd', $.proxy(complete
, this))
679 .emulateTransitionEnd(Collapse
.TRANSITION_DURATION
)
682 Collapse
.prototype.toggle = function () {
683 this[this.$element
.hasClass('in') ? 'hide' : 'show']()
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
)
696 Collapse
.prototype.addAriaAndCollapsedClass = function ($element
, $trigger
) {
697 var isOpen
= $element
.hasClass('in')
699 $element
.attr('aria-expanded', isOpen
)
701 .toggleClass('collapsed', !isOpen
)
702 .attr('aria-expanded', isOpen
)
705 function getTargetFromTrigger($trigger
) {
707 var target
= $trigger
.attr('data-target')
708 || (href
= $trigger
.attr('href')) && href
.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
710 return $(document
).find(target
)
714 // COLLAPSE PLUGIN DEFINITION
715 // ==========================
717 function Plugin(option
) {
718 return this.each(function () {
720 var data
= $this.data('bs.collapse')
721 var options
= $.extend({}, Collapse
.DEFAULTS
, $this.data(), typeof option
== 'object' && option
)
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
]()
729 var old
= $.fn
.collapse
731 $.fn
.collapse
= Plugin
732 $.fn
.collapse
.Constructor
= Collapse
735 // COLLAPSE NO CONFLICT
736 // ====================
738 $.fn
.collapse
.noConflict = function () {
747 $(document
).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e
) {
750 if (!$this.attr('data-target')) e
.preventDefault()
752 var $target
= getTargetFromTrigger($this)
753 var data
= $target
.data('bs.collapse')
754 var option
= data
? 'toggle' : $this.data()
756 Plugin
.call($target
, option
)
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 * ======================================================================== */
773 // DROPDOWN CLASS DEFINITION
774 // =========================
776 var backdrop
= '.dropdown-backdrop'
777 var toggle
= '[data-toggle="dropdown"]'
778 var Dropdown = function (element
) {
779 $(element
).on('click.bs.dropdown', this.toggle
)
782 Dropdown
.VERSION
= '3.4.1'
784 function getParent($this) {
785 var selector
= $this.attr('data-target')
788 selector
= $this.attr('href')
789 selector
= selector
&& /#[A-Za-z]/.test(selector
) && selector
.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
792 var $parent
= selector
!== '#' ? $(document
).find(selector
) : null
794 return $parent
&& $parent
.length
? $parent : $this.parent()
797 function clearMenus(e
) {
798 if (e
&& e
.which
=== 3) return
800 $(toggle
).each(function () {
802 var $parent
= getParent($this)
803 var relatedTarget
= { relatedTarget: this }
805 if (!$parent
.hasClass('open')) return
807 if (e
&& e
.type
== 'click' && /input|textarea/i.test(e
.target
.tagName
) && $.contains($parent
[0], e
.target
)) return
809 $parent
.trigger(e
= $.Event('hide.bs.dropdown', relatedTarget
))
811 if (e
.isDefaultPrevented()) return
813 $this.attr('aria-expanded', 'false')
814 $parent
.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget
))
818 Dropdown
.prototype.toggle = function (e
) {
821 if ($this.is('.disabled, :disabled')) return
823 var $parent
= getParent($this)
824 var isActive
= $parent
.hasClass('open')
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
)
837 var relatedTarget
= { relatedTarget: this }
838 $parent
.trigger(e
= $.Event('show.bs.dropdown', relatedTarget
))
840 if (e
.isDefaultPrevented()) return
844 .attr('aria-expanded', 'true')
848 .trigger($.Event('shown.bs.dropdown', relatedTarget
))
854 Dropdown
.prototype.keydown = function (e
) {
855 if (!/(38|40|27|32)/.test(e
.which
) || /input|textarea/i.test(e
.target
.tagName
)) return
862 if ($this.is('.disabled, :disabled')) return
864 var $parent
= getParent($this)
865 var isActive
= $parent
.hasClass('open')
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')
872 var desc
= ' li:not(.disabled):visible a'
873 var $items
= $parent
.find('.dropdown-menu' + desc
)
875 if (!$items
.length
) return
877 var index
= $items
.index(e
.target
)
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
883 $items
.eq(index
).trigger('focus')
887 // DROPDOWN PLUGIN DEFINITION
888 // ==========================
890 function Plugin(option
) {
891 return this.each(function () {
893 var data
= $this.data('bs.dropdown')
895 if (!data
) $this.data('bs.dropdown', (data
= new Dropdown(this)))
896 if (typeof option
== 'string') data
[option
].call($this)
900 var old
= $.fn
.dropdown
902 $.fn
.dropdown
= Plugin
903 $.fn
.dropdown
.Constructor
= Dropdown
906 // DROPDOWN NO CONFLICT
907 // ====================
909 $.fn
.dropdown
.noConflict = function () {
915 // APPLY TO STANDARD DROPDOWN ELEMENTS
916 // ===================================
919 .on('click.bs.dropdown.data-api', clearMenus
)
920 .on('click.bs.dropdown.data-api', '.dropdown form', function (e
) { e
.stopPropagation() })
921 .on('click.bs.dropdown.data-api', toggle
, Dropdown
.prototype.toggle
)
922 .on('keydown.bs.dropdown.data-api', toggle
, Dropdown
.prototype.keydown
)
923 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown
.prototype.keydown
)
927 /* ========================================================================
928 * Bootstrap: modal.js v3.4.1
929 * https://getbootstrap.com/docs/3.4/javascript/#modals
930 * ========================================================================
931 * Copyright 2011-2019 Twitter, Inc.
932 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
933 * ======================================================================== */
939 // MODAL CLASS DEFINITION
940 // ======================
942 var Modal = function (element
, options
) {
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
949 this.originalBodyPad
= null
950 this.scrollbarWidth
= 0
951 this.ignoreBackdropClick
= false
952 this.fixedContent
= '.navbar-fixed-top, .navbar-fixed-bottom'
954 if (this.options
.remote
) {
956 .find('.modal-content')
957 .load(this.options
.remote
, $.proxy(function () {
958 this.$element
.trigger('loaded.bs.modal')
963 Modal
.VERSION
= '3.4.1'
965 Modal
.TRANSITION_DURATION
= 300
966 Modal
.BACKDROP_TRANSITION_DURATION
= 150
974 Modal
.prototype.toggle = function (_relatedTarget
) {
975 return this.isShown
? this.hide() : this.show(_relatedTarget
)
978 Modal
.prototype.show = function (_relatedTarget
) {
980 var e
= $.Event('show.bs.modal', { relatedTarget: _relatedTarget
})
982 this.$element
.trigger(e
)
984 if (this.isShown
|| e
.isDefaultPrevented()) return
988 this.checkScrollbar()
990 this.$body
.addClass('modal-open')
995 this.$element
.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide
, this))
997 this.$dialog
.on('mousedown.dismiss.bs.modal', function () {
998 that
.$element
.one('mouseup.dismiss.bs.modal', function (e
) {
999 if ($(e
.target
).is(that
.$element
)) that
.ignoreBackdropClick
= true
1003 this.backdrop(function () {
1004 var transition
= $.support
.transition
&& that
.$element
.hasClass('fade')
1006 if (!that
.$element
.parent().length
) {
1007 that
.$element
.appendTo(that
.$body
) // don't move modals dom position
1017 that
.$element
[0].offsetWidth
// force reflow
1020 that
.$element
.addClass('in')
1024 var e
= $.Event('shown.bs.modal', { relatedTarget: _relatedTarget
})
1027 that
.$dialog
// wait for modal to slide in
1028 .one('bsTransitionEnd', function () {
1029 that
.$element
.trigger('focus').trigger(e
)
1031 .emulateTransitionEnd(Modal
.TRANSITION_DURATION
) :
1032 that
.$element
.trigger('focus').trigger(e
)
1036 Modal
.prototype.hide = function (e
) {
1037 if (e
) e
.preventDefault()
1039 e
= $.Event('hide.bs.modal')
1041 this.$element
.trigger(e
)
1043 if (!this.isShown
|| e
.isDefaultPrevented()) return
1045 this.isShown
= false
1050 $(document
).off('focusin.bs.modal')
1054 .off('click.dismiss.bs.modal')
1055 .off('mouseup.dismiss.bs.modal')
1057 this.$dialog
.off('mousedown.dismiss.bs.modal')
1059 $.support
.transition
&& this.$element
.hasClass('fade') ?
1061 .one('bsTransitionEnd', $.proxy(this.hideModal
, this))
1062 .emulateTransitionEnd(Modal
.TRANSITION_DURATION
) :
1066 Modal
.prototype.enforceFocus = function () {
1068 .off('focusin.bs.modal') // guard against infinite focus loop
1069 .on('focusin.bs.modal', $.proxy(function (e
) {
1070 if (document
!== e
.target
&&
1071 this.$element
[0] !== e
.target
&&
1072 !this.$element
.has(e
.target
).length
) {
1073 this.$element
.trigger('focus')
1078 Modal
.prototype.escape = function () {
1079 if (this.isShown
&& this.options
.keyboard
) {
1080 this.$element
.on('keydown.dismiss.bs.modal', $.proxy(function (e
) {
1081 e
.which
== 27 && this.hide()
1083 } else if (!this.isShown
) {
1084 this.$element
.off('keydown.dismiss.bs.modal')
1088 Modal
.prototype.resize = function () {
1090 $(window
).on('resize.bs.modal', $.proxy(this.handleUpdate
, this))
1092 $(window
).off('resize.bs.modal')
1096 Modal
.prototype.hideModal = function () {
1098 this.$element
.hide()
1099 this.backdrop(function () {
1100 that
.$body
.removeClass('modal-open')
1101 that
.resetAdjustments()
1102 that
.resetScrollbar()
1103 that
.$element
.trigger('hidden.bs.modal')
1107 Modal
.prototype.removeBackdrop = function () {
1108 this.$backdrop
&& this.$backdrop
.remove()
1109 this.$backdrop
= null
1112 Modal
.prototype.backdrop = function (callback
) {
1114 var animate
= this.$element
.hasClass('fade') ? 'fade' : ''
1116 if (this.isShown
&& this.options
.backdrop
) {
1117 var doAnimate
= $.support
.transition
&& animate
1119 this.$backdrop
= $(document
.createElement('div'))
1120 .addClass('modal-backdrop ' + animate
)
1121 .appendTo(this.$body
)
1123 this.$element
.on('click.dismiss.bs.modal', $.proxy(function (e
) {
1124 if (this.ignoreBackdropClick
) {
1125 this.ignoreBackdropClick
= false
1128 if (e
.target
!== e
.currentTarget
) return
1129 this.options
.backdrop
== 'static'
1130 ? this.$element
[0].focus()
1134 if (doAnimate
) this.$backdrop
[0].offsetWidth
// force reflow
1136 this.$backdrop
.addClass('in')
1138 if (!callback
) return
1142 .one('bsTransitionEnd', callback
)
1143 .emulateTransitionEnd(Modal
.BACKDROP_TRANSITION_DURATION
) :
1146 } else if (!this.isShown
&& this.$backdrop
) {
1147 this.$backdrop
.removeClass('in')
1149 var callbackRemove = function () {
1150 that
.removeBackdrop()
1151 callback
&& callback()
1153 $.support
.transition
&& this.$element
.hasClass('fade') ?
1155 .one('bsTransitionEnd', callbackRemove
)
1156 .emulateTransitionEnd(Modal
.BACKDROP_TRANSITION_DURATION
) :
1159 } else if (callback
) {
1164 // these following methods are used to handle overflowing modals
1166 Modal
.prototype.handleUpdate = function () {
1170 Modal
.prototype.adjustDialog = function () {
1171 var modalIsOverflowing
= this.$element
[0].scrollHeight
> document
.documentElement
.clientHeight
1174 paddingLeft: !this.bodyIsOverflowing
&& modalIsOverflowing
? this.scrollbarWidth : '',
1175 paddingRight: this.bodyIsOverflowing
&& !modalIsOverflowing
? this.scrollbarWidth : ''
1179 Modal
.prototype.resetAdjustments = function () {
1186 Modal
.prototype.checkScrollbar = function () {
1187 var fullWindowWidth
= window
.innerWidth
1188 if (!fullWindowWidth
) { // workaround for missing window.innerWidth in IE8
1189 var documentElementRect
= document
.documentElement
.getBoundingClientRect()
1190 fullWindowWidth
= documentElementRect
.right
- Math
.abs(documentElementRect
.left
)
1192 this.bodyIsOverflowing
= document
.body
.clientWidth
< fullWindowWidth
1193 this.scrollbarWidth
= this.measureScrollbar()
1196 Modal
.prototype.setScrollbar = function () {
1197 var bodyPad
= parseInt((this.$body
.css('padding-right') || 0), 10)
1198 this.originalBodyPad
= document
.body
.style
.paddingRight
|| ''
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')
1206 .data('padding-right', actualPadding
)
1207 .css('padding-right', parseFloat(calculatedPadding
) + scrollbarWidth
+ 'px')
1212 Modal
.prototype.resetScrollbar = function () {
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 : ''
1221 Modal
.prototype.measureScrollbar = function () { // thx walsh
1222 var scrollDiv
= document
.createElement('div')
1223 scrollDiv
.className
= 'modal-scrollbar-measure'
1224 this.$body
.append(scrollDiv
)
1225 var scrollbarWidth
= scrollDiv
.offsetWidth
- scrollDiv
.clientWidth
1226 this.$body
[0].removeChild(scrollDiv
)
1227 return scrollbarWidth
1231 // MODAL PLUGIN DEFINITION
1232 // =======================
1234 function Plugin(option
, _relatedTarget
) {
1235 return this.each(function () {
1237 var data
= $this.data('bs.modal')
1238 var options
= $.extend({}, Modal
.DEFAULTS
, $this.data(), typeof option
== 'object' && option
)
1240 if (!data
) $this.data('bs.modal', (data
= new Modal(this, options
)))
1241 if (typeof option
== 'string') data
[option
](_relatedTarget
)
1242 else if (options
.show
) data
.show(_relatedTarget
)
1246 var old
= $.fn
.modal
1249 $.fn
.modal
.Constructor
= Modal
1252 // MODAL NO CONFLICT
1253 // =================
1255 $.fn
.modal
.noConflict = function () {
1264 $(document
).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e
) {
1266 var href
= $this.attr('href')
1267 var target
= $this.attr('data-target') ||
1268 (href
&& href
.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
1270 var $target
= $(document
).find(target
)
1271 var option
= $target
.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href
) && href
}, $target
.data(), $this.data())
1273 if ($this.is('a')) e
.preventDefault()
1275 $target
.one('show.bs.modal', function (showEvent
) {
1276 if (showEvent
.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1277 $target
.one('hidden.bs.modal', function () {
1278 $this.is(':visible') && $this.trigger('focus')
1281 Plugin
.call($target
, option
, this)
1286 /* ========================================================================
1287 * Bootstrap: tooltip.js v3.4.1
1288 * https://getbootstrap.com/docs/3.4/javascript/#tooltip
1289 * Inspired by the original jQuery.tipsy by Jason Frame
1290 * ========================================================================
1291 * Copyright 2011-2019 Twitter, Inc.
1292 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1293 * ======================================================================== */
1298 var DISALLOWED_ATTRIBUTES
= ['sanitize', 'whiteList', 'sanitizeFn']
1311 var ARIA_ATTRIBUTE_PATTERN
= /^aria-[\w-]*$/i
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'],
1332 img: ['src', 'alt', 'title', 'width', 'height'],
1348 * A pattern that recognizes a commonly useful subset of URLs that are safe.
1350 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
1352 var SAFE_URL_PATTERN
= /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
1355 * A pattern that matches safe data URLs. Only matches image, video and audio types.
1357 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
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
1361 function allowedAttribute(attr
, allowedAttributeList
) {
1362 var attrName
= attr
.nodeName
.toLowerCase()
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
))
1372 var regExp
= $(allowedAttributeList
).filter(function (index
, value
) {
1373 return value
instanceof RegExp
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
])) {
1386 function sanitizeHtml(unsafeHtml
, whiteList
, sanitizeFn
) {
1387 if (unsafeHtml
.length
=== 0) {
1391 if (sanitizeFn
&& typeof sanitizeFn
=== 'function') {
1392 return sanitizeFn(unsafeHtml
)
1395 // IE 8 and below don't support createHTMLDocument
1396 if (!document
.implementation
|| !document
.implementation
.createHTMLDocument
) {
1400 var createdDocument
= document
.implementation
.createHTMLDocument('sanitization')
1401 createdDocument
.body
.innerHTML
= unsafeHtml
1403 var whitelistKeys
= $.map(whiteList
, function (el
, i
) { return i
})
1404 var elements
= $(createdDocument
.body
).find('*')
1406 for (var i
= 0, len
= elements
.length
; i
< len
; i
++) {
1407 var el
= elements
[i
]
1408 var elName
= el
.nodeName
.toLowerCase()
1410 if ($.inArray(elName
, whitelistKeys
) === -1) {
1411 el
.parentNode
.removeChild(el
)
1416 var attributeList
= $.map(el
.attributes
, function (el
) { return el
})
1417 var whitelistedAttributes
= [].concat(whiteList
['*'] || [], whiteList
[elName
] || [])
1419 for (var j
= 0, len2
= attributeList
.length
; j
< len2
; j
++) {
1420 if (!allowedAttribute(attributeList
[j
], whitelistedAttributes
)) {
1421 el
.removeAttribute(attributeList
[j
].nodeName
)
1426 return createdDocument
.body
.innerHTML
1429 // TOOLTIP PUBLIC CLASS DEFINITION
1430 // ===============================
1432 var Tooltip = function (element
, options
) {
1437 this.hoverState
= null
1438 this.$element
= null
1441 this.init('tooltip', element
, options
)
1444 Tooltip
.VERSION
= '3.4.1'
1446 Tooltip
.TRANSITION_DURATION
= 150
1448 Tooltip
.DEFAULTS
= {
1452 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1453 trigger: 'hover focus',
1464 whiteList : DefaultWhitelist
1467 Tooltip
.prototype.init = function (type
, element
, options
) {
1470 this.$element
= $(element
)
1471 this.options
= this.getOptions(options
)
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
))
1473 this.inState
= { click: false, hover: false, focus: false }
1475 if (this.$element
[0] instanceof document
.constructor && !this.options
.selector
) {
1476 throw new Error('`selector` option must be specified when initializing ' + this.type
+ ' on the window.document object!')
1479 var triggers
= this.options
.trigger
.split(' ')
1481 for (var i
= triggers
.length
; i
--;) {
1482 var trigger
= triggers
[i
]
1484 if (trigger
== 'click') {
1485 this.$element
.on('click.' + this.type
, this.options
.selector
, $.proxy(this.toggle
, this))
1486 } else if (trigger
!= 'manual') {
1487 var eventIn
= trigger
== 'hover' ? 'mouseenter' : 'focusin'
1488 var eventOut
= trigger
== 'hover' ? 'mouseleave' : 'focusout'
1490 this.$element
.on(eventIn
+ '.' + this.type
, this.options
.selector
, $.proxy(this.enter
, this))
1491 this.$element
.on(eventOut
+ '.' + this.type
, this.options
.selector
, $.proxy(this.leave
, this))
1495 this.options
.selector
?
1496 (this._options
= $.extend({}, this.options
, { trigger: 'manual', selector: '' })) :
1500 Tooltip
.prototype.getDefaults = function () {
1501 return Tooltip
.DEFAULTS
1504 Tooltip
.prototype.getOptions = function (options
) {
1505 var dataAttributes
= this.$element
.data()
1507 for (var dataAttr
in dataAttributes
) {
1508 if (dataAttributes
.hasOwnProperty(dataAttr
) && $.inArray(dataAttr
, DISALLOWED_ATTRIBUTES
) !== -1) {
1509 delete dataAttributes
[dataAttr
]
1513 options
= $.extend({}, this.getDefaults(), dataAttributes
, options
)
1515 if (options
.delay
&& typeof options
.delay
== 'number') {
1517 show: options
.delay
,
1522 if (options
.sanitize
) {
1523 options
.template
= sanitizeHtml(options
.template
, options
.whiteList
, options
.sanitizeFn
)
1529 Tooltip
.prototype.getDelegateOptions = function () {
1531 var defaults
= this.getDefaults()
1533 this._options
&& $.each(this._options
, function (key
, value
) {
1534 if (defaults
[key
] != value
) options
[key
] = value
1540 Tooltip
.prototype.enter = function (obj
) {
1541 var self
= obj
instanceof this.constructor ?
1542 obj : $(obj
.currentTarget
).data('bs.' + this.type
)
1545 self
= new this.constructor(obj
.currentTarget
, this.getDelegateOptions())
1546 $(obj
.currentTarget
).data('bs.' + this.type
, self
)
1549 if (obj
instanceof $.Event
) {
1550 self
.inState
[obj
.type
== 'focusin' ? 'focus' : 'hover'] = true
1553 if (self
.tip().hasClass('in') || self
.hoverState
== 'in') {
1554 self
.hoverState
= 'in'
1558 clearTimeout(self
.timeout
)
1560 self
.hoverState
= 'in'
1562 if (!self
.options
.delay
|| !self
.options
.delay
.show
) return self
.show()
1564 self
.timeout
= setTimeout(function () {
1565 if (self
.hoverState
== 'in') self
.show()
1566 }, self
.options
.delay
.show
)
1569 Tooltip
.prototype.isInStateTrue = function () {
1570 for (var key
in this.inState
) {
1571 if (this.inState
[key
]) return true
1577 Tooltip
.prototype.leave = function (obj
) {
1578 var self
= obj
instanceof this.constructor ?
1579 obj : $(obj
.currentTarget
).data('bs.' + this.type
)
1582 self
= new this.constructor(obj
.currentTarget
, this.getDelegateOptions())
1583 $(obj
.currentTarget
).data('bs.' + this.type
, self
)
1586 if (obj
instanceof $.Event
) {
1587 self
.inState
[obj
.type
== 'focusout' ? 'focus' : 'hover'] = false
1590 if (self
.isInStateTrue()) return
1592 clearTimeout(self
.timeout
)
1594 self
.hoverState
= 'out'
1596 if (!self
.options
.delay
|| !self
.options
.delay
.hide
) return self
.hide()
1598 self
.timeout
= setTimeout(function () {
1599 if (self
.hoverState
== 'out') self
.hide()
1600 }, self
.options
.delay
.hide
)
1603 Tooltip
.prototype.show = function () {
1604 var e
= $.Event('show.bs.' + this.type
)
1606 if (this.hasContent() && this.enabled
) {
1607 this.$element
.trigger(e
)
1609 var inDom
= $.contains(this.$element
[0].ownerDocument
.documentElement
, this.$element
[0])
1610 if (e
.isDefaultPrevented() || !inDom
) return
1613 var $tip
= this.tip()
1615 var tipId
= this.getUID(this.type
)
1618 $tip
.attr('id', tipId
)
1619 this.$element
.attr('aria-describedby', tipId
)
1621 if (this.options
.animation
) $tip
.addClass('fade')
1623 var placement
= typeof this.options
.placement
== 'function' ?
1624 this.options
.placement
.call(this, $tip
[0], this.$element
[0]) :
1625 this.options
.placement
1627 var autoToken
= /\s?auto?\s?/i
1628 var autoPlace
= autoToken
.test(placement
)
1629 if (autoPlace
) placement
= placement
.replace(autoToken
, '') || 'top'
1633 .css({ top: 0, left: 0, display: 'block' })
1634 .addClass(placement
)
1635 .data('bs.' + this.type
, this)
1637 this.options
.container
? $tip
.appendTo($(document
).find(this.options
.container
)) : $tip
.insertAfter(this.$element
)
1638 this.$element
.trigger('inserted.bs.' + this.type
)
1640 var pos
= this.getPosition()
1641 var actualWidth
= $tip
[0].offsetWidth
1642 var actualHeight
= $tip
[0].offsetHeight
1645 var orgPlacement
= placement
1646 var viewportDim
= this.getPosition(this.$viewport
)
1648 placement
= placement
== 'bottom' && pos
.bottom
+ actualHeight
> viewportDim
.bottom
? 'top' :
1649 placement
== 'top' && pos
.top
- actualHeight
< viewportDim
.top
? 'bottom' :
1650 placement
== 'right' && pos
.right
+ actualWidth
> viewportDim
.width
? 'left' :
1651 placement
== 'left' && pos
.left
- actualWidth
< viewportDim
.left
? 'right' :
1655 .removeClass(orgPlacement
)
1656 .addClass(placement
)
1659 var calculatedOffset
= this.getCalculatedOffset(placement
, pos
, actualWidth
, actualHeight
)
1661 this.applyPlacement(calculatedOffset
, placement
)
1663 var complete = function () {
1664 var prevHoverState
= that
.hoverState
1665 that
.$element
.trigger('shown.bs.' + that
.type
)
1666 that
.hoverState
= null
1668 if (prevHoverState
== 'out') that
.leave(that
)
1671 $.support
.transition
&& this.$tip
.hasClass('fade') ?
1673 .one('bsTransitionEnd', complete
)
1674 .emulateTransitionEnd(Tooltip
.TRANSITION_DURATION
) :
1679 Tooltip
.prototype.applyPlacement = function (offset
, placement
) {
1680 var $tip
= this.tip()
1681 var width
= $tip
[0].offsetWidth
1682 var height
= $tip
[0].offsetHeight
1684 // manually read margins because getBoundingClientRect includes difference
1685 var marginTop
= parseInt($tip
.css('margin-top'), 10)
1686 var marginLeft
= parseInt($tip
.css('margin-left'), 10)
1688 // we must check for NaN for ie 8/9
1689 if (isNaN(marginTop
)) marginTop
= 0
1690 if (isNaN(marginLeft
)) marginLeft
= 0
1692 offset
.top
+= marginTop
1693 offset
.left
+= marginLeft
1695 // $.fn.offset doesn't round pixel values
1696 // so we use setOffset directly with our own function B-0
1697 $.offset
.setOffset($tip
[0], $.extend({
1698 using: function (props
) {
1700 top: Math
.round(props
.top
),
1701 left: Math
.round(props
.left
)
1708 // check to see if placing tip in new offset caused the tip to resize itself
1709 var actualWidth
= $tip
[0].offsetWidth
1710 var actualHeight
= $tip
[0].offsetHeight
1712 if (placement
== 'top' && actualHeight
!= height
) {
1713 offset
.top
= offset
.top
+ height
- actualHeight
1716 var delta
= this.getViewportAdjustedDelta(placement
, offset
, actualWidth
, actualHeight
)
1718 if (delta
.left
) offset
.left
+= delta
.left
1719 else offset
.top
+= delta
.top
1721 var isVertical
= /top|bottom/.test(placement
)
1722 var arrowDelta
= isVertical
? delta
.left
* 2 - width
+ actualWidth : delta
.top
* 2 - height
+ actualHeight
1723 var arrowOffsetPosition
= isVertical
? 'offsetWidth' : 'offsetHeight'
1726 this.replaceArrow(arrowDelta
, $tip
[0][arrowOffsetPosition
], isVertical
)
1729 Tooltip
.prototype.replaceArrow = function (delta
, dimension
, isVertical
) {
1731 .css(isVertical
? 'left' : 'top', 50 * (1 - delta
/ dimension
) + '%')
1732 .css(isVertical
? 'top' : 'left', '')
1735 Tooltip
.prototype.setContent = function () {
1736 var $tip
= this.tip()
1737 var title
= this.getTitle()
1739 if (this.options
.html
) {
1740 if (this.options
.sanitize
) {
1741 title
= sanitizeHtml(title
, this.options
.whiteList
, this.options
.sanitizeFn
)
1744 $tip
.find('.tooltip-inner').html(title
)
1746 $tip
.find('.tooltip-inner').text(title
)
1749 $tip
.removeClass('fade in top bottom left right')
1752 Tooltip
.prototype.hide = function (callback
) {
1754 var $tip
= $(this.$tip
)
1755 var e
= $.Event('hide.bs.' + this.type
)
1757 function complete() {
1758 if (that
.hoverState
!= 'in') $tip
.detach()
1759 if (that
.$element
) { // TODO: Check whether guarding this code with this `if` is really necessary.
1761 .removeAttr('aria-describedby')
1762 .trigger('hidden.bs.' + that
.type
)
1764 callback
&& callback()
1767 this.$element
.trigger(e
)
1769 if (e
.isDefaultPrevented()) return
1771 $tip
.removeClass('in')
1773 $.support
.transition
&& $tip
.hasClass('fade') ?
1775 .one('bsTransitionEnd', complete
)
1776 .emulateTransitionEnd(Tooltip
.TRANSITION_DURATION
) :
1779 this.hoverState
= null
1784 Tooltip
.prototype.fixTitle = function () {
1785 var $e
= this.$element
1786 if ($e
.attr('title') || typeof $e
.attr('data-original-title') != 'string') {
1787 $e
.attr('data-original-title', $e
.attr('title') || '').attr('title', '')
1791 Tooltip
.prototype.hasContent = function () {
1792 return this.getTitle()
1795 Tooltip
.prototype.getPosition = function ($element
) {
1796 $element
= $element
|| this.$element
1798 var el
= $element
[0]
1799 var isBody
= el
.tagName
== 'BODY'
1801 var elRect
= el
.getBoundingClientRect()
1802 if (elRect
.width
== null) {
1803 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1804 elRect
= $.extend({}, elRect
, { width: elRect
.right
- elRect
.left
, height: elRect
.bottom
- elRect
.top
})
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())
1810 var scroll
= { scroll: isBody
? document
.documentElement
.scrollTop
|| document
.body
.scrollTop : $element
.scrollTop() }
1811 var outerDims
= isBody
? { width: $(window
).width(), height: $(window
).height() } : null
1813 return $.extend({}, elRect
, scroll
, outerDims
, elOffset
)
1816 Tooltip
.prototype.getCalculatedOffset = function (placement
, pos
, actualWidth
, actualHeight
) {
1817 return placement
== 'bottom' ? { top: pos
.top
+ pos
.height
, left: pos
.left
+ pos
.width
/ 2 - actualWidth
/ 2 } :
1818 placement
== 'top' ? { top: pos
.top
- actualHeight
, left: pos
.left
+ pos
.width
/ 2 - actualWidth
/ 2 } :
1819 placement
== 'left' ? { top: pos
.top
+ pos
.height
/ 2 - actualHeight
/ 2, left: pos
.left
- actualWidth
} :
1820 /* placement == 'right' */ { top: pos
.top
+ pos
.height
/ 2 - actualHeight
/ 2, left: pos
.left
+ pos
.width
}
1824 Tooltip
.prototype.getViewportAdjustedDelta = function (placement
, pos
, actualWidth
, actualHeight
) {
1825 var delta
= { top: 0, left: 0 }
1826 if (!this.$viewport
) return delta
1828 var viewportPadding
= this.options
.viewport
&& this.options
.viewport
.padding
|| 0
1829 var viewportDimensions
= this.getPosition(this.$viewport
)
1831 if (/right|left/.test(placement
)) {
1832 var topEdgeOffset
= pos
.top
- viewportPadding
- viewportDimensions
.scroll
1833 var bottomEdgeOffset
= pos
.top
+ viewportPadding
- viewportDimensions
.scroll
+ actualHeight
1834 if (topEdgeOffset
< viewportDimensions
.top
) { // top overflow
1835 delta
.top
= viewportDimensions
.top
- topEdgeOffset
1836 } else if (bottomEdgeOffset
> viewportDimensions
.top
+ viewportDimensions
.height
) { // bottom overflow
1837 delta
.top
= viewportDimensions
.top
+ viewportDimensions
.height
- bottomEdgeOffset
1840 var leftEdgeOffset
= pos
.left
- viewportPadding
1841 var rightEdgeOffset
= pos
.left
+ viewportPadding
+ actualWidth
1842 if (leftEdgeOffset
< viewportDimensions
.left
) { // left overflow
1843 delta
.left
= viewportDimensions
.left
- leftEdgeOffset
1844 } else if (rightEdgeOffset
> viewportDimensions
.right
) { // right overflow
1845 delta
.left
= viewportDimensions
.left
+ viewportDimensions
.width
- rightEdgeOffset
1852 Tooltip
.prototype.getTitle = function () {
1854 var $e
= this.$element
1855 var o
= this.options
1857 title
= $e
.attr('data-original-title')
1858 || (typeof o
.title
== 'function' ? o
.title
.call($e
[0]) : o
.title
)
1863 Tooltip
.prototype.getUID = function (prefix
) {
1864 do prefix
+= ~~(Math
.random() * 1000000)
1865 while (document
.getElementById(prefix
))
1869 Tooltip
.prototype.tip = function () {
1871 this.$tip
= $(this.options
.template
)
1872 if (this.$tip
.length
!= 1) {
1873 throw new Error(this.type
+ ' `template` option must consist of exactly 1 top-level element!')
1879 Tooltip
.prototype.arrow = function () {
1880 return (this.$arrow
= this.$arrow
|| this.tip().find('.tooltip-arrow'))
1883 Tooltip
.prototype.enable = function () {
1887 Tooltip
.prototype.disable = function () {
1888 this.enabled
= false
1891 Tooltip
.prototype.toggleEnabled = function () {
1892 this.enabled
= !this.enabled
1895 Tooltip
.prototype.toggle = function (e
) {
1898 self
= $(e
.currentTarget
).data('bs.' + this.type
)
1900 self
= new this.constructor(e
.currentTarget
, this.getDelegateOptions())
1901 $(e
.currentTarget
).data('bs.' + this.type
, self
)
1906 self
.inState
.click
= !self
.inState
.click
1907 if (self
.isInStateTrue()) self
.enter(self
)
1908 else self
.leave(self
)
1910 self
.tip().hasClass('in') ? self
.leave(self
) : self
.enter(self
)
1914 Tooltip
.prototype.destroy = function () {
1916 clearTimeout(this.timeout
)
1917 this.hide(function () {
1918 that
.$element
.off('.' + that
.type
).removeData('bs.' + that
.type
)
1924 that
.$viewport
= null
1925 that
.$element
= null
1929 Tooltip
.prototype.sanitizeHtml = function (unsafeHtml
) {
1930 return sanitizeHtml(unsafeHtml
, this.options
.whiteList
, this.options
.sanitizeFn
)
1933 // TOOLTIP PLUGIN DEFINITION
1934 // =========================
1936 function Plugin(option
) {
1937 return this.each(function () {
1939 var data
= $this.data('bs.tooltip')
1940 var options
= typeof option
== 'object' && option
1942 if (!data
&& /destroy|hide/.test(option
)) return
1943 if (!data
) $this.data('bs.tooltip', (data
= new Tooltip(this, options
)))
1944 if (typeof option
== 'string') data
[option
]()
1948 var old
= $.fn
.tooltip
1950 $.fn
.tooltip
= Plugin
1951 $.fn
.tooltip
.Constructor
= Tooltip
1954 // TOOLTIP NO CONFLICT
1955 // ===================
1957 $.fn
.tooltip
.noConflict = function () {
1964 /* ========================================================================
1965 * Bootstrap: popover.js v3.4.1
1966 * https://getbootstrap.com/docs/3.4/javascript/#popovers
1967 * ========================================================================
1968 * Copyright 2011-2019 Twitter, Inc.
1969 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1970 * ======================================================================== */
1976 // POPOVER PUBLIC CLASS DEFINITION
1977 // ===============================
1979 var Popover = function (element
, options
) {
1980 this.init('popover', element
, options
)
1983 if (!$.fn
.tooltip
) throw new Error('Popover requires tooltip.js')
1985 Popover
.VERSION
= '3.4.1'
1987 Popover
.DEFAULTS
= $.extend({}, $.fn
.tooltip
.Constructor
.DEFAULTS
, {
1991 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1995 // NOTE: POPOVER EXTENDS tooltip.js
1996 // ================================
1998 Popover
.prototype = $.extend({}, $.fn
.tooltip
.Constructor
.prototype)
2000 Popover
.prototype.constructor = Popover
2002 Popover
.prototype.getDefaults = function () {
2003 return Popover
.DEFAULTS
2006 Popover
.prototype.setContent = function () {
2007 var $tip
= this.tip()
2008 var title
= this.getTitle()
2009 var content
= this.getContent()
2011 if (this.options
.html
) {
2012 var typeContent
= typeof content
2014 if (this.options
.sanitize
) {
2015 title
= this.sanitizeHtml(title
)
2017 if (typeContent
=== 'string') {
2018 content
= this.sanitizeHtml(content
)
2022 $tip
.find('.popover-title').html(title
)
2023 $tip
.find('.popover-content').children().detach().end()[
2024 typeContent
=== 'string' ? 'html' : 'append'
2027 $tip
.find('.popover-title').text(title
)
2028 $tip
.find('.popover-content').children().detach().end().text(content
)
2031 $tip
.removeClass('fade top bottom left right in')
2033 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
2034 // this manually by checking the contents.
2035 if (!$tip
.find('.popover-title').html()) $tip
.find('.popover-title').hide()
2038 Popover
.prototype.hasContent = function () {
2039 return this.getTitle() || this.getContent()
2042 Popover
.prototype.getContent = function () {
2043 var $e
= this.$element
2044 var o
= this.options
2046 return $e
.attr('data-content')
2047 || (typeof o
.content
== 'function' ?
2048 o
.content
.call($e
[0]) :
2052 Popover
.prototype.arrow = function () {
2053 return (this.$arrow
= this.$arrow
|| this.tip().find('.arrow'))
2057 // POPOVER PLUGIN DEFINITION
2058 // =========================
2060 function Plugin(option
) {
2061 return this.each(function () {
2063 var data
= $this.data('bs.popover')
2064 var options
= typeof option
== 'object' && option
2066 if (!data
&& /destroy|hide/.test(option
)) return
2067 if (!data
) $this.data('bs.popover', (data
= new Popover(this, options
)))
2068 if (typeof option
== 'string') data
[option
]()
2072 var old
= $.fn
.popover
2074 $.fn
.popover
= Plugin
2075 $.fn
.popover
.Constructor
= Popover
2078 // POPOVER NO CONFLICT
2079 // ===================
2081 $.fn
.popover
.noConflict = function () {
2088 /* ========================================================================
2089 * Bootstrap: scrollspy.js v3.4.1
2090 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
2091 * ========================================================================
2092 * Copyright 2011-2019 Twitter, Inc.
2093 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2094 * ======================================================================== */
2100 // SCROLLSPY CLASS DEFINITION
2101 // ==========================
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'
2110 this.activeTarget
= null
2111 this.scrollHeight
= 0
2113 this.$scrollElement
.on('scroll.bs.scrollspy', $.proxy(this.process
, this))
2118 ScrollSpy
.VERSION
= '3.4.1'
2120 ScrollSpy
.DEFAULTS
= {
2124 ScrollSpy
.prototype.getScrollHeight = function () {
2125 return this.$scrollElement
[0].scrollHeight
|| Math
.max(this.$body
[0].scrollHeight
, document
.documentElement
.scrollHeight
)
2128 ScrollSpy
.prototype.refresh = function () {
2130 var offsetMethod
= 'offset'
2135 this.scrollHeight
= this.getScrollHeight()
2137 if (!$.isWindow(this.$scrollElement
[0])) {
2138 offsetMethod
= 'position'
2139 offsetBase
= this.$scrollElement
.scrollTop()
2143 .find(this.selector
)
2146 var href
= $el
.data('target') || $el
.attr('href')
2147 var $href
= /^#./.test(href
) && $(href
)
2151 && $href
.is(':visible')
2152 && [[$href
[offsetMethod
]().top
+ offsetBase
, href
]]) || null
2154 .sort(function (a
, b
) { return a
[0] - b
[0] })
2156 that
.offsets
.push(this[0])
2157 that
.targets
.push(this[1])
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
2170 if (this.scrollHeight
!= scrollHeight
) {
2174 if (scrollTop
>= maxScroll
) {
2175 return activeTarget
!= (i
= targets
[targets
.length
- 1]) && this.activate(i
)
2178 if (activeTarget
&& scrollTop
< offsets
[0]) {
2179 this.activeTarget
= null
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
])
2191 ScrollSpy
.prototype.activate = function (target
) {
2192 this.activeTarget
= target
2196 var selector
= this.selector
+
2197 '[data-target="' + target
+ '"],' +
2198 this.selector
+ '[href="' + target
+ '"]'
2200 var active
= $(selector
)
2204 if (active
.parent('.dropdown-menu').length
) {
2206 .closest('li.dropdown')
2210 active
.trigger('activate.bs.scrollspy')
2213 ScrollSpy
.prototype.clear = function () {
2215 .parentsUntil(this.options
.target
, '.active')
2216 .removeClass('active')
2220 // SCROLLSPY PLUGIN DEFINITION
2221 // ===========================
2223 function Plugin(option
) {
2224 return this.each(function () {
2226 var data
= $this.data('bs.scrollspy')
2227 var options
= typeof option
== 'object' && option
2229 if (!data
) $this.data('bs.scrollspy', (data
= new ScrollSpy(this, options
)))
2230 if (typeof option
== 'string') data
[option
]()
2234 var old
= $.fn
.scrollspy
2236 $.fn
.scrollspy
= Plugin
2237 $.fn
.scrollspy
.Constructor
= ScrollSpy
2240 // SCROLLSPY NO CONFLICT
2241 // =====================
2243 $.fn
.scrollspy
.noConflict = function () {
2244 $.fn
.scrollspy
= old
2249 // SCROLLSPY DATA-API
2250 // ==================
2252 $(window
).on('load.bs.scrollspy.data-api', function () {
2253 $('[data-spy="scroll"]').each(function () {
2255 Plugin
.call($spy
, $spy
.data())
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 * ======================================================================== */
2273 // TAB CLASS DEFINITION
2274 // ====================
2276 var Tab = function (element
) {
2277 // jscs:disable requireDollarBeforejQueryAssignment
2278 this.element
= $(element
)
2279 // jscs:enable requireDollarBeforejQueryAssignment
2282 Tab
.VERSION
= '3.4.1'
2284 Tab
.TRANSITION_DURATION
= 150
2286 Tab
.prototype.show = function () {
2287 var $this = this.element
2288 var $ul
= $this.closest('ul:not(.dropdown-menu)')
2289 var selector
= $this.data('target')
2292 selector
= $this.attr('href')
2293 selector
= selector
&& selector
.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2296 if ($this.parent('li').hasClass('active')) return
2298 var $previous
= $ul
.find('.active:last a')
2299 var hideEvent
= $.Event('hide.bs.tab', {
2300 relatedTarget: $this[0]
2302 var showEvent
= $.Event('show.bs.tab', {
2303 relatedTarget: $previous
[0]
2306 $previous
.trigger(hideEvent
)
2307 $this.trigger(showEvent
)
2309 if (showEvent
.isDefaultPrevented() || hideEvent
.isDefaultPrevented()) return
2311 var $target
= $(document
).find(selector
)
2313 this.activate($this.closest('li'), $ul
)
2314 this.activate($target
, $target
.parent(), function () {
2316 type: 'hidden.bs.tab',
2317 relatedTarget: $this[0]
2320 type: 'shown.bs.tab',
2321 relatedTarget: $previous
[0]
2326 Tab
.prototype.activate = function (element
, container
, callback
) {
2327 var $active
= container
.find('> .active')
2328 var transition
= callback
2329 && $.support
.transition
2330 && ($active
.length
&& $active
.hasClass('fade') || !!container
.find('> .fade').length
)
2334 .removeClass('active')
2335 .find('> .dropdown-menu > .active')
2336 .removeClass('active')
2338 .find('[data-toggle="tab"]')
2339 .attr('aria-expanded', false)
2343 .find('[data-toggle="tab"]')
2344 .attr('aria-expanded', true)
2347 element
[0].offsetWidth
// reflow for transition
2348 element
.addClass('in')
2350 element
.removeClass('fade')
2353 if (element
.parent('.dropdown-menu').length
) {
2355 .closest('li.dropdown')
2358 .find('[data-toggle="tab"]')
2359 .attr('aria-expanded', true)
2362 callback
&& callback()
2365 $active
.length
&& transition
?
2367 .one('bsTransitionEnd', next
)
2368 .emulateTransitionEnd(Tab
.TRANSITION_DURATION
) :
2371 $active
.removeClass('in')
2375 // TAB PLUGIN DEFINITION
2376 // =====================
2378 function Plugin(option
) {
2379 return this.each(function () {
2381 var data
= $this.data('bs.tab')
2383 if (!data
) $this.data('bs.tab', (data
= new Tab(this)))
2384 if (typeof option
== 'string') data
[option
]()
2391 $.fn
.tab
.Constructor
= Tab
2397 $.fn
.tab
.noConflict = function () {
2406 var clickHandler = function (e
) {
2408 Plugin
.call($(this), 'show')
2412 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler
)
2413 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler
)
2417 /* ========================================================================
2418 * Bootstrap: affix.js v3.4.1
2419 * https://getbootstrap.com/docs/3.4/javascript/#affix
2420 * ========================================================================
2421 * Copyright 2011-2019 Twitter, Inc.
2422 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2423 * ======================================================================== */
2429 // AFFIX CLASS DEFINITION
2430 // ======================
2432 var Affix = function (element
, options
) {
2433 this.options
= $.extend({}, Affix
.DEFAULTS
, options
)
2435 var target
= this.options
.target
=== Affix
.DEFAULTS
.target
? $(this.options
.target
) : $(document
).find(this.options
.target
)
2437 this.$target
= target
2438 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition
, this))
2439 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop
, this))
2441 this.$element
= $(element
)
2444 this.pinnedOffset
= null
2446 this.checkPosition()
2449 Affix
.VERSION
= '3.4.1'
2451 Affix
.RESET
= 'affix affix-top affix-bottom'
2458 Affix
.prototype.getState = function (scrollHeight
, height
, offsetTop
, offsetBottom
) {
2459 var scrollTop
= this.$target
.scrollTop()
2460 var position
= this.$element
.offset()
2461 var targetHeight
= this.$target
.height()
2463 if (offsetTop
!= null && this.affixed
== 'top') return scrollTop
< offsetTop
? 'top' : false
2465 if (this.affixed
== 'bottom') {
2466 if (offsetTop
!= null) return (scrollTop
+ this.unpin
<= position
.top
) ? false : 'bottom'
2467 return (scrollTop
+ targetHeight
<= scrollHeight
- offsetBottom
) ? false : 'bottom'
2470 var initializing
= this.affixed
== null
2471 var colliderTop
= initializing
? scrollTop : position
.top
2472 var colliderHeight
= initializing
? targetHeight : height
2474 if (offsetTop
!= null && scrollTop
<= offsetTop
) return 'top'
2475 if (offsetBottom
!= null && (colliderTop
+ colliderHeight
>= scrollHeight
- offsetBottom
)) return 'bottom'
2480 Affix
.prototype.getPinnedOffset = function () {
2481 if (this.pinnedOffset
) return this.pinnedOffset
2482 this.$element
.removeClass(Affix
.RESET
).addClass('affix')
2483 var scrollTop
= this.$target
.scrollTop()
2484 var position
= this.$element
.offset()
2485 return (this.pinnedOffset
= position
.top
- scrollTop
)
2488 Affix
.prototype.checkPositionWithEventLoop = function () {
2489 setTimeout($.proxy(this.checkPosition
, this), 1)
2492 Affix
.prototype.checkPosition = function () {
2493 if (!this.$element
.is(':visible')) return
2495 var height
= this.$element
.height()
2496 var offset
= this.options
.offset
2497 var offsetTop
= offset
.top
2498 var offsetBottom
= offset
.bottom
2499 var scrollHeight
= Math
.max($(document
).height(), $(document
.body
).height())
2501 if (typeof offset
!= 'object') offsetBottom
= offsetTop
= offset
2502 if (typeof offsetTop
== 'function') offsetTop
= offset
.top(this.$element
)
2503 if (typeof offsetBottom
== 'function') offsetBottom
= offset
.bottom(this.$element
)
2505 var affix
= this.getState(scrollHeight
, height
, offsetTop
, offsetBottom
)
2507 if (this.affixed
!= affix
) {
2508 if (this.unpin
!= null) this.$element
.css('top', '')
2510 var affixType
= 'affix' + (affix
? '-' + affix : '')
2511 var e
= $.Event(affixType
+ '.bs.affix')
2513 this.$element
.trigger(e
)
2515 if (e
.isDefaultPrevented()) return
2517 this.affixed
= affix
2518 this.unpin
= affix
== 'bottom' ? this.getPinnedOffset() : null
2521 .removeClass(Affix
.RESET
)
2522 .addClass(affixType
)
2523 .trigger(affixType
.replace('affix', 'affixed') + '.bs.affix')
2526 if (affix
== 'bottom') {
2527 this.$element
.offset({
2528 top: scrollHeight
- height
- offsetBottom
2534 // AFFIX PLUGIN DEFINITION
2535 // =======================
2537 function Plugin(option
) {
2538 return this.each(function () {
2540 var data
= $this.data('bs.affix')
2541 var options
= typeof option
== 'object' && option
2543 if (!data
) $this.data('bs.affix', (data
= new Affix(this, options
)))
2544 if (typeof option
== 'string') data
[option
]()
2548 var old
= $.fn
.affix
2551 $.fn
.affix
.Constructor
= Affix
2554 // AFFIX NO CONFLICT
2555 // =================
2557 $.fn
.affix
.noConflict = function () {
2566 $(window
).on('load', function () {
2567 $('[data-spy="affix"]').each(function () {
2569 var data
= $spy
.data()
2571 data
.offset
= data
.offset
|| {}
2573 if (data
.offsetBottom
!= null) data
.offset
.bottom
= data
.offsetBottom
2574 if (data
.offsetTop
!= null) data
.offset
.top
= data
.offsetTop
2576 Plugin
.call($spy
, data
)