diff options
author | Mario Vavti <mario@mariovavti.com> | 2019-05-10 14:21:36 +0200 |
---|---|---|
committer | Mario Vavti <mario@mariovavti.com> | 2019-05-10 14:21:36 +0200 |
commit | 9866053f0ce44721c11990c9f9407e7428757c99 (patch) | |
tree | 6e414efa36c3bda00205918cecb9122f951427e3 /vendor/twbs/bootstrap/js/src | |
parent | 89a2c1a09c896ac3a23df26a1783f5c682188a56 (diff) | |
download | volse-hubzilla-9866053f0ce44721c11990c9f9407e7428757c99.tar.gz volse-hubzilla-9866053f0ce44721c11990c9f9407e7428757c99.tar.bz2 volse-hubzilla-9866053f0ce44721c11990c9f9407e7428757c99.zip |
update bootstrap to version 4.3.1
Diffstat (limited to 'vendor/twbs/bootstrap/js/src')
-rw-r--r-- | vendor/twbs/bootstrap/js/src/alert.js | 270 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/button.js | 266 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/carousel.js | 882 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/collapse.js | 620 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/dropdown.js | 815 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/index.js | 8 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/modal.js | 911 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/popover.js | 288 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/scrollspy.js | 526 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/tab.js | 402 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/toast.js | 227 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/tools/sanitizer.js | 127 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/tooltip.js | 1168 | ||||
-rw-r--r-- | vendor/twbs/bootstrap/js/src/util.js | 263 |
14 files changed, 3674 insertions, 3099 deletions
diff --git a/vendor/twbs/bootstrap/js/src/alert.js b/vendor/twbs/bootstrap/js/src/alert.js index f39d9d931..64e8e3843 100644 --- a/vendor/twbs/bootstrap/js/src/alert.js +++ b/vendor/twbs/bootstrap/js/src/alert.js @@ -1,183 +1,179 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): alert.js + * Bootstrap (v4.3.1): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Alert = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'alert' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.alert' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const Selector = { - DISMISS : '[data-dismiss="alert"]' - } +import $ from 'jquery' +import Util from './util' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'alert' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.alert' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Selector = { + DISMISS : '[data-dismiss="alert"]' +} + +const Event = { + CLOSE : `close${EVENT_KEY}`, + CLOSED : `closed${EVENT_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + ALERT : 'alert', + FADE : 'fade', + SHOW : 'show' +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - const Event = { - CLOSE : `close${EVENT_KEY}`, - CLOSED : `closed${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +class Alert { + constructor(element) { + this._element = element } - const ClassName = { - ALERT : 'alert', - FADE : 'fade', - SHOW : 'show' + // Getters + + static get VERSION() { + return VERSION } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + // Public - class Alert { - constructor(element) { - this._element = element + close(element) { + let rootElement = this._element + if (element) { + rootElement = this._getRootElement(element) } - // Getters + const customEvent = this._triggerCloseEvent(rootElement) - static get VERSION() { - return VERSION + if (customEvent.isDefaultPrevented()) { + return } - // Public + this._removeElement(rootElement) + } - close(element) { - let rootElement = this._element - if (element) { - rootElement = this._getRootElement(element) - } + dispose() { + $.removeData(this._element, DATA_KEY) + this._element = null + } - const customEvent = this._triggerCloseEvent(rootElement) + // Private - if (customEvent.isDefaultPrevented()) { - return - } + _getRootElement(element) { + const selector = Util.getSelectorFromElement(element) + let parent = false - this._removeElement(rootElement) + if (selector) { + parent = document.querySelector(selector) } - dispose() { - $.removeData(this._element, DATA_KEY) - this._element = null + if (!parent) { + parent = $(element).closest(`.${ClassName.ALERT}`)[0] } - // Private + return parent + } - _getRootElement(element) { - const selector = Util.getSelectorFromElement(element) - let parent = false + _triggerCloseEvent(element) { + const closeEvent = $.Event(Event.CLOSE) - if (selector) { - parent = document.querySelector(selector) - } - - if (!parent) { - parent = $(element).closest(`.${ClassName.ALERT}`)[0] - } - - return parent - } + $(element).trigger(closeEvent) + return closeEvent + } - _triggerCloseEvent(element) { - const closeEvent = $.Event(Event.CLOSE) + _removeElement(element) { + $(element).removeClass(ClassName.SHOW) - $(element).trigger(closeEvent) - return closeEvent + if (!$(element).hasClass(ClassName.FADE)) { + this._destroyElement(element) + return } - _removeElement(element) { - $(element).removeClass(ClassName.SHOW) + const transitionDuration = Util.getTransitionDurationFromElement(element) - if (!$(element).hasClass(ClassName.FADE)) { - this._destroyElement(element) - return - } + $(element) + .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event)) + .emulateTransitionEnd(transitionDuration) + } - const transitionDuration = Util.getTransitionDurationFromElement(element) + _destroyElement(element) { + $(element) + .detach() + .trigger(Event.CLOSED) + .remove() + } - $(element) - .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event)) - .emulateTransitionEnd(transitionDuration) - } + // Static - _destroyElement(element) { - $(element) - .detach() - .trigger(Event.CLOSED) - .remove() - } + static _jQueryInterface(config) { + return this.each(function () { + const $element = $(this) + let data = $element.data(DATA_KEY) - // Static + if (!data) { + data = new Alert(this) + $element.data(DATA_KEY, data) + } - static _jQueryInterface(config) { - return this.each(function () { - const $element = $(this) - let data = $element.data(DATA_KEY) + if (config === 'close') { + data[config](this) + } + }) + } - if (!data) { - data = new Alert(this) - $element.data(DATA_KEY, data) - } + static _handleDismiss(alertInstance) { + return function (event) { + if (event) { + event.preventDefault() + } - if (config === 'close') { - data[config](this) - } - }) + alertInstance.close(this) } + } +} - static _handleDismiss(alertInstance) { - return function (event) { - if (event) { - event.preventDefault() - } +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - alertInstance.close(this) - } - } - } +$(document).on( + Event.CLICK_DATA_API, + Selector.DISMISS, + Alert._handleDismiss(new Alert()) +) - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ - - $(document).on( - Event.CLICK_DATA_API, - Selector.DISMISS, - Alert._handleDismiss(new Alert()) - ) - - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Alert._jQueryInterface - $.fn[NAME].Constructor = Alert - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Alert._jQueryInterface - } +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Alert -})($) +$.fn[NAME] = Alert._jQueryInterface +$.fn[NAME].Constructor = Alert +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Alert._jQueryInterface +} export default Alert diff --git a/vendor/twbs/bootstrap/js/src/button.js b/vendor/twbs/bootstrap/js/src/button.js index cf181d3fc..fcf805502 100644 --- a/vendor/twbs/bootstrap/js/src/button.js +++ b/vendor/twbs/bootstrap/js/src/button.js @@ -1,175 +1,171 @@ -import $ from 'jquery' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): button.js + * Bootstrap (v4.3.1): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Button = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'button' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.button' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const ClassName = { - ACTIVE : 'active', - BUTTON : 'btn', - FOCUS : 'focus' - } +import $ from 'jquery' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'button' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.button' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const ClassName = { + ACTIVE : 'active', + BUTTON : 'btn', + FOCUS : 'focus' +} + +const Selector = { + DATA_TOGGLE_CARROT : '[data-toggle^="button"]', + DATA_TOGGLE : '[data-toggle="buttons"]', + INPUT : 'input:not([type="hidden"])', + ACTIVE : '.active', + BUTTON : '.btn' +} + +const Event = { + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, + FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` + + `blur${EVENT_KEY}${DATA_API_KEY}` +} - const Selector = { - DATA_TOGGLE_CARROT : '[data-toggle^="button"]', - DATA_TOGGLE : '[data-toggle="buttons"]', - INPUT : 'input', - ACTIVE : '.active', - BUTTON : '.btn' +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Button { + constructor(element) { + this._element = element } - const Event = { - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, - FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` + - `blur${EVENT_KEY}${DATA_API_KEY}` + // Getters + + static get VERSION() { + return VERSION } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + // Public - class Button { - constructor(element) { - this._element = element - } + toggle() { + let triggerChangeEvent = true + let addAriaPressed = true + const rootElement = $(this._element).closest( + Selector.DATA_TOGGLE + )[0] - // Getters + if (rootElement) { + const input = this._element.querySelector(Selector.INPUT) - static get VERSION() { - return VERSION - } + if (input) { + if (input.type === 'radio') { + if (input.checked && + this._element.classList.contains(ClassName.ACTIVE)) { + triggerChangeEvent = false + } else { + const activeElement = rootElement.querySelector(Selector.ACTIVE) - // Public - - toggle() { - let triggerChangeEvent = true - let addAriaPressed = true - const rootElement = $(this._element).closest( - Selector.DATA_TOGGLE - )[0] - - if (rootElement) { - const input = this._element.querySelector(Selector.INPUT) - - if (input) { - if (input.type === 'radio') { - if (input.checked && - this._element.classList.contains(ClassName.ACTIVE)) { - triggerChangeEvent = false - } else { - const activeElement = rootElement.querySelector(Selector.ACTIVE) - - if (activeElement) { - $(activeElement).removeClass(ClassName.ACTIVE) - } + if (activeElement) { + $(activeElement).removeClass(ClassName.ACTIVE) } } + } - if (triggerChangeEvent) { - if (input.hasAttribute('disabled') || - rootElement.hasAttribute('disabled') || - input.classList.contains('disabled') || - rootElement.classList.contains('disabled')) { - return - } - input.checked = !this._element.classList.contains(ClassName.ACTIVE) - $(input).trigger('change') + if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || + rootElement.hasAttribute('disabled') || + input.classList.contains('disabled') || + rootElement.classList.contains('disabled')) { + return } - - input.focus() - addAriaPressed = false + input.checked = !this._element.classList.contains(ClassName.ACTIVE) + $(input).trigger('change') } - } - if (addAriaPressed) { - this._element.setAttribute('aria-pressed', - !this._element.classList.contains(ClassName.ACTIVE)) + input.focus() + addAriaPressed = false } + } - if (triggerChangeEvent) { - $(this._element).toggleClass(ClassName.ACTIVE) - } + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', + !this._element.classList.contains(ClassName.ACTIVE)) } - dispose() { - $.removeData(this._element, DATA_KEY) - this._element = null + if (triggerChangeEvent) { + $(this._element).toggleClass(ClassName.ACTIVE) } + } - // Static + dispose() { + $.removeData(this._element, DATA_KEY) + this._element = null + } - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) + // Static - if (!data) { - data = new Button(this) - $(this).data(DATA_KEY, data) - } + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) - if (config === 'toggle') { - data[config]() - } - }) - } + if (!data) { + data = new Button(this) + $(this).data(DATA_KEY, data) + } + + if (config === 'toggle') { + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - $(document) - .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { - event.preventDefault() +$(document) + .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { + event.preventDefault() - let button = event.target + let button = event.target - if (!$(button).hasClass(ClassName.BUTTON)) { - button = $(button).closest(Selector.BUTTON) - } + if (!$(button).hasClass(ClassName.BUTTON)) { + button = $(button).closest(Selector.BUTTON) + } - Button._jQueryInterface.call($(button), 'toggle') - }) - .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { - const button = $(event.target).closest(Selector.BUTTON)[0] - $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)) - }) + Button._jQueryInterface.call($(button), 'toggle') + }) + .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { + const button = $(event.target).closest(Selector.BUTTON)[0] + $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)) + }) - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Button._jQueryInterface - $.fn[NAME].Constructor = Button - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Button._jQueryInterface - } +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Button -})($) +$.fn[NAME] = Button._jQueryInterface +$.fn[NAME].Constructor = Button +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Button._jQueryInterface +} export default Button diff --git a/vendor/twbs/bootstrap/js/src/carousel.js b/vendor/twbs/bootstrap/js/src/carousel.js index 62af5cdb1..36176dd9c 100644 --- a/vendor/twbs/bootstrap/js/src/carousel.js +++ b/vendor/twbs/bootstrap/js/src/carousel.js @@ -1,520 +1,606 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): carousel.js + * Bootstrap (v4.3.1): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Carousel = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'carousel' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.carousel' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key - const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key - const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch - - const Default = { - interval : 5000, - keyboard : true, - slide : false, - pause : 'hover', - wrap : true - } +import $ from 'jquery' +import Util from './util' - const DefaultType = { - interval : '(number|boolean)', - keyboard : 'boolean', - slide : '(boolean|string)', - pause : '(string|boolean)', - wrap : 'boolean' - } +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - const Direction = { - NEXT : 'next', - PREV : 'prev', - LEFT : 'left', - RIGHT : 'right' - } +const NAME = 'carousel' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.carousel' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] +const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key +const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key +const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch +const SWIPE_THRESHOLD = 40 + +const Default = { + interval : 5000, + keyboard : true, + slide : false, + pause : 'hover', + wrap : true, + touch : true +} + +const DefaultType = { + interval : '(number|boolean)', + keyboard : 'boolean', + slide : '(boolean|string)', + pause : '(string|boolean)', + wrap : 'boolean', + touch : 'boolean' +} + +const Direction = { + NEXT : 'next', + PREV : 'prev', + LEFT : 'left', + RIGHT : 'right' +} + +const Event = { + SLIDE : `slide${EVENT_KEY}`, + SLID : `slid${EVENT_KEY}`, + KEYDOWN : `keydown${EVENT_KEY}`, + MOUSEENTER : `mouseenter${EVENT_KEY}`, + MOUSELEAVE : `mouseleave${EVENT_KEY}`, + TOUCHSTART : `touchstart${EVENT_KEY}`, + TOUCHMOVE : `touchmove${EVENT_KEY}`, + TOUCHEND : `touchend${EVENT_KEY}`, + POINTERDOWN : `pointerdown${EVENT_KEY}`, + POINTERUP : `pointerup${EVENT_KEY}`, + DRAG_START : `dragstart${EVENT_KEY}`, + LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + CAROUSEL : 'carousel', + ACTIVE : 'active', + SLIDE : 'slide', + RIGHT : 'carousel-item-right', + LEFT : 'carousel-item-left', + NEXT : 'carousel-item-next', + PREV : 'carousel-item-prev', + ITEM : 'carousel-item', + POINTER_EVENT : 'pointer-event' +} + +const Selector = { + ACTIVE : '.active', + ACTIVE_ITEM : '.active.carousel-item', + ITEM : '.carousel-item', + ITEM_IMG : '.carousel-item img', + NEXT_PREV : '.carousel-item-next, .carousel-item-prev', + INDICATORS : '.carousel-indicators', + DATA_SLIDE : '[data-slide], [data-slide-to]', + DATA_RIDE : '[data-ride="carousel"]' +} + +const PointerType = { + TOUCH : 'touch', + PEN : 'pen' +} - const Event = { - SLIDE : `slide${EVENT_KEY}`, - SLID : `slid${EVENT_KEY}`, - KEYDOWN : `keydown${EVENT_KEY}`, - MOUSEENTER : `mouseenter${EVENT_KEY}`, - MOUSELEAVE : `mouseleave${EVENT_KEY}`, - TOUCHEND : `touchend${EVENT_KEY}`, - LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ +class Carousel { + constructor(element, config) { + this._items = null + this._interval = null + this._activeElement = null + this._isPaused = false + this._isSliding = false + this.touchTimeout = null + this.touchStartX = 0 + this.touchDeltaX = 0 + + this._config = this._getConfig(config) + this._element = element + this._indicatorsElement = this._element.querySelector(Selector.INDICATORS) + this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 + this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent) + + this._addEventListeners() } - const ClassName = { - CAROUSEL : 'carousel', - ACTIVE : 'active', - SLIDE : 'slide', - RIGHT : 'carousel-item-right', - LEFT : 'carousel-item-left', - NEXT : 'carousel-item-next', - PREV : 'carousel-item-prev', - ITEM : 'carousel-item' + // Getters + + static get VERSION() { + return VERSION } - const Selector = { - ACTIVE : '.active', - ACTIVE_ITEM : '.active.carousel-item', - ITEM : '.carousel-item', - NEXT_PREV : '.carousel-item-next, .carousel-item-prev', - INDICATORS : '.carousel-indicators', - DATA_SLIDE : '[data-slide], [data-slide-to]', - DATA_RIDE : '[data-ride="carousel"]' + static get Default() { + return Default } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + // Public - class Carousel { - constructor(element, config) { - this._items = null - this._interval = null - this._activeElement = null + next() { + if (!this._isSliding) { + this._slide(Direction.NEXT) + } + } - this._isPaused = false - this._isSliding = false + nextWhenVisible() { + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && + ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) { + this.next() + } + } - this.touchTimeout = null + prev() { + if (!this._isSliding) { + this._slide(Direction.PREV) + } + } - this._config = this._getConfig(config) - this._element = $(element)[0] - this._indicatorsElement = this._element.querySelector(Selector.INDICATORS) + pause(event) { + if (!event) { + this._isPaused = true + } - this._addEventListeners() + if (this._element.querySelector(Selector.NEXT_PREV)) { + Util.triggerTransitionEnd(this._element) + this.cycle(true) } - // Getters + clearInterval(this._interval) + this._interval = null + } - static get VERSION() { - return VERSION + cycle(event) { + if (!event) { + this._isPaused = false } - static get Default() { - return Default + if (this._interval) { + clearInterval(this._interval) + this._interval = null } - // Public - - next() { - if (!this._isSliding) { - this._slide(Direction.NEXT) - } + if (this._config.interval && !this._isPaused) { + this._interval = setInterval( + (document.visibilityState ? this.nextWhenVisible : this.next).bind(this), + this._config.interval + ) } + } - nextWhenVisible() { - // Don't call next when the page isn't visible - // or the carousel or its parent isn't visible - if (!document.hidden && - ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) { - this.next() - } + to(index) { + this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) + + const activeIndex = this._getItemIndex(this._activeElement) + + if (index > this._items.length - 1 || index < 0) { + return } - prev() { - if (!this._isSliding) { - this._slide(Direction.PREV) - } + if (this._isSliding) { + $(this._element).one(Event.SLID, () => this.to(index)) + return } - pause(event) { - if (!event) { - this._isPaused = true - } + if (activeIndex === index) { + this.pause() + this.cycle() + return + } - if (this._element.querySelector(Selector.NEXT_PREV)) { - Util.triggerTransitionEnd(this._element) - this.cycle(true) - } + const direction = index > activeIndex + ? Direction.NEXT + : Direction.PREV - clearInterval(this._interval) - this._interval = null - } + this._slide(direction, this._items[index]) + } - cycle(event) { - if (!event) { - this._isPaused = false - } + dispose() { + $(this._element).off(EVENT_KEY) + $.removeData(this._element, DATA_KEY) + + this._items = null + this._config = null + this._element = null + this._interval = null + this._isPaused = null + this._isSliding = null + this._activeElement = null + this._indicatorsElement = null + } - if (this._interval) { - clearInterval(this._interval) - this._interval = null - } + // Private - if (this._config.interval && !this._isPaused) { - this._interval = setInterval( - (document.visibilityState ? this.nextWhenVisible : this.next).bind(this), - this._config.interval - ) - } + _getConfig(config) { + config = { + ...Default, + ...config } + Util.typeCheckConfig(NAME, config, DefaultType) + return config + } - to(index) { - this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) + _handleSwipe() { + const absDeltax = Math.abs(this.touchDeltaX) - const activeIndex = this._getItemIndex(this._activeElement) + if (absDeltax <= SWIPE_THRESHOLD) { + return + } - if (index > this._items.length - 1 || index < 0) { - return - } + const direction = absDeltax / this.touchDeltaX - if (this._isSliding) { - $(this._element).one(Event.SLID, () => this.to(index)) - return - } + // swipe left + if (direction > 0) { + this.prev() + } - if (activeIndex === index) { - this.pause() - this.cycle() - return - } + // swipe right + if (direction < 0) { + this.next() + } + } - const direction = index > activeIndex - ? Direction.NEXT - : Direction.PREV + _addEventListeners() { + if (this._config.keyboard) { + $(this._element) + .on(Event.KEYDOWN, (event) => this._keydown(event)) + } - this._slide(direction, this._items[index]) + if (this._config.pause === 'hover') { + $(this._element) + .on(Event.MOUSEENTER, (event) => this.pause(event)) + .on(Event.MOUSELEAVE, (event) => this.cycle(event)) } - dispose() { - $(this._element).off(EVENT_KEY) - $.removeData(this._element, DATA_KEY) + if (this._config.touch) { + this._addTouchEventListeners() + } + } - this._items = null - this._config = null - this._element = null - this._interval = null - this._isPaused = null - this._isSliding = null - this._activeElement = null - this._indicatorsElement = null + _addTouchEventListeners() { + if (!this._touchSupported) { + return } - // Private + const start = (event) => { + if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { + this.touchStartX = event.originalEvent.clientX + } else if (!this._pointerEvent) { + this.touchStartX = event.originalEvent.touches[0].clientX + } + } - _getConfig(config) { - config = { - ...Default, - ...config + const move = (event) => { + // ensure swiping with one touch and not pinching + if (event.originalEvent.touches && event.originalEvent.touches.length > 1) { + this.touchDeltaX = 0 + } else { + this.touchDeltaX = event.originalEvent.touches[0].clientX - this.touchStartX } - Util.typeCheckConfig(NAME, config, DefaultType) - return config } - _addEventListeners() { - if (this._config.keyboard) { - $(this._element) - .on(Event.KEYDOWN, (event) => this._keydown(event)) + const end = (event) => { + if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { + this.touchDeltaX = event.originalEvent.clientX - this.touchStartX } + this._handleSwipe() if (this._config.pause === 'hover') { - $(this._element) - .on(Event.MOUSEENTER, (event) => this.pause(event)) - .on(Event.MOUSELEAVE, (event) => this.cycle(event)) - if ('ontouchstart' in document.documentElement) { - // If it's a touch-enabled device, mouseenter/leave are fired as - // part of the mouse compatibility events on first tap - the carousel - // would stop cycling until user tapped out of it; - // here, we listen for touchend, explicitly pause the carousel - // (as if it's the second time we tap on it, mouseenter compat event - // is NOT fired) and after a timeout (to allow for mouse compatibility - // events to fire) we explicitly restart cycling - $(this._element).on(Event.TOUCHEND, () => { - this.pause() - if (this.touchTimeout) { - clearTimeout(this.touchTimeout) - } - this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) - }) + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + + this.pause() + if (this.touchTimeout) { + clearTimeout(this.touchTimeout) } + this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) } } - _keydown(event) { - if (/input|textarea/i.test(event.target.tagName)) { - return - } + $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, (e) => e.preventDefault()) + if (this._pointerEvent) { + $(this._element).on(Event.POINTERDOWN, (event) => start(event)) + $(this._element).on(Event.POINTERUP, (event) => end(event)) - switch (event.which) { - case ARROW_LEFT_KEYCODE: - event.preventDefault() - this.prev() - break - case ARROW_RIGHT_KEYCODE: - event.preventDefault() - this.next() - break - default: - } + this._element.classList.add(ClassName.POINTER_EVENT) + } else { + $(this._element).on(Event.TOUCHSTART, (event) => start(event)) + $(this._element).on(Event.TOUCHMOVE, (event) => move(event)) + $(this._element).on(Event.TOUCHEND, (event) => end(event)) } + } - _getItemIndex(element) { - this._items = element && element.parentNode - ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) - : [] - return this._items.indexOf(element) + _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) { + return } - _getItemByDirection(direction, activeElement) { - const isNextDirection = direction === Direction.NEXT - const isPrevDirection = direction === Direction.PREV - const activeIndex = this._getItemIndex(activeElement) - const lastItemIndex = this._items.length - 1 - const isGoingToWrap = isPrevDirection && activeIndex === 0 || - isNextDirection && activeIndex === lastItemIndex - - if (isGoingToWrap && !this._config.wrap) { - return activeElement - } - - const delta = direction === Direction.PREV ? -1 : 1 - const itemIndex = (activeIndex + delta) % this._items.length - - return itemIndex === -1 - ? this._items[this._items.length - 1] : this._items[itemIndex] + switch (event.which) { + case ARROW_LEFT_KEYCODE: + event.preventDefault() + this.prev() + break + case ARROW_RIGHT_KEYCODE: + event.preventDefault() + this.next() + break + default: } + } - _triggerSlideEvent(relatedTarget, eventDirectionName) { - const targetIndex = this._getItemIndex(relatedTarget) - const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)) - const slideEvent = $.Event(Event.SLIDE, { - relatedTarget, - direction: eventDirectionName, - from: fromIndex, - to: targetIndex - }) + _getItemIndex(element) { + this._items = element && element.parentNode + ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) + : [] + return this._items.indexOf(element) + } - $(this._element).trigger(slideEvent) + _getItemByDirection(direction, activeElement) { + const isNextDirection = direction === Direction.NEXT + const isPrevDirection = direction === Direction.PREV + const activeIndex = this._getItemIndex(activeElement) + const lastItemIndex = this._items.length - 1 + const isGoingToWrap = isPrevDirection && activeIndex === 0 || + isNextDirection && activeIndex === lastItemIndex - return slideEvent + if (isGoingToWrap && !this._config.wrap) { + return activeElement } - _setActiveIndicatorElement(element) { - if (this._indicatorsElement) { - const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)) - $(indicators) - .removeClass(ClassName.ACTIVE) + const delta = direction === Direction.PREV ? -1 : 1 + const itemIndex = (activeIndex + delta) % this._items.length - const nextIndicator = this._indicatorsElement.children[ - this._getItemIndex(element) - ] + return itemIndex === -1 + ? this._items[this._items.length - 1] : this._items[itemIndex] + } - if (nextIndicator) { - $(nextIndicator).addClass(ClassName.ACTIVE) - } - } - } + _triggerSlideEvent(relatedTarget, eventDirectionName) { + const targetIndex = this._getItemIndex(relatedTarget) + const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)) + const slideEvent = $.Event(Event.SLIDE, { + relatedTarget, + direction: eventDirectionName, + from: fromIndex, + to: targetIndex + }) - _slide(direction, element) { - const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) - const activeElementIndex = this._getItemIndex(activeElement) - const nextElement = element || activeElement && - this._getItemByDirection(direction, activeElement) - const nextElementIndex = this._getItemIndex(nextElement) - const isCycling = Boolean(this._interval) + $(this._element).trigger(slideEvent) - let directionalClassName - let orderClassName - let eventDirectionName + return slideEvent + } - if (direction === Direction.NEXT) { - directionalClassName = ClassName.LEFT - orderClassName = ClassName.NEXT - eventDirectionName = Direction.LEFT - } else { - directionalClassName = ClassName.RIGHT - orderClassName = ClassName.PREV - eventDirectionName = Direction.RIGHT - } + _setActiveIndicatorElement(element) { + if (this._indicatorsElement) { + const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)) + $(indicators) + .removeClass(ClassName.ACTIVE) - if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { - this._isSliding = false - return - } + const nextIndicator = this._indicatorsElement.children[ + this._getItemIndex(element) + ] - const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName) - if (slideEvent.isDefaultPrevented()) { - return - } - - if (!activeElement || !nextElement) { - // Some weirdness is happening, so we bail - return + if (nextIndicator) { + $(nextIndicator).addClass(ClassName.ACTIVE) } + } + } - this._isSliding = true + _slide(direction, element) { + const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) + const activeElementIndex = this._getItemIndex(activeElement) + const nextElement = element || activeElement && + this._getItemByDirection(direction, activeElement) + const nextElementIndex = this._getItemIndex(nextElement) + const isCycling = Boolean(this._interval) + + let directionalClassName + let orderClassName + let eventDirectionName + + if (direction === Direction.NEXT) { + directionalClassName = ClassName.LEFT + orderClassName = ClassName.NEXT + eventDirectionName = Direction.LEFT + } else { + directionalClassName = ClassName.RIGHT + orderClassName = ClassName.PREV + eventDirectionName = Direction.RIGHT + } - if (isCycling) { - this.pause() - } + if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { + this._isSliding = false + return + } - this._setActiveIndicatorElement(nextElement) + const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName) + if (slideEvent.isDefaultPrevented()) { + return + } - const slidEvent = $.Event(Event.SLID, { - relatedTarget: nextElement, - direction: eventDirectionName, - from: activeElementIndex, - to: nextElementIndex - }) + if (!activeElement || !nextElement) { + // Some weirdness is happening, so we bail + return + } - if ($(this._element).hasClass(ClassName.SLIDE)) { - $(nextElement).addClass(orderClassName) + this._isSliding = true - Util.reflow(nextElement) + if (isCycling) { + this.pause() + } - $(activeElement).addClass(directionalClassName) - $(nextElement).addClass(directionalClassName) + this._setActiveIndicatorElement(nextElement) - const transitionDuration = Util.getTransitionDurationFromElement(activeElement) + const slidEvent = $.Event(Event.SLID, { + relatedTarget: nextElement, + direction: eventDirectionName, + from: activeElementIndex, + to: nextElementIndex + }) - $(activeElement) - .one(Util.TRANSITION_END, () => { - $(nextElement) - .removeClass(`${directionalClassName} ${orderClassName}`) - .addClass(ClassName.ACTIVE) + if ($(this._element).hasClass(ClassName.SLIDE)) { + $(nextElement).addClass(orderClassName) - $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`) + Util.reflow(nextElement) - this._isSliding = false + $(activeElement).addClass(directionalClassName) + $(nextElement).addClass(directionalClassName) - setTimeout(() => $(this._element).trigger(slidEvent), 0) - }) - .emulateTransitionEnd(transitionDuration) + const nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10) + if (nextElementInterval) { + this._config.defaultInterval = this._config.defaultInterval || this._config.interval + this._config.interval = nextElementInterval } else { - $(activeElement).removeClass(ClassName.ACTIVE) - $(nextElement).addClass(ClassName.ACTIVE) - - this._isSliding = false - $(this._element).trigger(slidEvent) + this._config.interval = this._config.defaultInterval || this._config.interval } - if (isCycling) { - this.cycle() - } - } + const transitionDuration = Util.getTransitionDurationFromElement(activeElement) - // Static + $(activeElement) + .one(Util.TRANSITION_END, () => { + $(nextElement) + .removeClass(`${directionalClassName} ${orderClassName}`) + .addClass(ClassName.ACTIVE) - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - let _config = { - ...Default, - ...$(this).data() - } + $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`) - if (typeof config === 'object') { - _config = { - ..._config, - ...config - } - } + this._isSliding = false - const action = typeof config === 'string' ? config : _config.slide + setTimeout(() => $(this._element).trigger(slidEvent), 0) + }) + .emulateTransitionEnd(transitionDuration) + } else { + $(activeElement).removeClass(ClassName.ACTIVE) + $(nextElement).addClass(ClassName.ACTIVE) - if (!data) { - data = new Carousel(this, _config) - $(this).data(DATA_KEY, data) - } + this._isSliding = false + $(this._element).trigger(slidEvent) + } - if (typeof config === 'number') { - data.to(config) - } else if (typeof action === 'string') { - if (typeof data[action] === 'undefined') { - throw new TypeError(`No method named "${action}"`) - } - data[action]() - } else if (_config.interval) { - data.pause() - data.cycle() - } - }) + if (isCycling) { + this.cycle() } + } - static _dataApiClickHandler(event) { - const selector = Util.getSelectorFromElement(this) + // Static - if (!selector) { - return + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + let _config = { + ...Default, + ...$(this).data() } - const target = $(selector)[0] - - if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { - return + if (typeof config === 'object') { + _config = { + ..._config, + ...config + } } - const config = { - ...$(target).data(), - ...$(this).data() + const action = typeof config === 'string' ? config : _config.slide + + if (!data) { + data = new Carousel(this, _config) + $(this).data(DATA_KEY, data) } - const slideIndex = this.getAttribute('data-slide-to') - if (slideIndex) { - config.interval = false + if (typeof config === 'number') { + data.to(config) + } else if (typeof action === 'string') { + if (typeof data[action] === 'undefined') { + throw new TypeError(`No method named "${action}"`) + } + data[action]() + } else if (_config.interval && _config.ride) { + data.pause() + data.cycle() } + }) + } - Carousel._jQueryInterface.call($(target), config) + static _dataApiClickHandler(event) { + const selector = Util.getSelectorFromElement(this) - if (slideIndex) { - $(target).data(DATA_KEY).to(slideIndex) - } + if (!selector) { + return + } + + const target = $(selector)[0] - event.preventDefault() + if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { + return } + + const config = { + ...$(target).data(), + ...$(this).data() + } + const slideIndex = this.getAttribute('data-slide-to') + + if (slideIndex) { + config.interval = false + } + + Carousel._jQueryInterface.call($(target), config) + + if (slideIndex) { + $(target).data(DATA_KEY).to(slideIndex) + } + + event.preventDefault() } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ - - $(document) - .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler) - - $(window).on(Event.LOAD_DATA_API, () => { - const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)) - for (let i = 0, len = carousels.length; i < len; i++) { - const $carousel = $(carousels[i]) - Carousel._jQueryInterface.call($carousel, $carousel.data()) - } - }) - - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Carousel._jQueryInterface - $.fn[NAME].Constructor = Carousel - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Carousel._jQueryInterface +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + +$(document) + .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler) + +$(window).on(Event.LOAD_DATA_API, () => { + const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)) + for (let i = 0, len = carousels.length; i < len; i++) { + const $carousel = $(carousels[i]) + Carousel._jQueryInterface.call($carousel, $carousel.data()) } +}) + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Carousel -})($) +$.fn[NAME] = Carousel._jQueryInterface +$.fn[NAME].Constructor = Carousel +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Carousel._jQueryInterface +} export default Carousel diff --git a/vendor/twbs/bootstrap/js/src/collapse.js b/vendor/twbs/bootstrap/js/src/collapse.js index 9277420a2..10df450d0 100644 --- a/vendor/twbs/bootstrap/js/src/collapse.js +++ b/vendor/twbs/bootstrap/js/src/collapse.js @@ -1,398 +1,402 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): collapse.js + * Bootstrap (v4.3.1): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Collapse = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'collapse' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.collapse' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const Default = { - toggle : true, - parent : '' - } - - const DefaultType = { - toggle : 'boolean', - parent : '(string|element)' - } - - const Event = { - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` - } +import $ from 'jquery' +import Util from './util' - const ClassName = { - SHOW : 'show', - COLLAPSE : 'collapse', - COLLAPSING : 'collapsing', - COLLAPSED : 'collapsed' - } +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - const Dimension = { - WIDTH : 'width', - HEIGHT : 'height' - } +const NAME = 'collapse' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.collapse' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Default = { + toggle : true, + parent : '' +} + +const DefaultType = { + toggle : 'boolean', + parent : '(string|element)' +} + +const Event = { + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + SHOW : 'show', + COLLAPSE : 'collapse', + COLLAPSING : 'collapsing', + COLLAPSED : 'collapsed' +} + +const Dimension = { + WIDTH : 'width', + HEIGHT : 'height' +} + +const Selector = { + ACTIVES : '.show, .collapsing', + DATA_TOGGLE : '[data-toggle="collapse"]' +} - const Selector = { - ACTIVES : '.show, .collapsing', - DATA_TOGGLE : '[data-toggle="collapse"]' - } +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class Collapse { - constructor(element, config) { - this._isTransitioning = false - this._element = element - this._config = this._getConfig(config) - this._triggerArray = $.makeArray(document.querySelectorAll( - `[data-toggle="collapse"][href="#${element.id}"],` + - `[data-toggle="collapse"][data-target="#${element.id}"]` - )) - const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) - for (let i = 0, len = toggleList.length; i < len; i++) { - const elem = toggleList[i] - const selector = Util.getSelectorFromElement(elem) - const filterElement = [].slice.call(document.querySelectorAll(selector)) - .filter((foundElem) => foundElem === element) - - if (selector !== null && filterElement.length > 0) { - this._selector = selector - this._triggerArray.push(elem) - } +class Collapse { + constructor(element, config) { + this._isTransitioning = false + this._element = element + this._config = this._getConfig(config) + this._triggerArray = [].slice.call(document.querySelectorAll( + `[data-toggle="collapse"][href="#${element.id}"],` + + `[data-toggle="collapse"][data-target="#${element.id}"]` + )) + + const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) + for (let i = 0, len = toggleList.length; i < len; i++) { + const elem = toggleList[i] + const selector = Util.getSelectorFromElement(elem) + const filterElement = [].slice.call(document.querySelectorAll(selector)) + .filter((foundElem) => foundElem === element) + + if (selector !== null && filterElement.length > 0) { + this._selector = selector + this._triggerArray.push(elem) } + } - this._parent = this._config.parent ? this._getParent() : null + this._parent = this._config.parent ? this._getParent() : null - if (!this._config.parent) { - this._addAriaAndCollapsedClass(this._element, this._triggerArray) - } + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray) + } - if (this._config.toggle) { - this.toggle() - } + if (this._config.toggle) { + this.toggle() } + } - // Getters + // Getters - static get VERSION() { - return VERSION - } + static get VERSION() { + return VERSION + } - static get Default() { - return Default - } + static get Default() { + return Default + } - // Public + // Public - toggle() { - if ($(this._element).hasClass(ClassName.SHOW)) { - this.hide() - } else { - this.show() - } + toggle() { + if ($(this._element).hasClass(ClassName.SHOW)) { + this.hide() + } else { + this.show() } + } - show() { - if (this._isTransitioning || - $(this._element).hasClass(ClassName.SHOW)) { - return - } + show() { + if (this._isTransitioning || + $(this._element).hasClass(ClassName.SHOW)) { + return + } - let actives - let activesData + let actives + let activesData - if (this._parent) { - actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)) - .filter((elem) => elem.getAttribute('data-parent') === this._config.parent) + if (this._parent) { + actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)) + .filter((elem) => { + if (typeof this._config.parent === 'string') { + return elem.getAttribute('data-parent') === this._config.parent + } - if (actives.length === 0) { - actives = null - } - } + return elem.classList.contains(ClassName.COLLAPSE) + }) - if (actives) { - activesData = $(actives).not(this._selector).data(DATA_KEY) - if (activesData && activesData._isTransitioning) { - return - } + if (actives.length === 0) { + actives = null } + } - const startEvent = $.Event(Event.SHOW) - $(this._element).trigger(startEvent) - if (startEvent.isDefaultPrevented()) { + if (actives) { + activesData = $(actives).not(this._selector).data(DATA_KEY) + if (activesData && activesData._isTransitioning) { return } + } - if (actives) { - Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide') - if (!activesData) { - $(actives).data(DATA_KEY, null) - } + const startEvent = $.Event(Event.SHOW) + $(this._element).trigger(startEvent) + if (startEvent.isDefaultPrevented()) { + return + } + + if (actives) { + Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide') + if (!activesData) { + $(actives).data(DATA_KEY, null) } + } - const dimension = this._getDimension() + const dimension = this._getDimension() - $(this._element) - .removeClass(ClassName.COLLAPSE) - .addClass(ClassName.COLLAPSING) + $(this._element) + .removeClass(ClassName.COLLAPSE) + .addClass(ClassName.COLLAPSING) - this._element.style[dimension] = 0 + this._element.style[dimension] = 0 - if (this._triggerArray.length) { - $(this._triggerArray) - .removeClass(ClassName.COLLAPSED) - .attr('aria-expanded', true) - } + if (this._triggerArray.length) { + $(this._triggerArray) + .removeClass(ClassName.COLLAPSED) + .attr('aria-expanded', true) + } - this.setTransitioning(true) + this.setTransitioning(true) - const complete = () => { - $(this._element) - .removeClass(ClassName.COLLAPSING) - .addClass(ClassName.COLLAPSE) - .addClass(ClassName.SHOW) + const complete = () => { + $(this._element) + .removeClass(ClassName.COLLAPSING) + .addClass(ClassName.COLLAPSE) + .addClass(ClassName.SHOW) - this._element.style[dimension] = '' + this._element.style[dimension] = '' - this.setTransitioning(false) + this.setTransitioning(false) - $(this._element).trigger(Event.SHOWN) - } + $(this._element).trigger(Event.SHOWN) + } - const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) - const scrollSize = `scroll${capitalizedDimension}` - const transitionDuration = Util.getTransitionDurationFromElement(this._element) + const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) + const scrollSize = `scroll${capitalizedDimension}` + const transitionDuration = Util.getTransitionDurationFromElement(this._element) - $(this._element) - .one(Util.TRANSITION_END, complete) - .emulateTransitionEnd(transitionDuration) + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + + this._element.style[dimension] = `${this._element[scrollSize]}px` + } - this._element.style[dimension] = `${this._element[scrollSize]}px` + hide() { + if (this._isTransitioning || + !$(this._element).hasClass(ClassName.SHOW)) { + return } - hide() { - if (this._isTransitioning || - !$(this._element).hasClass(ClassName.SHOW)) { - return - } + const startEvent = $.Event(Event.HIDE) + $(this._element).trigger(startEvent) + if (startEvent.isDefaultPrevented()) { + return + } - const startEvent = $.Event(Event.HIDE) - $(this._element).trigger(startEvent) - if (startEvent.isDefaultPrevented()) { - return - } + const dimension = this._getDimension() - const dimension = this._getDimension() + this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px` - this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px` + Util.reflow(this._element) - Util.reflow(this._element) + $(this._element) + .addClass(ClassName.COLLAPSING) + .removeClass(ClassName.COLLAPSE) + .removeClass(ClassName.SHOW) - $(this._element) - .addClass(ClassName.COLLAPSING) - .removeClass(ClassName.COLLAPSE) - .removeClass(ClassName.SHOW) - - const triggerArrayLength = this._triggerArray.length - if (triggerArrayLength > 0) { - for (let i = 0; i < triggerArrayLength; i++) { - const trigger = this._triggerArray[i] - const selector = Util.getSelectorFromElement(trigger) - if (selector !== null) { - const $elem = $([].slice.call(document.querySelectorAll(selector))) - if (!$elem.hasClass(ClassName.SHOW)) { - $(trigger).addClass(ClassName.COLLAPSED) - .attr('aria-expanded', false) - } + const triggerArrayLength = this._triggerArray.length + if (triggerArrayLength > 0) { + for (let i = 0; i < triggerArrayLength; i++) { + const trigger = this._triggerArray[i] + const selector = Util.getSelectorFromElement(trigger) + + if (selector !== null) { + const $elem = $([].slice.call(document.querySelectorAll(selector))) + if (!$elem.hasClass(ClassName.SHOW)) { + $(trigger).addClass(ClassName.COLLAPSED) + .attr('aria-expanded', false) } } } + } - this.setTransitioning(true) - - const complete = () => { - this.setTransitioning(false) - $(this._element) - .removeClass(ClassName.COLLAPSING) - .addClass(ClassName.COLLAPSE) - .trigger(Event.HIDDEN) - } - - this._element.style[dimension] = '' - const transitionDuration = Util.getTransitionDurationFromElement(this._element) + this.setTransitioning(true) + const complete = () => { + this.setTransitioning(false) $(this._element) - .one(Util.TRANSITION_END, complete) - .emulateTransitionEnd(transitionDuration) + .removeClass(ClassName.COLLAPSING) + .addClass(ClassName.COLLAPSE) + .trigger(Event.HIDDEN) } - setTransitioning(isTransitioning) { - this._isTransitioning = isTransitioning - } + this._element.style[dimension] = '' + const transitionDuration = Util.getTransitionDurationFromElement(this._element) - dispose() { - $.removeData(this._element, DATA_KEY) + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + } - this._config = null - this._parent = null - this._element = null - this._triggerArray = null - this._isTransitioning = null - } + setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning + } - // Private + dispose() { + $.removeData(this._element, DATA_KEY) - _getConfig(config) { - config = { - ...Default, - ...config - } - config.toggle = Boolean(config.toggle) // Coerce string values - Util.typeCheckConfig(NAME, config, DefaultType) - return config - } + this._config = null + this._parent = null + this._element = null + this._triggerArray = null + this._isTransitioning = null + } - _getDimension() { - const hasWidth = $(this._element).hasClass(Dimension.WIDTH) - return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT + // Private + + _getConfig(config) { + config = { + ...Default, + ...config } + config.toggle = Boolean(config.toggle) // Coerce string values + Util.typeCheckConfig(NAME, config, DefaultType) + return config + } - _getParent() { - let parent = null - if (Util.isElement(this._config.parent)) { - parent = this._config.parent + _getDimension() { + const hasWidth = $(this._element).hasClass(Dimension.WIDTH) + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT + } - // It's a jQuery object - if (typeof this._config.parent.jquery !== 'undefined') { - parent = this._config.parent[0] - } - } else { - parent = document.querySelector(this._config.parent) + _getParent() { + let parent + + if (Util.isElement(this._config.parent)) { + parent = this._config.parent + + // It's a jQuery object + if (typeof this._config.parent.jquery !== 'undefined') { + parent = this._config.parent[0] } + } else { + parent = document.querySelector(this._config.parent) + } - const selector = - `[data-toggle="collapse"][data-parent="${this._config.parent}"]` + const selector = + `[data-toggle="collapse"][data-parent="${this._config.parent}"]` - const children = [].slice.call(parent.querySelectorAll(selector)) - $(children).each((i, element) => { - this._addAriaAndCollapsedClass( - Collapse._getTargetFromElement(element), - [element] - ) - }) + const children = [].slice.call(parent.querySelectorAll(selector)) + $(children).each((i, element) => { + this._addAriaAndCollapsedClass( + Collapse._getTargetFromElement(element), + [element] + ) + }) - return parent - } + return parent + } - _addAriaAndCollapsedClass(element, triggerArray) { - if (element) { - const isOpen = $(element).hasClass(ClassName.SHOW) + _addAriaAndCollapsedClass(element, triggerArray) { + const isOpen = $(element).hasClass(ClassName.SHOW) - if (triggerArray.length) { - $(triggerArray) - .toggleClass(ClassName.COLLAPSED, !isOpen) - .attr('aria-expanded', isOpen) - } - } + if (triggerArray.length) { + $(triggerArray) + .toggleClass(ClassName.COLLAPSED, !isOpen) + .attr('aria-expanded', isOpen) } + } - // Static + // Static - static _getTargetFromElement(element) { - const selector = Util.getSelectorFromElement(element) - return selector ? document.querySelector(selector) : null - } + static _getTargetFromElement(element) { + const selector = Util.getSelectorFromElement(element) + return selector ? document.querySelector(selector) : null + } - static _jQueryInterface(config) { - return this.each(function () { - const $this = $(this) - let data = $this.data(DATA_KEY) - const _config = { - ...Default, - ...$this.data(), - ...typeof config === 'object' && config ? config : {} - } + static _jQueryInterface(config) { + return this.each(function () { + const $this = $(this) + let data = $this.data(DATA_KEY) + const _config = { + ...Default, + ...$this.data(), + ...typeof config === 'object' && config ? config : {} + } - if (!data && _config.toggle && /show|hide/.test(config)) { - _config.toggle = false - } + if (!data && _config.toggle && /show|hide/.test(config)) { + _config.toggle = false + } - if (!data) { - data = new Collapse(this, _config) - $this.data(DATA_KEY, data) - } + if (!data) { + data = new Collapse(this, _config) + $this.data(DATA_KEY, data) + } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - // preventDefault only for <a> elements (which change the URL) not inside the collapsible element - if (event.currentTarget.tagName === 'A') { - event.preventDefault() - } +$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + // preventDefault only for <a> elements (which change the URL) not inside the collapsible element + if (event.currentTarget.tagName === 'A') { + event.preventDefault() + } - const $trigger = $(this) - const selector = Util.getSelectorFromElement(this) - const selectors = [].slice.call(document.querySelectorAll(selector)) - $(selectors).each(function () { - const $target = $(this) - const data = $target.data(DATA_KEY) - const config = data ? 'toggle' : $trigger.data() - Collapse._jQueryInterface.call($target, config) - }) + const $trigger = $(this) + const selector = Util.getSelectorFromElement(this) + const selectors = [].slice.call(document.querySelectorAll(selector)) + + $(selectors).each(function () { + const $target = $(this) + const data = $target.data(DATA_KEY) + const config = data ? 'toggle' : $trigger.data() + Collapse._jQueryInterface.call($target, config) }) +}) - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Collapse._jQueryInterface - $.fn[NAME].Constructor = Collapse - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Collapse._jQueryInterface - } +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Collapse -})($) +$.fn[NAME] = Collapse._jQueryInterface +$.fn[NAME].Constructor = Collapse +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Collapse._jQueryInterface +} export default Collapse diff --git a/vendor/twbs/bootstrap/js/src/dropdown.js b/vendor/twbs/bootstrap/js/src/dropdown.js index 072bce6e3..d336a46d9 100644 --- a/vendor/twbs/bootstrap/js/src/dropdown.js +++ b/vendor/twbs/bootstrap/js/src/dropdown.js @@ -1,494 +1,545 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.3.1): dropdown.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + import $ from 'jquery' import Popper from 'popper.js' import Util from './util' /** - * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): dropdown.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ */ -const Dropdown = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'dropdown' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.dropdown' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key - const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key - const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key - const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key - const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key - const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse) - const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`) - - const Event = { - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - CLICK : `click${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, - KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`, - KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}` - } +const NAME = 'dropdown' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.dropdown' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] +const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key +const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key +const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key +const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key +const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key +const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse) +const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`) + +const Event = { + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + CLICK : `click${EVENT_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, + KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`, + KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + DISABLED : 'disabled', + SHOW : 'show', + DROPUP : 'dropup', + DROPRIGHT : 'dropright', + DROPLEFT : 'dropleft', + MENURIGHT : 'dropdown-menu-right', + MENULEFT : 'dropdown-menu-left', + POSITION_STATIC : 'position-static' +} + +const Selector = { + DATA_TOGGLE : '[data-toggle="dropdown"]', + FORM_CHILD : '.dropdown form', + MENU : '.dropdown-menu', + NAVBAR_NAV : '.navbar-nav', + VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' +} + +const AttachmentMap = { + TOP : 'top-start', + TOPEND : 'top-end', + BOTTOM : 'bottom-start', + BOTTOMEND : 'bottom-end', + RIGHT : 'right-start', + RIGHTEND : 'right-end', + LEFT : 'left-start', + LEFTEND : 'left-end' +} + +const Default = { + offset : 0, + flip : true, + boundary : 'scrollParent', + reference : 'toggle', + display : 'dynamic' +} + +const DefaultType = { + offset : '(number|string|function)', + flip : 'boolean', + boundary : '(string|element)', + reference : '(string|element)', + display : 'string' +} - const ClassName = { - DISABLED : 'disabled', - SHOW : 'show', - DROPUP : 'dropup', - DROPRIGHT : 'dropright', - DROPLEFT : 'dropleft', - MENURIGHT : 'dropdown-menu-right', - MENULEFT : 'dropdown-menu-left', - POSITION_STATIC : 'position-static' - } +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Dropdown { + constructor(element, config) { + this._element = element + this._popper = null + this._config = this._getConfig(config) + this._menu = this._getMenuElement() + this._inNavbar = this._detectNavbar() - const Selector = { - DATA_TOGGLE : '[data-toggle="dropdown"]', - FORM_CHILD : '.dropdown form', - MENU : '.dropdown-menu', - NAVBAR_NAV : '.navbar-nav', - VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' + this._addEventListeners() } - const AttachmentMap = { - TOP : 'top-start', - TOPEND : 'top-end', - BOTTOM : 'bottom-start', - BOTTOMEND : 'bottom-end', - RIGHT : 'right-start', - RIGHTEND : 'right-end', - LEFT : 'left-start', - LEFTEND : 'left-end' + // Getters + + static get VERSION() { + return VERSION } - const Default = { - offset : 0, - flip : true, - boundary : 'scrollParent', - reference : 'toggle', - display : 'dynamic' + static get Default() { + return Default } - const DefaultType = { - offset : '(number|string|function)', - flip : 'boolean', - boundary : '(string|element)', - reference : '(string|element)', - display : 'string' + static get DefaultType() { + return DefaultType } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class Dropdown { - constructor(element, config) { - this._element = element - this._popper = null - this._config = this._getConfig(config) - this._menu = this._getMenuElement() - this._inNavbar = this._detectNavbar() - - this._addEventListeners() + // Public + + toggle() { + if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { + return } - // Getters + const parent = Dropdown._getParentFromElement(this._element) + const isActive = $(this._menu).hasClass(ClassName.SHOW) - static get VERSION() { - return VERSION - } + Dropdown._clearMenus() - static get Default() { - return Default + if (isActive) { + return } - static get DefaultType() { - return DefaultType + const relatedTarget = { + relatedTarget: this._element } + const showEvent = $.Event(Event.SHOW, relatedTarget) + + $(parent).trigger(showEvent) - // Public + if (showEvent.isDefaultPrevented()) { + return + } - toggle() { - if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { - return + // Disable totally Popper.js for Dropdown in Navbar + if (!this._inNavbar) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap\'s dropdowns require Popper.js (https://popper.js.org/)') } - const parent = Dropdown._getParentFromElement(this._element) - const isActive = $(this._menu).hasClass(ClassName.SHOW) + let referenceElement = this._element - Dropdown._clearMenus() + if (this._config.reference === 'parent') { + referenceElement = parent + } else if (Util.isElement(this._config.reference)) { + referenceElement = this._config.reference - if (isActive) { - return + // Check if it's jQuery element + if (typeof this._config.reference.jquery !== 'undefined') { + referenceElement = this._config.reference[0] + } } - const relatedTarget = { - relatedTarget: this._element + // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + if (this._config.boundary !== 'scrollParent') { + $(parent).addClass(ClassName.POSITION_STATIC) } - const showEvent = $.Event(Event.SHOW, relatedTarget) - - $(parent).trigger(showEvent) + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) + } - if (showEvent.isDefaultPrevented()) { - return - } + // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + if ('ontouchstart' in document.documentElement && + $(parent).closest(Selector.NAVBAR_NAV).length === 0) { + $(document.body).children().on('mouseover', null, $.noop) + } - // Disable totally Popper.js for Dropdown in Navbar - if (!this._inNavbar) { - /** - * Check for Popper dependency - * Popper - https://popper.js.org - */ - if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)') - } + this._element.focus() + this._element.setAttribute('aria-expanded', true) - let referenceElement = this._element + $(this._menu).toggleClass(ClassName.SHOW) + $(parent) + .toggleClass(ClassName.SHOW) + .trigger($.Event(Event.SHOWN, relatedTarget)) + } - if (this._config.reference === 'parent') { - referenceElement = parent - } else if (Util.isElement(this._config.reference)) { - referenceElement = this._config.reference + show() { + if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) { + return + } - // Check if it's jQuery element - if (typeof this._config.reference.jquery !== 'undefined') { - referenceElement = this._config.reference[0] - } - } + const relatedTarget = { + relatedTarget: this._element + } + const showEvent = $.Event(Event.SHOW, relatedTarget) + const parent = Dropdown._getParentFromElement(this._element) - // If boundary is not `scrollParent`, then set position to `static` - // to allow the menu to "escape" the scroll parent's boundaries - // https://github.com/twbs/bootstrap/issues/24251 - if (this._config.boundary !== 'scrollParent') { - $(parent).addClass(ClassName.POSITION_STATIC) - } - this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) - } + $(parent).trigger(showEvent) - // If this is a touch-enabled device we add extra - // empty mouseover listeners to the body's immediate children; - // only needed because of broken event delegation on iOS - // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html - if ('ontouchstart' in document.documentElement && - $(parent).closest(Selector.NAVBAR_NAV).length === 0) { - $(document.body).children().on('mouseover', null, $.noop) - } + if (showEvent.isDefaultPrevented()) { + return + } - this._element.focus() - this._element.setAttribute('aria-expanded', true) + $(this._menu).toggleClass(ClassName.SHOW) + $(parent) + .toggleClass(ClassName.SHOW) + .trigger($.Event(Event.SHOWN, relatedTarget)) + } - $(this._menu).toggleClass(ClassName.SHOW) - $(parent) - .toggleClass(ClassName.SHOW) - .trigger($.Event(Event.SHOWN, relatedTarget)) + hide() { + if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) { + return } - dispose() { - $.removeData(this._element, DATA_KEY) - $(this._element).off(EVENT_KEY) - this._element = null - this._menu = null - if (this._popper !== null) { - this._popper.destroy() - this._popper = null - } + const relatedTarget = { + relatedTarget: this._element } + const hideEvent = $.Event(Event.HIDE, relatedTarget) + const parent = Dropdown._getParentFromElement(this._element) - update() { - this._inNavbar = this._detectNavbar() - if (this._popper !== null) { - this._popper.scheduleUpdate() - } + $(parent).trigger(hideEvent) + + if (hideEvent.isDefaultPrevented()) { + return } - // Private + $(this._menu).toggleClass(ClassName.SHOW) + $(parent) + .toggleClass(ClassName.SHOW) + .trigger($.Event(Event.HIDDEN, relatedTarget)) + } - _addEventListeners() { - $(this._element).on(Event.CLICK, (event) => { - event.preventDefault() - event.stopPropagation() - this.toggle() - }) + dispose() { + $.removeData(this._element, DATA_KEY) + $(this._element).off(EVENT_KEY) + this._element = null + this._menu = null + if (this._popper !== null) { + this._popper.destroy() + this._popper = null } + } - _getConfig(config) { - config = { - ...this.constructor.Default, - ...$(this._element).data(), - ...config - } + update() { + this._inNavbar = this._detectNavbar() + if (this._popper !== null) { + this._popper.scheduleUpdate() + } + } - Util.typeCheckConfig( - NAME, - config, - this.constructor.DefaultType - ) + // Private - return config + _addEventListeners() { + $(this._element).on(Event.CLICK, (event) => { + event.preventDefault() + event.stopPropagation() + this.toggle() + }) + } + + _getConfig(config) { + config = { + ...this.constructor.Default, + ...$(this._element).data(), + ...config } - _getMenuElement() { - if (!this._menu) { - const parent = Dropdown._getParentFromElement(this._element) - if (parent) { - this._menu = parent.querySelector(Selector.MENU) - } + Util.typeCheckConfig( + NAME, + config, + this.constructor.DefaultType + ) + + return config + } + + _getMenuElement() { + if (!this._menu) { + const parent = Dropdown._getParentFromElement(this._element) + + if (parent) { + this._menu = parent.querySelector(Selector.MENU) } - return this._menu } + return this._menu + } - _getPlacement() { - const $parentDropdown = $(this._element.parentNode) - let placement = AttachmentMap.BOTTOM + _getPlacement() { + const $parentDropdown = $(this._element.parentNode) + let placement = AttachmentMap.BOTTOM - // Handle dropup - if ($parentDropdown.hasClass(ClassName.DROPUP)) { - placement = AttachmentMap.TOP - if ($(this._menu).hasClass(ClassName.MENURIGHT)) { - placement = AttachmentMap.TOPEND - } - } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { - placement = AttachmentMap.RIGHT - } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { - placement = AttachmentMap.LEFT - } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { - placement = AttachmentMap.BOTTOMEND + // Handle dropup + if ($parentDropdown.hasClass(ClassName.DROPUP)) { + placement = AttachmentMap.TOP + if ($(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.TOPEND } - return placement + } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { + placement = AttachmentMap.RIGHT + } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { + placement = AttachmentMap.LEFT + } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND } + return placement + } - _detectNavbar() { - return $(this._element).closest('.navbar').length > 0 - } + _detectNavbar() { + return $(this._element).closest('.navbar').length > 0 + } - _getPopperConfig() { - const offsetConf = {} - if (typeof this._config.offset === 'function') { - offsetConf.fn = (data) => { - data.offsets = { - ...data.offsets, - ...this._config.offset(data.offsets) || {} - } - return data - } - } else { - offsetConf.offset = this._config.offset - } + _getOffset() { + const offset = {} - const popperConfig = { - placement: this._getPlacement(), - modifiers: { - offset: offsetConf, - flip: { - enabled: this._config.flip - }, - preventOverflow: { - boundariesElement: this._config.boundary - } + if (typeof this._config.offset === 'function') { + offset.fn = (data) => { + data.offsets = { + ...data.offsets, + ...this._config.offset(data.offsets, this._element) || {} } + + return data } + } else { + offset.offset = this._config.offset + } + + return offset + } - // Disable Popper.js if we have a static display - if (this._config.display === 'static') { - popperConfig.modifiers.applyStyle = { - enabled: false + _getPopperConfig() { + const popperConfig = { + placement: this._getPlacement(), + modifiers: { + offset: this._getOffset(), + flip: { + enabled: this._config.flip + }, + preventOverflow: { + boundariesElement: this._config.boundary } } - return popperConfig } - // Static + // Disable Popper.js if we have a static display + if (this._config.display === 'static') { + popperConfig.modifiers.applyStyle = { + enabled: false + } + } - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = typeof config === 'object' ? config : null + return popperConfig + } - if (!data) { - data = new Dropdown(this, _config) - $(this).data(DATA_KEY, data) - } + // Static - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() - } - }) - } + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' ? config : null - static _clearMenus(event) { - if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || - event.type === 'keyup' && event.which !== TAB_KEYCODE)) { - return + if (!data) { + data = new Dropdown(this, _config) + $(this).data(DATA_KEY, data) } - const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) - for (let i = 0, len = toggles.length; i < len; i++) { - const parent = Dropdown._getParentFromElement(toggles[i]) - const context = $(toggles[i]).data(DATA_KEY) - const relatedTarget = { - relatedTarget: toggles[i] + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } + data[config]() + } + }) + } - if (event && event.type === 'click') { - relatedTarget.clickEvent = event - } + static _clearMenus(event) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || + event.type === 'keyup' && event.which !== TAB_KEYCODE)) { + return + } - if (!context) { - continue - } + const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) - const dropdownMenu = context._menu - if (!$(parent).hasClass(ClassName.SHOW)) { - continue - } - - if (event && (event.type === 'click' && - /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && - $.contains(parent, event.target)) { - continue - } + for (let i = 0, len = toggles.length; i < len; i++) { + const parent = Dropdown._getParentFromElement(toggles[i]) + const context = $(toggles[i]).data(DATA_KEY) + const relatedTarget = { + relatedTarget: toggles[i] + } - const hideEvent = $.Event(Event.HIDE, relatedTarget) - $(parent).trigger(hideEvent) - if (hideEvent.isDefaultPrevented()) { - continue - } + if (event && event.type === 'click') { + relatedTarget.clickEvent = event + } - // If this is a touch-enabled device we remove the extra - // empty mouseover listeners we added for iOS support - if ('ontouchstart' in document.documentElement) { - $(document.body).children().off('mouseover', null, $.noop) - } + if (!context) { + continue + } - toggles[i].setAttribute('aria-expanded', 'false') + const dropdownMenu = context._menu + if (!$(parent).hasClass(ClassName.SHOW)) { + continue + } - $(dropdownMenu).removeClass(ClassName.SHOW) - $(parent) - .removeClass(ClassName.SHOW) - .trigger($.Event(Event.HIDDEN, relatedTarget)) + if (event && (event.type === 'click' && + /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && + $.contains(parent, event.target)) { + continue } - } - static _getParentFromElement(element) { - let parent - const selector = Util.getSelectorFromElement(element) + const hideEvent = $.Event(Event.HIDE, relatedTarget) + $(parent).trigger(hideEvent) + if (hideEvent.isDefaultPrevented()) { + continue + } - if (selector) { - parent = document.querySelector(selector) + // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + $(document.body).children().off('mouseover', null, $.noop) } - return parent || element.parentNode + toggles[i].setAttribute('aria-expanded', 'false') + + $(dropdownMenu).removeClass(ClassName.SHOW) + $(parent) + .removeClass(ClassName.SHOW) + .trigger($.Event(Event.HIDDEN, relatedTarget)) } + } - // eslint-disable-next-line complexity - static _dataApiKeydownHandler(event) { - // If not input/textarea: - // - And not a key in REGEXP_KEYDOWN => not a dropdown command - // If input/textarea: - // - If space key => not a dropdown command - // - If key is other than escape - // - If key is not up or down => not a dropdown command - // - If trigger inside the menu => not a dropdown command - if (/input|textarea/i.test(event.target.tagName) - ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && - (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || - $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { - return - } + static _getParentFromElement(element) { + let parent + const selector = Util.getSelectorFromElement(element) - event.preventDefault() - event.stopPropagation() + if (selector) { + parent = document.querySelector(selector) + } - if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { - return - } + return parent || element.parentNode + } - const parent = Dropdown._getParentFromElement(this) - const isActive = $(parent).hasClass(ClassName.SHOW) + // eslint-disable-next-line complexity + static _dataApiKeydownHandler(event) { + // If not input/textarea: + // - And not a key in REGEXP_KEYDOWN => not a dropdown command + // If input/textarea: + // - If space key => not a dropdown command + // - If key is other than escape + // - If key is not up or down => not a dropdown command + // - If trigger inside the menu => not a dropdown command + if (/input|textarea/i.test(event.target.tagName) + ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && + (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || + $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { + return + } - if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || - isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { - if (event.which === ESCAPE_KEYCODE) { - const toggle = parent.querySelector(Selector.DATA_TOGGLE) - $(toggle).trigger('focus') - } + event.preventDefault() + event.stopPropagation() - $(this).trigger('click') - return - } + if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { + return + } - const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)) + const parent = Dropdown._getParentFromElement(this) + const isActive = $(parent).hasClass(ClassName.SHOW) - if (items.length === 0) { - return + if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { + if (event.which === ESCAPE_KEYCODE) { + const toggle = parent.querySelector(Selector.DATA_TOGGLE) + $(toggle).trigger('focus') } - let index = items.indexOf(event.target) + $(this).trigger('click') + return + } - if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up - index-- - } + const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)) - if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down - index++ - } + if (items.length === 0) { + return + } - if (index < 0) { - index = 0 - } + let index = items.indexOf(event.target) - items[index].focus() + if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up + index-- } - } - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ - - $(document) - .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler) - .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler) - .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus) - .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - event.preventDefault() - event.stopPropagation() - Dropdown._jQueryInterface.call($(this), 'toggle') - }) - .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => { - e.stopPropagation() - }) + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down + index++ + } + + if (index < 0) { + index = 0 + } - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Dropdown._jQueryInterface - $.fn[NAME].Constructor = Dropdown - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Dropdown._jQueryInterface + items[index].focus() } +} + +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + +$(document) + .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler) + .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler) + .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus) + .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault() + event.stopPropagation() + Dropdown._jQueryInterface.call($(this), 'toggle') + }) + .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => { + e.stopPropagation() + }) + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + +$.fn[NAME] = Dropdown._jQueryInterface +$.fn[NAME].Constructor = Dropdown +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Dropdown._jQueryInterface +} - return Dropdown -})($, Popper) export default Dropdown diff --git a/vendor/twbs/bootstrap/js/src/index.js b/vendor/twbs/bootstrap/js/src/index.js index 7304b69d3..c4a4d4b1f 100644 --- a/vendor/twbs/bootstrap/js/src/index.js +++ b/vendor/twbs/bootstrap/js/src/index.js @@ -8,17 +8,18 @@ import Modal from './modal' import Popover from './popover' import Scrollspy from './scrollspy' import Tab from './tab' +import Toast from './toast' import Tooltip from './tooltip' import Util from './util' /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): index.js + * Bootstrap (v4.3.1): index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -(($) => { +(() => { if (typeof $ === 'undefined') { throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.') } @@ -33,7 +34,7 @@ import Util from './util' if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') } -})($) +})() export { Util, @@ -46,5 +47,6 @@ export { Popover, Scrollspy, Tab, + Toast, Tooltip } diff --git a/vendor/twbs/bootstrap/js/src/modal.js b/vendor/twbs/bootstrap/js/src/modal.js index ddcf370b6..99fe1bf2d 100644 --- a/vendor/twbs/bootstrap/js/src/modal.js +++ b/vendor/twbs/bootstrap/js/src/modal.js @@ -1,579 +1,594 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): modal.js + * Bootstrap (v4.3.1): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Modal = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'modal' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.modal' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key - - const Default = { - backdrop : true, - keyboard : true, - focus : true, - show : true - } +import $ from 'jquery' +import Util from './util' - const DefaultType = { - backdrop : '(boolean|string)', - keyboard : 'boolean', - focus : 'boolean', - show : 'boolean' - } +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'modal' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.modal' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] +const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key + +const Default = { + backdrop : true, + keyboard : true, + focus : true, + show : true +} + +const DefaultType = { + backdrop : '(boolean|string)', + keyboard : 'boolean', + focus : 'boolean', + show : 'boolean' +} + +const Event = { + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + FOCUSIN : `focusin${EVENT_KEY}`, + RESIZE : `resize${EVENT_KEY}`, + CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, + KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`, + MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`, + MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + SCROLLABLE : 'modal-dialog-scrollable', + SCROLLBAR_MEASURER : 'modal-scrollbar-measure', + BACKDROP : 'modal-backdrop', + OPEN : 'modal-open', + FADE : 'fade', + SHOW : 'show' +} + +const Selector = { + DIALOG : '.modal-dialog', + MODAL_BODY : '.modal-body', + DATA_TOGGLE : '[data-toggle="modal"]', + DATA_DISMISS : '[data-dismiss="modal"]', + FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + STICKY_CONTENT : '.sticky-top' +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - const Event = { - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - FOCUSIN : `focusin${EVENT_KEY}`, - RESIZE : `resize${EVENT_KEY}`, - CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, - KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`, - MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`, - MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +class Modal { + constructor(element, config) { + this._config = this._getConfig(config) + this._element = element + this._dialog = element.querySelector(Selector.DIALOG) + this._backdrop = null + this._isShown = false + this._isBodyOverflowing = false + this._ignoreBackdropClick = false + this._isTransitioning = false + this._scrollbarWidth = 0 } - const ClassName = { - SCROLLBAR_MEASURER : 'modal-scrollbar-measure', - BACKDROP : 'modal-backdrop', - OPEN : 'modal-open', - FADE : 'fade', - SHOW : 'show' + // Getters + + static get VERSION() { + return VERSION } - const Selector = { - DIALOG : '.modal-dialog', - DATA_TOGGLE : '[data-toggle="modal"]', - DATA_DISMISS : '[data-dismiss="modal"]', - FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', - STICKY_CONTENT : '.sticky-top' + static get Default() { + return Default } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class Modal { - constructor(element, config) { - this._config = this._getConfig(config) - this._element = element - this._dialog = element.querySelector(Selector.DIALOG) - this._backdrop = null - this._isShown = false - this._isBodyOverflowing = false - this._ignoreBackdropClick = false - this._scrollbarWidth = 0 - } + // Public - // Getters + toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget) + } - static get VERSION() { - return VERSION + show(relatedTarget) { + if (this._isShown || this._isTransitioning) { + return } - static get Default() { - return Default + if ($(this._element).hasClass(ClassName.FADE)) { + this._isTransitioning = true } - // Public + const showEvent = $.Event(Event.SHOW, { + relatedTarget + }) - toggle(relatedTarget) { - return this._isShown ? this.hide() : this.show(relatedTarget) + $(this._element).trigger(showEvent) + + if (this._isShown || showEvent.isDefaultPrevented()) { + return } - show(relatedTarget) { - if (this._isTransitioning || this._isShown) { - return - } + this._isShown = true - if ($(this._element).hasClass(ClassName.FADE)) { - this._isTransitioning = true - } + this._checkScrollbar() + this._setScrollbar() - const showEvent = $.Event(Event.SHOW, { - relatedTarget - }) + this._adjustDialog() - $(this._element).trigger(showEvent) + this._setEscapeEvent() + this._setResizeEvent() - if (this._isShown || showEvent.isDefaultPrevented()) { - return - } + $(this._element).on( + Event.CLICK_DISMISS, + Selector.DATA_DISMISS, + (event) => this.hide(event) + ) - this._isShown = true + $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => { + $(this._element).one(Event.MOUSEUP_DISMISS, (event) => { + if ($(event.target).is(this._element)) { + this._ignoreBackdropClick = true + } + }) + }) - this._checkScrollbar() - this._setScrollbar() + this._showBackdrop(() => this._showElement(relatedTarget)) + } - this._adjustDialog() + hide(event) { + if (event) { + event.preventDefault() + } - $(document.body).addClass(ClassName.OPEN) + if (!this._isShown || this._isTransitioning) { + return + } - this._setEscapeEvent() - this._setResizeEvent() + const hideEvent = $.Event(Event.HIDE) - $(this._element).on( - Event.CLICK_DISMISS, - Selector.DATA_DISMISS, - (event) => this.hide(event) - ) + $(this._element).trigger(hideEvent) - $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => { - $(this._element).one(Event.MOUSEUP_DISMISS, (event) => { - if ($(event.target).is(this._element)) { - this._ignoreBackdropClick = true - } - }) - }) - - this._showBackdrop(() => this._showElement(relatedTarget)) + if (!this._isShown || hideEvent.isDefaultPrevented()) { + return } - hide(event) { - if (event) { - event.preventDefault() - } - - if (this._isTransitioning || !this._isShown) { - return - } + this._isShown = false + const transition = $(this._element).hasClass(ClassName.FADE) - const hideEvent = $.Event(Event.HIDE) + if (transition) { + this._isTransitioning = true + } - $(this._element).trigger(hideEvent) + this._setEscapeEvent() + this._setResizeEvent() - if (!this._isShown || hideEvent.isDefaultPrevented()) { - return - } + $(document).off(Event.FOCUSIN) - this._isShown = false - const transition = $(this._element).hasClass(ClassName.FADE) + $(this._element).removeClass(ClassName.SHOW) - if (transition) { - this._isTransitioning = true - } + $(this._element).off(Event.CLICK_DISMISS) + $(this._dialog).off(Event.MOUSEDOWN_DISMISS) - this._setEscapeEvent() - this._setResizeEvent() - $(document).off(Event.FOCUSIN) + if (transition) { + const transitionDuration = Util.getTransitionDurationFromElement(this._element) - $(this._element).removeClass(ClassName.SHOW) + $(this._element) + .one(Util.TRANSITION_END, (event) => this._hideModal(event)) + .emulateTransitionEnd(transitionDuration) + } else { + this._hideModal() + } + } - $(this._element).off(Event.CLICK_DISMISS) - $(this._dialog).off(Event.MOUSEDOWN_DISMISS) + dispose() { + [window, this._element, this._dialog] + .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY)) + + /** + * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` + * Do not move `document` in `htmlElements` array + * It will remove `Event.CLICK_DATA_API` event that should remain + */ + $(document).off(Event.FOCUSIN) + + $.removeData(this._element, DATA_KEY) + + this._config = null + this._element = null + this._dialog = null + this._backdrop = null + this._isShown = null + this._isBodyOverflowing = null + this._ignoreBackdropClick = null + this._isTransitioning = null + this._scrollbarWidth = null + } + handleUpdate() { + this._adjustDialog() + } - if (transition) { - const transitionDuration = Util.getTransitionDurationFromElement(this._element) + // Private - $(this._element) - .one(Util.TRANSITION_END, (event) => this._hideModal(event)) - .emulateTransitionEnd(transitionDuration) - } else { - this._hideModal() - } + _getConfig(config) { + config = { + ...Default, + ...config } + Util.typeCheckConfig(NAME, config, DefaultType) + return config + } - dispose() { - $.removeData(this._element, DATA_KEY) - - $(window, document, this._element, this._backdrop).off(EVENT_KEY) - - this._config = null - this._element = null - this._dialog = null - this._backdrop = null - this._isShown = null - this._isBodyOverflowing = null - this._ignoreBackdropClick = null - this._scrollbarWidth = null - } + _showElement(relatedTarget) { + const transition = $(this._element).hasClass(ClassName.FADE) - handleUpdate() { - this._adjustDialog() + if (!this._element.parentNode || + this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { + // Don't move modal's DOM position + document.body.appendChild(this._element) } - // Private + this._element.style.display = 'block' + this._element.removeAttribute('aria-hidden') + this._element.setAttribute('aria-modal', true) - _getConfig(config) { - config = { - ...Default, - ...config - } - Util.typeCheckConfig(NAME, config, DefaultType) - return config + if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) { + this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0 + } else { + this._element.scrollTop = 0 } - _showElement(relatedTarget) { - const transition = $(this._element).hasClass(ClassName.FADE) - - if (!this._element.parentNode || - this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { - // Don't move modal's DOM position - document.body.appendChild(this._element) - } + if (transition) { + Util.reflow(this._element) + } - this._element.style.display = 'block' - this._element.removeAttribute('aria-hidden') - this._element.scrollTop = 0 + $(this._element).addClass(ClassName.SHOW) - if (transition) { - Util.reflow(this._element) - } + if (this._config.focus) { + this._enforceFocus() + } - $(this._element).addClass(ClassName.SHOW) + const shownEvent = $.Event(Event.SHOWN, { + relatedTarget + }) + const transitionComplete = () => { if (this._config.focus) { - this._enforceFocus() + this._element.focus() } + this._isTransitioning = false + $(this._element).trigger(shownEvent) + } - const shownEvent = $.Event(Event.SHOWN, { - relatedTarget - }) + if (transition) { + const transitionDuration = Util.getTransitionDurationFromElement(this._dialog) + + $(this._dialog) + .one(Util.TRANSITION_END, transitionComplete) + .emulateTransitionEnd(transitionDuration) + } else { + transitionComplete() + } + } - const transitionComplete = () => { - if (this._config.focus) { + _enforceFocus() { + $(document) + .off(Event.FOCUSIN) // Guard against infinite focus loop + .on(Event.FOCUSIN, (event) => { + if (document !== event.target && + this._element !== event.target && + $(this._element).has(event.target).length === 0) { this._element.focus() } - this._isTransitioning = false - $(this._element).trigger(shownEvent) - } - - if (transition) { - const transitionDuration = Util.getTransitionDurationFromElement(this._element) + }) + } - $(this._dialog) - .one(Util.TRANSITION_END, transitionComplete) - .emulateTransitionEnd(transitionDuration) - } else { - transitionComplete() - } + _setEscapeEvent() { + if (this._isShown && this._config.keyboard) { + $(this._element).on(Event.KEYDOWN_DISMISS, (event) => { + if (event.which === ESCAPE_KEYCODE) { + event.preventDefault() + this.hide() + } + }) + } else if (!this._isShown) { + $(this._element).off(Event.KEYDOWN_DISMISS) } + } - _enforceFocus() { - $(document) - .off(Event.FOCUSIN) // Guard against infinite focus loop - .on(Event.FOCUSIN, (event) => { - if (document !== event.target && - this._element !== event.target && - $(this._element).has(event.target).length === 0) { - this._element.focus() - } - }) + _setResizeEvent() { + if (this._isShown) { + $(window).on(Event.RESIZE, (event) => this.handleUpdate(event)) + } else { + $(window).off(Event.RESIZE) } + } - _setEscapeEvent() { - if (this._isShown && this._config.keyboard) { - $(this._element).on(Event.KEYDOWN_DISMISS, (event) => { - if (event.which === ESCAPE_KEYCODE) { - event.preventDefault() - this.hide() - } - }) - } else if (!this._isShown) { - $(this._element).off(Event.KEYDOWN_DISMISS) - } + _hideModal() { + this._element.style.display = 'none' + this._element.setAttribute('aria-hidden', true) + this._element.removeAttribute('aria-modal') + this._isTransitioning = false + this._showBackdrop(() => { + $(document.body).removeClass(ClassName.OPEN) + this._resetAdjustments() + this._resetScrollbar() + $(this._element).trigger(Event.HIDDEN) + }) + } + + _removeBackdrop() { + if (this._backdrop) { + $(this._backdrop).remove() + this._backdrop = null } + } - _setResizeEvent() { - if (this._isShown) { - $(window).on(Event.RESIZE, (event) => this.handleUpdate(event)) - } else { - $(window).off(Event.RESIZE) + _showBackdrop(callback) { + const animate = $(this._element).hasClass(ClassName.FADE) + ? ClassName.FADE : '' + + if (this._isShown && this._config.backdrop) { + this._backdrop = document.createElement('div') + this._backdrop.className = ClassName.BACKDROP + + if (animate) { + this._backdrop.classList.add(animate) } - } - _hideModal() { - this._element.style.display = 'none' - this._element.setAttribute('aria-hidden', true) - this._isTransitioning = false - this._showBackdrop(() => { - $(document.body).removeClass(ClassName.OPEN) - this._resetAdjustments() - this._resetScrollbar() - $(this._element).trigger(Event.HIDDEN) + $(this._backdrop).appendTo(document.body) + + $(this._element).on(Event.CLICK_DISMISS, (event) => { + if (this._ignoreBackdropClick) { + this._ignoreBackdropClick = false + return + } + if (event.target !== event.currentTarget) { + return + } + if (this._config.backdrop === 'static') { + this._element.focus() + } else { + this.hide() + } }) - } - _removeBackdrop() { - if (this._backdrop) { - $(this._backdrop).remove() - this._backdrop = null + if (animate) { + Util.reflow(this._backdrop) } - } - _showBackdrop(callback) { - const animate = $(this._element).hasClass(ClassName.FADE) - ? ClassName.FADE : '' + $(this._backdrop).addClass(ClassName.SHOW) - if (this._isShown && this._config.backdrop) { - this._backdrop = document.createElement('div') - this._backdrop.className = ClassName.BACKDROP + if (!callback) { + return + } - if (animate) { - this._backdrop.classList.add(animate) - } + if (!animate) { + callback() + return + } - $(this._backdrop).appendTo(document.body) - - $(this._element).on(Event.CLICK_DISMISS, (event) => { - if (this._ignoreBackdropClick) { - this._ignoreBackdropClick = false - return - } - if (event.target !== event.currentTarget) { - return - } - if (this._config.backdrop === 'static') { - this._element.focus() - } else { - this.hide() - } - }) - - if (animate) { - Util.reflow(this._backdrop) - } + const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop) - $(this._backdrop).addClass(ClassName.SHOW) + $(this._backdrop) + .one(Util.TRANSITION_END, callback) + .emulateTransitionEnd(backdropTransitionDuration) + } else if (!this._isShown && this._backdrop) { + $(this._backdrop).removeClass(ClassName.SHOW) - if (!callback) { - return - } - - if (!animate) { + const callbackRemove = () => { + this._removeBackdrop() + if (callback) { callback() - return } + } + if ($(this._element).hasClass(ClassName.FADE)) { const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop) $(this._backdrop) - .one(Util.TRANSITION_END, callback) + .one(Util.TRANSITION_END, callbackRemove) .emulateTransitionEnd(backdropTransitionDuration) - } else if (!this._isShown && this._backdrop) { - $(this._backdrop).removeClass(ClassName.SHOW) - - const callbackRemove = () => { - this._removeBackdrop() - if (callback) { - callback() - } - } - - if ($(this._element).hasClass(ClassName.FADE)) { - const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop) - - $(this._backdrop) - .one(Util.TRANSITION_END, callbackRemove) - .emulateTransitionEnd(backdropTransitionDuration) - } else { - callbackRemove() - } - } else if (callback) { - callback() + } else { + callbackRemove() } + } else if (callback) { + callback() } + } - // ---------------------------------------------------------------------- - // the following methods are used to handle overflowing modals - // todo (fat): these should probably be refactored out of modal.js - // ---------------------------------------------------------------------- - - _adjustDialog() { - const isModalOverflowing = - this._element.scrollHeight > document.documentElement.clientHeight + // ---------------------------------------------------------------------- + // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js + // ---------------------------------------------------------------------- - if (!this._isBodyOverflowing && isModalOverflowing) { - this._element.style.paddingLeft = `${this._scrollbarWidth}px` - } + _adjustDialog() { + const isModalOverflowing = + this._element.scrollHeight > document.documentElement.clientHeight - if (this._isBodyOverflowing && !isModalOverflowing) { - this._element.style.paddingRight = `${this._scrollbarWidth}px` - } + if (!this._isBodyOverflowing && isModalOverflowing) { + this._element.style.paddingLeft = `${this._scrollbarWidth}px` } - _resetAdjustments() { - this._element.style.paddingLeft = '' - this._element.style.paddingRight = '' + if (this._isBodyOverflowing && !isModalOverflowing) { + this._element.style.paddingRight = `${this._scrollbarWidth}px` } + } - _checkScrollbar() { - const rect = document.body.getBoundingClientRect() - this._isBodyOverflowing = rect.left + rect.right < window.innerWidth - this._scrollbarWidth = this._getScrollbarWidth() - } + _resetAdjustments() { + this._element.style.paddingLeft = '' + this._element.style.paddingRight = '' + } - _setScrollbar() { - if (this._isBodyOverflowing) { - // Note: DOMNode.style.paddingRight returns the actual value or '' if not set - // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set - const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)) - const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)) - - // Adjust fixed content padding - $(fixedContent).each((index, element) => { - const actualPadding = element.style.paddingRight - const calculatedPadding = $(element).css('padding-right') - $(element) - .data('padding-right', actualPadding) - .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) - }) - - // Adjust sticky content margin - $(stickyContent).each((index, element) => { - const actualMargin = element.style.marginRight - const calculatedMargin = $(element).css('margin-right') - $(element) - .data('margin-right', actualMargin) - .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`) - }) - - // Adjust body padding - const actualPadding = document.body.style.paddingRight - const calculatedPadding = $(document.body).css('padding-right') - $(document.body) - .data('padding-right', actualPadding) - .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) - } - } + _checkScrollbar() { + const rect = document.body.getBoundingClientRect() + this._isBodyOverflowing = rect.left + rect.right < window.innerWidth + this._scrollbarWidth = this._getScrollbarWidth() + } - _resetScrollbar() { - // Restore fixed content padding + _setScrollbar() { + if (this._isBodyOverflowing) { + // Note: DOMNode.style.paddingRight returns the actual value or '' if not set + // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)) + const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)) + + // Adjust fixed content padding $(fixedContent).each((index, element) => { - const padding = $(element).data('padding-right') - $(element).removeData('padding-right') - element.style.paddingRight = padding ? padding : '' + const actualPadding = element.style.paddingRight + const calculatedPadding = $(element).css('padding-right') + $(element) + .data('padding-right', actualPadding) + .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) }) - // Restore sticky content - const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`)) - $(elements).each((index, element) => { - const margin = $(element).data('margin-right') - if (typeof margin !== 'undefined') { - $(element).css('margin-right', margin).removeData('margin-right') - } + // Adjust sticky content margin + $(stickyContent).each((index, element) => { + const actualMargin = element.style.marginRight + const calculatedMargin = $(element).css('margin-right') + $(element) + .data('margin-right', actualMargin) + .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`) }) - // Restore body padding - const padding = $(document.body).data('padding-right') - $(document.body).removeData('padding-right') - document.body.style.paddingRight = padding ? padding : '' + // Adjust body padding + const actualPadding = document.body.style.paddingRight + const calculatedPadding = $(document.body).css('padding-right') + $(document.body) + .data('padding-right', actualPadding) + .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) } - _getScrollbarWidth() { // thx d.walsh - const scrollDiv = document.createElement('div') - scrollDiv.className = ClassName.SCROLLBAR_MEASURER - document.body.appendChild(scrollDiv) - const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth - document.body.removeChild(scrollDiv) - return scrollbarWidth - } + $(document.body).addClass(ClassName.OPEN) + } - // Static + _resetScrollbar() { + // Restore fixed content padding + const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)) + $(fixedContent).each((index, element) => { + const padding = $(element).data('padding-right') + $(element).removeData('padding-right') + element.style.paddingRight = padding ? padding : '' + }) - static _jQueryInterface(config, relatedTarget) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = { - ...Default, - ...$(this).data(), - ...typeof config === 'object' && config ? config : {} - } + // Restore sticky content + const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`)) + $(elements).each((index, element) => { + const margin = $(element).data('margin-right') + if (typeof margin !== 'undefined') { + $(element).css('margin-right', margin).removeData('margin-right') + } + }) - if (!data) { - data = new Modal(this, _config) - $(this).data(DATA_KEY, data) - } + // Restore body padding + const padding = $(document.body).data('padding-right') + $(document.body).removeData('padding-right') + document.body.style.paddingRight = padding ? padding : '' + } + + _getScrollbarWidth() { // thx d.walsh + const scrollDiv = document.createElement('div') + scrollDiv.className = ClassName.SCROLLBAR_MEASURER + document.body.appendChild(scrollDiv) + const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth + document.body.removeChild(scrollDiv) + return scrollbarWidth + } + + // Static + + static _jQueryInterface(config, relatedTarget) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = { + ...Default, + ...$(this).data(), + ...typeof config === 'object' && config ? config : {} + } + + if (!data) { + data = new Modal(this, _config) + $(this).data(DATA_KEY, data) + } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config](relatedTarget) - } else if (_config.show) { - data.show(relatedTarget) + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config](relatedTarget) + } else if (_config.show) { + data.show(relatedTarget) + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + +$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + let target + const selector = Util.getSelectorFromElement(this) - $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - let target - const selector = Util.getSelectorFromElement(this) + if (selector) { + target = document.querySelector(selector) + } - if (selector) { - target = document.querySelector(selector) + const config = $(target).data(DATA_KEY) + ? 'toggle' : { + ...$(target).data(), + ...$(this).data() } - const config = $(target).data(DATA_KEY) - ? 'toggle' : { - ...$(target).data(), - ...$(this).data() - } + if (this.tagName === 'A' || this.tagName === 'AREA') { + event.preventDefault() + } - if (this.tagName === 'A' || this.tagName === 'AREA') { - event.preventDefault() + const $target = $(target).one(Event.SHOW, (showEvent) => { + if (showEvent.isDefaultPrevented()) { + // Only register focus restorer if modal will actually get shown + return } - const $target = $(target).one(Event.SHOW, (showEvent) => { - if (showEvent.isDefaultPrevented()) { - // Only register focus restorer if modal will actually get shown - return + $target.one(Event.HIDDEN, () => { + if ($(this).is(':visible')) { + this.focus() } - - $target.one(Event.HIDDEN, () => { - if ($(this).is(':visible')) { - this.focus() - } - }) }) - - Modal._jQueryInterface.call($(target), config, this) }) - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Modal._jQueryInterface - $.fn[NAME].Constructor = Modal - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Modal._jQueryInterface - } + Modal._jQueryInterface.call($(target), config, this) +}) + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Modal -})($) +$.fn[NAME] = Modal._jQueryInterface +$.fn[NAME].Constructor = Modal +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Modal._jQueryInterface +} export default Modal diff --git a/vendor/twbs/bootstrap/js/src/popover.js b/vendor/twbs/bootstrap/js/src/popover.js index eade7cf58..98f2f3fbe 100644 --- a/vendor/twbs/bootstrap/js/src/popover.js +++ b/vendor/twbs/bootstrap/js/src/popover.js @@ -1,188 +1,184 @@ -import $ from 'jquery' -import Tooltip from './tooltip' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): popover.js + * Bootstrap (v4.3.1): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Popover = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'popover' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.popover' - const EVENT_KEY = `.${DATA_KEY}` - const JQUERY_NO_CONFLICT = $.fn[NAME] - const CLASS_PREFIX = 'bs-popover' - const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') - - const Default = { - ...Tooltip.Default, - placement : 'right', - trigger : 'click', - content : '', - template : '<div class="popover" role="tooltip">' + - '<div class="arrow"></div>' + - '<h3 class="popover-header"></h3>' + - '<div class="popover-body"></div></div>' +import $ from 'jquery' +import Tooltip from './tooltip' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'popover' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.popover' +const EVENT_KEY = `.${DATA_KEY}` +const JQUERY_NO_CONFLICT = $.fn[NAME] +const CLASS_PREFIX = 'bs-popover' +const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') + +const Default = { + ...Tooltip.Default, + placement : 'right', + trigger : 'click', + content : '', + template : '<div class="popover" role="tooltip">' + + '<div class="arrow"></div>' + + '<h3 class="popover-header"></h3>' + + '<div class="popover-body"></div></div>' +} + +const DefaultType = { + ...Tooltip.DefaultType, + content : '(string|element|function)' +} + +const ClassName = { + FADE : 'fade', + SHOW : 'show' +} + +const Selector = { + TITLE : '.popover-header', + CONTENT : '.popover-body' +} + +const Event = { + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + INSERTED : `inserted${EVENT_KEY}`, + CLICK : `click${EVENT_KEY}`, + FOCUSIN : `focusin${EVENT_KEY}`, + FOCUSOUT : `focusout${EVENT_KEY}`, + MOUSEENTER : `mouseenter${EVENT_KEY}`, + MOUSELEAVE : `mouseleave${EVENT_KEY}` +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Popover extends Tooltip { + // Getters + + static get VERSION() { + return VERSION } - const DefaultType = { - ...Tooltip.DefaultType, - content : '(string|element|function)' + static get Default() { + return Default } - const ClassName = { - FADE : 'fade', - SHOW : 'show' + static get NAME() { + return NAME } - const Selector = { - TITLE : '.popover-header', - CONTENT : '.popover-body' + static get DATA_KEY() { + return DATA_KEY } - const Event = { - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - INSERTED : `inserted${EVENT_KEY}`, - CLICK : `click${EVENT_KEY}`, - FOCUSIN : `focusin${EVENT_KEY}`, - FOCUSOUT : `focusout${EVENT_KEY}`, - MOUSEENTER : `mouseenter${EVENT_KEY}`, - MOUSELEAVE : `mouseleave${EVENT_KEY}` + static get Event() { + return Event } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + static get EVENT_KEY() { + return EVENT_KEY + } - class Popover extends Tooltip { - // Getters + static get DefaultType() { + return DefaultType + } - static get VERSION() { - return VERSION - } + // Overrides - static get Default() { - return Default - } + isWithContent() { + return this.getTitle() || this._getContent() + } - static get NAME() { - return NAME - } + addAttachmentClass(attachment) { + $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + } - static get DATA_KEY() { - return DATA_KEY - } + getTipElement() { + this.tip = this.tip || $(this.config.template)[0] + return this.tip + } - static get Event() { - return Event - } + setContent() { + const $tip = $(this.getTipElement()) - static get EVENT_KEY() { - return EVENT_KEY + // We use append for html objects to maintain js events + this.setElementContent($tip.find(Selector.TITLE), this.getTitle()) + let content = this._getContent() + if (typeof content === 'function') { + content = content.call(this.element) } + this.setElementContent($tip.find(Selector.CONTENT), content) - static get DefaultType() { - return DefaultType - } + $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) + } - // Overrides + // Private - isWithContent() { - return this.getTitle() || this._getContent() - } + _getContent() { + return this.element.getAttribute('data-content') || + this.config.content + } - addAttachmentClass(attachment) { - $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + _cleanTipClass() { + const $tip = $(this.getTipElement()) + const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')) } + } - getTipElement() { - this.tip = this.tip || $(this.config.template)[0] - return this.tip - } + // Static - setContent() { - const $tip = $(this.getTipElement()) + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' ? config : null - // We use append for html objects to maintain js events - this.setElementContent($tip.find(Selector.TITLE), this.getTitle()) - let content = this._getContent() - if (typeof content === 'function') { - content = content.call(this.element) + if (!data && /dispose|hide/.test(config)) { + return } - this.setElementContent($tip.find(Selector.CONTENT), content) - $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) - } - - // Private - - _getContent() { - return this.element.getAttribute('data-content') || - this.config.content - } - - _cleanTipClass() { - const $tip = $(this.getTipElement()) - const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) - if (tabClass !== null && tabClass.length > 0) { - $tip.removeClass(tabClass.join('')) + if (!data) { + data = new Popover(this, _config) + $(this).data(DATA_KEY, data) } - } - // Static - - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = typeof config === 'object' ? config : null - - if (!data && /destroy|hide/.test(config)) { - return - } - - if (!data) { - data = new Popover(this, _config) - $(this).data(DATA_KEY, data) - } - - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Popover._jQueryInterface - $.fn[NAME].Constructor = Popover - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Popover._jQueryInterface - } +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Popover -})($) +$.fn[NAME] = Popover._jQueryInterface +$.fn[NAME].Constructor = Popover +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Popover._jQueryInterface +} export default Popover diff --git a/vendor/twbs/bootstrap/js/src/scrollspy.js b/vendor/twbs/bootstrap/js/src/scrollspy.js index 5cbffc650..e8cd6bf98 100644 --- a/vendor/twbs/bootstrap/js/src/scrollspy.js +++ b/vendor/twbs/bootstrap/js/src/scrollspy.js @@ -1,332 +1,326 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): scrollspy.js + * Bootstrap (v4.3.1): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const ScrollSpy = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'scrollspy' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.scrollspy' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const Default = { - offset : 10, - method : 'auto', - target : '' - } +import $ from 'jquery' +import Util from './util' - const DefaultType = { - offset : 'number', - method : 'string', - target : '(string|element)' - } +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - const Event = { - ACTIVATE : `activate${EVENT_KEY}`, - SCROLL : `scroll${EVENT_KEY}`, - LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` - } +const NAME = 'scrollspy' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.scrollspy' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Default = { + offset : 10, + method : 'auto', + target : '' +} + +const DefaultType = { + offset : 'number', + method : 'string', + target : '(string|element)' +} + +const Event = { + ACTIVATE : `activate${EVENT_KEY}`, + SCROLL : `scroll${EVENT_KEY}`, + LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + DROPDOWN_ITEM : 'dropdown-item', + DROPDOWN_MENU : 'dropdown-menu', + ACTIVE : 'active' +} + +const Selector = { + DATA_SPY : '[data-spy="scroll"]', + ACTIVE : '.active', + NAV_LIST_GROUP : '.nav, .list-group', + NAV_LINKS : '.nav-link', + NAV_ITEMS : '.nav-item', + LIST_ITEMS : '.list-group-item', + DROPDOWN : '.dropdown', + DROPDOWN_ITEMS : '.dropdown-item', + DROPDOWN_TOGGLE : '.dropdown-toggle' +} + +const OffsetMethod = { + OFFSET : 'offset', + POSITION : 'position' +} - const ClassName = { - DROPDOWN_ITEM : 'dropdown-item', - DROPDOWN_MENU : 'dropdown-menu', - ACTIVE : 'active' - } +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - const Selector = { - DATA_SPY : '[data-spy="scroll"]', - ACTIVE : '.active', - NAV_LIST_GROUP : '.nav, .list-group', - NAV_LINKS : '.nav-link', - NAV_ITEMS : '.nav-item', - LIST_ITEMS : '.list-group-item', - DROPDOWN : '.dropdown', - DROPDOWN_ITEMS : '.dropdown-item', - DROPDOWN_TOGGLE : '.dropdown-toggle' +class ScrollSpy { + constructor(element, config) { + this._element = element + this._scrollElement = element.tagName === 'BODY' ? window : element + this._config = this._getConfig(config) + this._selector = `${this._config.target} ${Selector.NAV_LINKS},` + + `${this._config.target} ${Selector.LIST_ITEMS},` + + `${this._config.target} ${Selector.DROPDOWN_ITEMS}` + this._offsets = [] + this._targets = [] + this._activeTarget = null + this._scrollHeight = 0 + + $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event)) + + this.refresh() + this._process() } - const OffsetMethod = { - OFFSET : 'offset', - POSITION : 'position' - } + // Getters - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class ScrollSpy { - constructor(element, config) { - this._element = element - this._scrollElement = element.tagName === 'BODY' ? window : element - this._config = this._getConfig(config) - this._selector = `${this._config.target} ${Selector.NAV_LINKS},` + - `${this._config.target} ${Selector.LIST_ITEMS},` + - `${this._config.target} ${Selector.DROPDOWN_ITEMS}` - this._offsets = [] - this._targets = [] - this._activeTarget = null - this._scrollHeight = 0 - - $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event)) + static get VERSION() { + return VERSION + } - this.refresh() - this._process() - } + static get Default() { + return Default + } - // Getters + // Public - static get VERSION() { - return VERSION - } + refresh() { + const autoMethod = this._scrollElement === this._scrollElement.window + ? OffsetMethod.OFFSET : OffsetMethod.POSITION - static get Default() { - return Default - } + const offsetMethod = this._config.method === 'auto' + ? autoMethod : this._config.method - // Public + const offsetBase = offsetMethod === OffsetMethod.POSITION + ? this._getScrollTop() : 0 - refresh() { - const autoMethod = this._scrollElement === this._scrollElement.window - ? OffsetMethod.OFFSET : OffsetMethod.POSITION + this._offsets = [] + this._targets = [] - const offsetMethod = this._config.method === 'auto' - ? autoMethod : this._config.method + this._scrollHeight = this._getScrollHeight() - const offsetBase = offsetMethod === OffsetMethod.POSITION - ? this._getScrollTop() : 0 + const targets = [].slice.call(document.querySelectorAll(this._selector)) - this._offsets = [] - this._targets = [] + targets + .map((element) => { + let target + const targetSelector = Util.getSelectorFromElement(element) - this._scrollHeight = this._getScrollHeight() + if (targetSelector) { + target = document.querySelector(targetSelector) + } - const targets = [].slice.call(document.querySelectorAll(this._selector)) + if (target) { + const targetBCR = target.getBoundingClientRect() + if (targetBCR.width || targetBCR.height) { + // TODO (fat): remove sketch reliance on jQuery position/offset + return [ + $(target)[offsetMethod]().top + offsetBase, + targetSelector + ] + } + } + return null + }) + .filter((item) => item) + .sort((a, b) => a[0] - b[0]) + .forEach((item) => { + this._offsets.push(item[0]) + this._targets.push(item[1]) + }) + } - targets - .map((element) => { - let target - const targetSelector = Util.getSelectorFromElement(element) + dispose() { + $.removeData(this._element, DATA_KEY) + $(this._scrollElement).off(EVENT_KEY) + + this._element = null + this._scrollElement = null + this._config = null + this._selector = null + this._offsets = null + this._targets = null + this._activeTarget = null + this._scrollHeight = null + } - if (targetSelector) { - target = document.querySelector(targetSelector) - } + // Private - if (target) { - const targetBCR = target.getBoundingClientRect() - if (targetBCR.width || targetBCR.height) { - // TODO (fat): remove sketch reliance on jQuery position/offset - return [ - $(target)[offsetMethod]().top + offsetBase, - targetSelector - ] - } - } - return null - }) - .filter((item) => item) - .sort((a, b) => a[0] - b[0]) - .forEach((item) => { - this._offsets.push(item[0]) - this._targets.push(item[1]) - }) + _getConfig(config) { + config = { + ...Default, + ...typeof config === 'object' && config ? config : {} } - dispose() { - $.removeData(this._element, DATA_KEY) - $(this._scrollElement).off(EVENT_KEY) - - this._element = null - this._scrollElement = null - this._config = null - this._selector = null - this._offsets = null - this._targets = null - this._activeTarget = null - this._scrollHeight = null + if (typeof config.target !== 'string') { + let id = $(config.target).attr('id') + if (!id) { + id = Util.getUID(NAME) + $(config.target).attr('id', id) + } + config.target = `#${id}` } - // Private - - _getConfig(config) { - config = { - ...Default, - ...typeof config === 'object' && config ? config : {} - } + Util.typeCheckConfig(NAME, config, DefaultType) - if (typeof config.target !== 'string') { - let id = $(config.target).attr('id') - if (!id) { - id = Util.getUID(NAME) - $(config.target).attr('id', id) - } - config.target = `#${id}` - } + return config + } - Util.typeCheckConfig(NAME, config, DefaultType) + _getScrollTop() { + return this._scrollElement === window + ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop + } - return config - } + _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max( + document.body.scrollHeight, + document.documentElement.scrollHeight + ) + } - _getScrollTop() { - return this._scrollElement === window - ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop - } + _getOffsetHeight() { + return this._scrollElement === window + ? window.innerHeight : this._scrollElement.getBoundingClientRect().height + } - _getScrollHeight() { - return this._scrollElement.scrollHeight || Math.max( - document.body.scrollHeight, - document.documentElement.scrollHeight - ) - } + _process() { + const scrollTop = this._getScrollTop() + this._config.offset + const scrollHeight = this._getScrollHeight() + const maxScroll = this._config.offset + + scrollHeight - + this._getOffsetHeight() - _getOffsetHeight() { - return this._scrollElement === window - ? window.innerHeight : this._scrollElement.getBoundingClientRect().height + if (this._scrollHeight !== scrollHeight) { + this.refresh() } - _process() { - const scrollTop = this._getScrollTop() + this._config.offset - const scrollHeight = this._getScrollHeight() - const maxScroll = this._config.offset + - scrollHeight - - this._getOffsetHeight() - - if (this._scrollHeight !== scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - const target = this._targets[this._targets.length - 1] + if (scrollTop >= maxScroll) { + const target = this._targets[this._targets.length - 1] - if (this._activeTarget !== target) { - this._activate(target) - } - return + if (this._activeTarget !== target) { + this._activate(target) } + return + } - if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { - this._activeTarget = null - this._clear() - return - } + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null + this._clear() + return + } - const offsetLength = this._offsets.length - for (let i = offsetLength; i--;) { - const isActiveTarget = this._activeTarget !== this._targets[i] && - scrollTop >= this._offsets[i] && - (typeof this._offsets[i + 1] === 'undefined' || - scrollTop < this._offsets[i + 1]) + const offsetLength = this._offsets.length + for (let i = offsetLength; i--;) { + const isActiveTarget = this._activeTarget !== this._targets[i] && + scrollTop >= this._offsets[i] && + (typeof this._offsets[i + 1] === 'undefined' || + scrollTop < this._offsets[i + 1]) - if (isActiveTarget) { - this._activate(this._targets[i]) - } + if (isActiveTarget) { + this._activate(this._targets[i]) } } + } - _activate(target) { - this._activeTarget = target + _activate(target) { + this._activeTarget = target - this._clear() + this._clear() - let queries = this._selector.split(',') - // eslint-disable-next-line arrow-body-style - queries = queries.map((selector) => { - return `${selector}[data-target="${target}"],` + - `${selector}[href="${target}"]` - }) + const queries = this._selector + .split(',') + .map((selector) => `${selector}[data-target="${target}"],${selector}[href="${target}"]`) - const $link = $([].slice.call(document.querySelectorAll(queries.join(',')))) - - if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { - $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE) - $link.addClass(ClassName.ACTIVE) - } else { - // Set triggered link as active - $link.addClass(ClassName.ACTIVE) - // Set triggered links parents as active - // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor - $link.parents(Selector.NAV_LIST_GROUP).prev(`${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`).addClass(ClassName.ACTIVE) - // Handle special case when .nav-link is inside .nav-item - $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE) - } + const $link = $([].slice.call(document.querySelectorAll(queries.join(',')))) - $(this._scrollElement).trigger(Event.ACTIVATE, { - relatedTarget: target - }) + if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { + $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE) + $link.addClass(ClassName.ACTIVE) + } else { + // Set triggered link as active + $link.addClass(ClassName.ACTIVE) + // Set triggered links parents as active + // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor + $link.parents(Selector.NAV_LIST_GROUP).prev(`${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`).addClass(ClassName.ACTIVE) + // Handle special case when .nav-link is inside .nav-item + $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE) } - _clear() { - const nodes = [].slice.call(document.querySelectorAll(this._selector)) - $(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE) - } + $(this._scrollElement).trigger(Event.ACTIVATE, { + relatedTarget: target + }) + } - // Static + _clear() { + [].slice.call(document.querySelectorAll(this._selector)) + .filter((node) => node.classList.contains(ClassName.ACTIVE)) + .forEach((node) => node.classList.remove(ClassName.ACTIVE)) + } - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = typeof config === 'object' && config + // Static - if (!data) { - data = new ScrollSpy(this, _config) - $(this).data(DATA_KEY, data) - } + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' && config - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() + if (!data) { + data = new ScrollSpy(this, _config) + $(this).data(DATA_KEY, data) + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - $(window).on(Event.LOAD_DATA_API, () => { - const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)) +$(window).on(Event.LOAD_DATA_API, () => { + const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)) + const scrollSpysLength = scrollSpys.length - const scrollSpysLength = scrollSpys.length - for (let i = scrollSpysLength; i--;) { - const $spy = $(scrollSpys[i]) - ScrollSpy._jQueryInterface.call($spy, $spy.data()) - } - }) - - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = ScrollSpy._jQueryInterface - $.fn[NAME].Constructor = ScrollSpy - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return ScrollSpy._jQueryInterface + for (let i = scrollSpysLength; i--;) { + const $spy = $(scrollSpys[i]) + ScrollSpy._jQueryInterface.call($spy, $spy.data()) } +}) + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return ScrollSpy -})($) +$.fn[NAME] = ScrollSpy._jQueryInterface +$.fn[NAME].Constructor = ScrollSpy +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return ScrollSpy._jQueryInterface +} export default ScrollSpy diff --git a/vendor/twbs/bootstrap/js/src/tab.js b/vendor/twbs/bootstrap/js/src/tab.js index a91b088de..8421e0a43 100644 --- a/vendor/twbs/bootstrap/js/src/tab.js +++ b/vendor/twbs/bootstrap/js/src/tab.js @@ -1,264 +1,260 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): tab.js + * Bootstrap (v4.3.1): tab.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Tab = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'tab' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.tab' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const Event = { - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` - } +import $ from 'jquery' +import Util from './util' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'tab' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.tab' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Event = { + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + DROPDOWN_MENU : 'dropdown-menu', + ACTIVE : 'active', + DISABLED : 'disabled', + FADE : 'fade', + SHOW : 'show' +} + +const Selector = { + DROPDOWN : '.dropdown', + NAV_LIST_GROUP : '.nav, .list-group', + ACTIVE : '.active', + ACTIVE_UL : '> li > .active', + DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', + DROPDOWN_TOGGLE : '.dropdown-toggle', + DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active' +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - const ClassName = { - DROPDOWN_MENU : 'dropdown-menu', - ACTIVE : 'active', - DISABLED : 'disabled', - FADE : 'fade', - SHOW : 'show' +class Tab { + constructor(element) { + this._element = element } - const Selector = { - DROPDOWN : '.dropdown', - NAV_LIST_GROUP : '.nav, .list-group', - ACTIVE : '.active', - ACTIVE_UL : '> li > .active', - DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', - DROPDOWN_TOGGLE : '.dropdown-toggle', - DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active' + // Getters + + static get VERSION() { + return VERSION } - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + // Public - class Tab { - constructor(element) { - this._element = element + show() { + if (this._element.parentNode && + this._element.parentNode.nodeType === Node.ELEMENT_NODE && + $(this._element).hasClass(ClassName.ACTIVE) || + $(this._element).hasClass(ClassName.DISABLED)) { + return } - // Getters + let target + let previous + const listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0] + const selector = Util.getSelectorFromElement(this._element) - static get VERSION() { - return VERSION + if (listElement) { + const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE + previous = $.makeArray($(listElement).find(itemSelector)) + previous = previous[previous.length - 1] } - // Public + const hideEvent = $.Event(Event.HIDE, { + relatedTarget: this._element + }) - show() { - if (this._element.parentNode && - this._element.parentNode.nodeType === Node.ELEMENT_NODE && - $(this._element).hasClass(ClassName.ACTIVE) || - $(this._element).hasClass(ClassName.DISABLED)) { - return - } + const showEvent = $.Event(Event.SHOW, { + relatedTarget: previous + }) + + if (previous) { + $(previous).trigger(hideEvent) + } - let target - let previous - const listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0] - const selector = Util.getSelectorFromElement(this._element) + $(this._element).trigger(showEvent) - if (listElement) { - const itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE - previous = $.makeArray($(listElement).find(itemSelector)) - previous = previous[previous.length - 1] - } + if (showEvent.isDefaultPrevented() || + hideEvent.isDefaultPrevented()) { + return + } + + if (selector) { + target = document.querySelector(selector) + } + + this._activate( + this._element, + listElement + ) - const hideEvent = $.Event(Event.HIDE, { + const complete = () => { + const hiddenEvent = $.Event(Event.HIDDEN, { relatedTarget: this._element }) - const showEvent = $.Event(Event.SHOW, { + const shownEvent = $.Event(Event.SHOWN, { relatedTarget: previous }) - if (previous) { - $(previous).trigger(hideEvent) - } - - $(this._element).trigger(showEvent) + $(previous).trigger(hiddenEvent) + $(this._element).trigger(shownEvent) + } - if (showEvent.isDefaultPrevented() || - hideEvent.isDefaultPrevented()) { - return - } + if (target) { + this._activate(target, target.parentNode, complete) + } else { + complete() + } + } - if (selector) { - target = document.querySelector(selector) - } + dispose() { + $.removeData(this._element, DATA_KEY) + this._element = null + } - this._activate( - this._element, - listElement - ) + // Private + + _activate(element, container, callback) { + const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') + ? $(container).find(Selector.ACTIVE_UL) + : $(container).children(Selector.ACTIVE) + + const active = activeElements[0] + const isTransitioning = callback && (active && $(active).hasClass(ClassName.FADE)) + const complete = () => this._transitionComplete( + element, + active, + callback + ) + + if (active && isTransitioning) { + const transitionDuration = Util.getTransitionDurationFromElement(active) + + $(active) + .removeClass(ClassName.SHOW) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + } else { + complete() + } + } - const complete = () => { - const hiddenEvent = $.Event(Event.HIDDEN, { - relatedTarget: this._element - }) + _transitionComplete(element, active, callback) { + if (active) { + $(active).removeClass(ClassName.ACTIVE) - const shownEvent = $.Event(Event.SHOWN, { - relatedTarget: previous - }) + const dropdownChild = $(active.parentNode).find( + Selector.DROPDOWN_ACTIVE_CHILD + )[0] - $(previous).trigger(hiddenEvent) - $(this._element).trigger(shownEvent) + if (dropdownChild) { + $(dropdownChild).removeClass(ClassName.ACTIVE) } - if (target) { - this._activate(target, target.parentNode, complete) - } else { - complete() + if (active.getAttribute('role') === 'tab') { + active.setAttribute('aria-selected', false) } } - dispose() { - $.removeData(this._element, DATA_KEY) - this._element = null + $(element).addClass(ClassName.ACTIVE) + if (element.getAttribute('role') === 'tab') { + element.setAttribute('aria-selected', true) } - // Private - - _activate(element, container, callback) { - let activeElements - if (container.nodeName === 'UL') { - activeElements = $(container).find(Selector.ACTIVE_UL) - } else { - activeElements = $(container).children(Selector.ACTIVE) - } - - const active = activeElements[0] - const isTransitioning = callback && - (active && $(active).hasClass(ClassName.FADE)) - - const complete = () => this._transitionComplete( - element, - active, - callback - ) + Util.reflow(element) - if (active && isTransitioning) { - const transitionDuration = Util.getTransitionDurationFromElement(active) - - $(active) - .one(Util.TRANSITION_END, complete) - .emulateTransitionEnd(transitionDuration) - } else { - complete() - } + if (element.classList.contains(ClassName.FADE)) { + element.classList.add(ClassName.SHOW) } - _transitionComplete(element, active, callback) { - if (active) { - $(active).removeClass(`${ClassName.SHOW} ${ClassName.ACTIVE}`) + if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) { + const dropdownElement = $(element).closest(Selector.DROPDOWN)[0] - const dropdownChild = $(active.parentNode).find( - Selector.DROPDOWN_ACTIVE_CHILD - )[0] + if (dropdownElement) { + const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE)) - if (dropdownChild) { - $(dropdownChild).removeClass(ClassName.ACTIVE) - } - - if (active.getAttribute('role') === 'tab') { - active.setAttribute('aria-selected', false) - } - } - - $(element).addClass(ClassName.ACTIVE) - if (element.getAttribute('role') === 'tab') { - element.setAttribute('aria-selected', true) + $(dropdownToggleList).addClass(ClassName.ACTIVE) } - Util.reflow(element) - $(element).addClass(ClassName.SHOW) - - if (element.parentNode && - $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) { - const dropdownElement = $(element).closest(Selector.DROPDOWN)[0] - if (dropdownElement) { - const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE)) - $(dropdownToggleList).addClass(ClassName.ACTIVE) - } - - element.setAttribute('aria-expanded', true) - } + element.setAttribute('aria-expanded', true) + } - if (callback) { - callback() - } + if (callback) { + callback() } + } - // Static + // Static - static _jQueryInterface(config) { - return this.each(function () { - const $this = $(this) - let data = $this.data(DATA_KEY) + static _jQueryInterface(config) { + return this.each(function () { + const $this = $(this) + let data = $this.data(DATA_KEY) - if (!data) { - data = new Tab(this) - $this.data(DATA_KEY, data) - } + if (!data) { + data = new Tab(this) + $this.data(DATA_KEY, data) + } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - $(document) - .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - event.preventDefault() - Tab._jQueryInterface.call($(this), 'show') - }) +$(document) + .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault() + Tab._jQueryInterface.call($(this), 'show') + }) - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = Tab._jQueryInterface - $.fn[NAME].Constructor = Tab - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Tab._jQueryInterface - } +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Tab -})($) +$.fn[NAME] = Tab._jQueryInterface +$.fn[NAME].Constructor = Tab +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Tab._jQueryInterface +} export default Tab diff --git a/vendor/twbs/bootstrap/js/src/toast.js b/vendor/twbs/bootstrap/js/src/toast.js new file mode 100644 index 000000000..4aef2d40c --- /dev/null +++ b/vendor/twbs/bootstrap/js/src/toast.js @@ -0,0 +1,227 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.3.1): toast.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +import $ from 'jquery' +import Util from './util' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'toast' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.toast' +const EVENT_KEY = `.${DATA_KEY}` +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Event = { + CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}` +} + +const ClassName = { + FADE : 'fade', + HIDE : 'hide', + SHOW : 'show', + SHOWING : 'showing' +} + +const DefaultType = { + animation : 'boolean', + autohide : 'boolean', + delay : 'number' +} + +const Default = { + animation : true, + autohide : true, + delay : 500 +} + +const Selector = { + DATA_DISMISS : '[data-dismiss="toast"]' +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Toast { + constructor(element, config) { + this._element = element + this._config = this._getConfig(config) + this._timeout = null + this._setListeners() + } + + // Getters + + static get VERSION() { + return VERSION + } + + static get DefaultType() { + return DefaultType + } + + static get Default() { + return Default + } + + // Public + + show() { + $(this._element).trigger(Event.SHOW) + + if (this._config.animation) { + this._element.classList.add(ClassName.FADE) + } + + const complete = () => { + this._element.classList.remove(ClassName.SHOWING) + this._element.classList.add(ClassName.SHOW) + + $(this._element).trigger(Event.SHOWN) + + if (this._config.autohide) { + this.hide() + } + } + + this._element.classList.remove(ClassName.HIDE) + this._element.classList.add(ClassName.SHOWING) + if (this._config.animation) { + const transitionDuration = Util.getTransitionDurationFromElement(this._element) + + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + } else { + complete() + } + } + + hide(withoutTimeout) { + if (!this._element.classList.contains(ClassName.SHOW)) { + return + } + + $(this._element).trigger(Event.HIDE) + + if (withoutTimeout) { + this._close() + } else { + this._timeout = setTimeout(() => { + this._close() + }, this._config.delay) + } + } + + dispose() { + clearTimeout(this._timeout) + this._timeout = null + + if (this._element.classList.contains(ClassName.SHOW)) { + this._element.classList.remove(ClassName.SHOW) + } + + $(this._element).off(Event.CLICK_DISMISS) + + $.removeData(this._element, DATA_KEY) + this._element = null + this._config = null + } + + // Private + + _getConfig(config) { + config = { + ...Default, + ...$(this._element).data(), + ...typeof config === 'object' && config ? config : {} + } + + Util.typeCheckConfig( + NAME, + config, + this.constructor.DefaultType + ) + + return config + } + + _setListeners() { + $(this._element).on( + Event.CLICK_DISMISS, + Selector.DATA_DISMISS, + () => this.hide(true) + ) + } + + _close() { + const complete = () => { + this._element.classList.add(ClassName.HIDE) + $(this._element).trigger(Event.HIDDEN) + } + + this._element.classList.remove(ClassName.SHOW) + if (this._config.animation) { + const transitionDuration = Util.getTransitionDurationFromElement(this._element) + + $(this._element) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + } else { + complete() + } + } + + // Static + + static _jQueryInterface(config) { + return this.each(function () { + const $element = $(this) + let data = $element.data(DATA_KEY) + const _config = typeof config === 'object' && config + + if (!data) { + data = new Toast(this, _config) + $element.data(DATA_KEY, data) + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) + } + + data[config](this) + } + }) + } +} + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + +$.fn[NAME] = Toast._jQueryInterface +$.fn[NAME].Constructor = Toast +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Toast._jQueryInterface +} + +export default Toast diff --git a/vendor/twbs/bootstrap/js/src/tools/sanitizer.js b/vendor/twbs/bootstrap/js/src/tools/sanitizer.js new file mode 100644 index 000000000..ff78d06a7 --- /dev/null +++ b/vendor/twbs/bootstrap/js/src/tools/sanitizer.js @@ -0,0 +1,127 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.3.1): tools/sanitizer.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +const uriAttrs = [ + 'background', + 'cite', + 'href', + 'itemtype', + 'longdesc', + 'poster', + 'src', + 'xlink:href' +] + +const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i + +export const DefaultWhitelist = { + // Global attributes allowed on any supplied element below. + '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], + a: ['target', 'href', 'title', 'rel'], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + em: [], + hr: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + i: [], + img: ['src', 'alt', 'title', 'width', 'height'], + li: [], + ol: [], + p: [], + pre: [], + s: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + u: [], + ul: [] +} + +/** + * A pattern that recognizes a commonly useful subset of URLs that are safe. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ +const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi + +/** + * A pattern that matches safe data URLs. Only matches image, video and audio types. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ +const 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 + +function allowedAttribute(attr, allowedAttributeList) { + const attrName = attr.nodeName.toLowerCase() + + if (allowedAttributeList.indexOf(attrName) !== -1) { + if (uriAttrs.indexOf(attrName) !== -1) { + return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) + } + + return true + } + + const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp) + + // Check if a regular expression validates the attribute. + for (let i = 0, l = regExp.length; i < l; i++) { + if (attrName.match(regExp[i])) { + return true + } + } + + return false +} + +export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { + if (unsafeHtml.length === 0) { + return unsafeHtml + } + + if (sanitizeFn && typeof sanitizeFn === 'function') { + return sanitizeFn(unsafeHtml) + } + + const domParser = new window.DOMParser() + const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html') + const whitelistKeys = Object.keys(whiteList) + const elements = [].slice.call(createdDocument.body.querySelectorAll('*')) + + for (let i = 0, len = elements.length; i < len; i++) { + const el = elements[i] + const elName = el.nodeName.toLowerCase() + + if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) { + el.parentNode.removeChild(el) + + continue + } + + const attributeList = [].slice.call(el.attributes) + const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) + + attributeList.forEach((attr) => { + if (!allowedAttribute(attr, whitelistedAttributes)) { + el.removeAttribute(attr.nodeName) + } + }) + } + + return createdDocument.body.innerHTML +} diff --git a/vendor/twbs/bootstrap/js/src/tooltip.js b/vendor/twbs/bootstrap/js/src/tooltip.js index 72d9ba177..81a2dedc6 100644 --- a/vendor/twbs/bootstrap/js/src/tooltip.js +++ b/vendor/twbs/bootstrap/js/src/tooltip.js @@ -1,725 +1,785 @@ -import $ from 'jquery' -import Popper from 'popper.js' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): tooltip.js + * Bootstrap (v4.3.1): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Tooltip = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'tooltip' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.tooltip' - const EVENT_KEY = `.${DATA_KEY}` - const JQUERY_NO_CONFLICT = $.fn[NAME] - const CLASS_PREFIX = 'bs-tooltip' - const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') - - const DefaultType = { - animation : 'boolean', - template : 'string', - title : '(string|element|function)', - trigger : 'string', - delay : '(number|object)', - html : 'boolean', - selector : '(string|boolean)', - placement : '(string|function)', - offset : '(number|string)', - container : '(string|element|boolean)', - fallbackPlacement : '(string|array)', - boundary : '(string|element)' - } - - const AttachmentMap = { - AUTO : 'auto', - TOP : 'top', - RIGHT : 'right', - BOTTOM : 'bottom', - LEFT : 'left' - } - - const Default = { - animation : true, - template : '<div class="tooltip" role="tooltip">' + - '<div class="arrow"></div>' + - '<div class="tooltip-inner"></div></div>', - trigger : 'hover focus', - title : '', - delay : 0, - html : false, - selector : false, - placement : 'top', - offset : 0, - container : false, - fallbackPlacement : 'flip', - boundary : 'scrollParent' - } - - const HoverState = { - SHOW : 'show', - OUT : 'out' - } - - const Event = { - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}`, - INSERTED : `inserted${EVENT_KEY}`, - CLICK : `click${EVENT_KEY}`, - FOCUSIN : `focusin${EVENT_KEY}`, - FOCUSOUT : `focusout${EVENT_KEY}`, - MOUSEENTER : `mouseenter${EVENT_KEY}`, - MOUSELEAVE : `mouseleave${EVENT_KEY}` - } - - const ClassName = { - FADE : 'fade', - SHOW : 'show' - } - - const Selector = { - TOOLTIP : '.tooltip', - TOOLTIP_INNER : '.tooltip-inner', - ARROW : '.arrow' - } - - const Trigger = { - HOVER : 'hover', - FOCUS : 'focus', - CLICK : 'click', - MANUAL : 'manual' - } - - - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class Tooltip { - constructor(element, config) { - /** - * Check for Popper dependency - * Popper - https://popper.js.org - */ - if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)') - } +import { + DefaultWhitelist, + sanitizeHtml +} from './tools/sanitizer' +import $ from 'jquery' +import Popper from 'popper.js' +import Util from './util' - // private - this._isEnabled = true - this._timeout = 0 - this._hoverState = '' - this._activeTrigger = {} - this._popper = null +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - // Protected - this.element = element - this.config = this._getConfig(config) - this.tip = null +const NAME = 'tooltip' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.tooltip' +const EVENT_KEY = `.${DATA_KEY}` +const JQUERY_NO_CONFLICT = $.fn[NAME] +const CLASS_PREFIX = 'bs-tooltip' +const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') +const DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] + +const DefaultType = { + animation : 'boolean', + template : 'string', + title : '(string|element|function)', + trigger : 'string', + delay : '(number|object)', + html : 'boolean', + selector : '(string|boolean)', + placement : '(string|function)', + offset : '(number|string|function)', + container : '(string|element|boolean)', + fallbackPlacement : '(string|array)', + boundary : '(string|element)', + sanitize : 'boolean', + sanitizeFn : '(null|function)', + whiteList : 'object' +} + +const AttachmentMap = { + AUTO : 'auto', + TOP : 'top', + RIGHT : 'right', + BOTTOM : 'bottom', + LEFT : 'left' +} + +const Default = { + animation : true, + template : '<div class="tooltip" role="tooltip">' + + '<div class="arrow"></div>' + + '<div class="tooltip-inner"></div></div>', + trigger : 'hover focus', + title : '', + delay : 0, + html : false, + selector : false, + placement : 'top', + offset : 0, + container : false, + fallbackPlacement : 'flip', + boundary : 'scrollParent', + sanitize : true, + sanitizeFn : null, + whiteList : DefaultWhitelist +} + +const HoverState = { + SHOW : 'show', + OUT : 'out' +} + +const Event = { + HIDE : `hide${EVENT_KEY}`, + HIDDEN : `hidden${EVENT_KEY}`, + SHOW : `show${EVENT_KEY}`, + SHOWN : `shown${EVENT_KEY}`, + INSERTED : `inserted${EVENT_KEY}`, + CLICK : `click${EVENT_KEY}`, + FOCUSIN : `focusin${EVENT_KEY}`, + FOCUSOUT : `focusout${EVENT_KEY}`, + MOUSEENTER : `mouseenter${EVENT_KEY}`, + MOUSELEAVE : `mouseleave${EVENT_KEY}` +} + +const ClassName = { + FADE : 'fade', + SHOW : 'show' +} + +const Selector = { + TOOLTIP : '.tooltip', + TOOLTIP_INNER : '.tooltip-inner', + ARROW : '.arrow' +} + +const Trigger = { + HOVER : 'hover', + FOCUS : 'focus', + CLICK : 'click', + MANUAL : 'manual' +} - this._setListeners() - } - // Getters +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - static get VERSION() { - return VERSION +class Tooltip { + constructor(element, config) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)') } - static get Default() { - return Default - } + // private + this._isEnabled = true + this._timeout = 0 + this._hoverState = '' + this._activeTrigger = {} + this._popper = null - static get NAME() { - return NAME - } + // Protected + this.element = element + this.config = this._getConfig(config) + this.tip = null - static get DATA_KEY() { - return DATA_KEY - } + this._setListeners() + } - static get Event() { - return Event - } + // Getters - static get EVENT_KEY() { - return EVENT_KEY - } + static get VERSION() { + return VERSION + } - static get DefaultType() { - return DefaultType - } + static get Default() { + return Default + } - // Public + static get NAME() { + return NAME + } - enable() { - this._isEnabled = true - } + static get DATA_KEY() { + return DATA_KEY + } - disable() { - this._isEnabled = false - } + static get Event() { + return Event + } - toggleEnabled() { - this._isEnabled = !this._isEnabled - } + static get EVENT_KEY() { + return EVENT_KEY + } - toggle(event) { - if (!this._isEnabled) { - return - } + static get DefaultType() { + return DefaultType + } - if (event) { - const dataKey = this.constructor.DATA_KEY - let context = $(event.currentTarget).data(dataKey) + // Public - if (!context) { - context = new this.constructor( - event.currentTarget, - this._getDelegateConfig() - ) - $(event.currentTarget).data(dataKey, context) - } + enable() { + this._isEnabled = true + } - context._activeTrigger.click = !context._activeTrigger.click + disable() { + this._isEnabled = false + } - if (context._isWithActiveTrigger()) { - context._enter(null, context) - } else { - context._leave(null, context) - } - } else { - if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { - this._leave(null, this) - return - } + toggleEnabled() { + this._isEnabled = !this._isEnabled + } - this._enter(null, this) - } + toggle(event) { + if (!this._isEnabled) { + return } - dispose() { - clearTimeout(this._timeout) + if (event) { + const dataKey = this.constructor.DATA_KEY + let context = $(event.currentTarget).data(dataKey) - $.removeData(this.element, this.constructor.DATA_KEY) + if (!context) { + context = new this.constructor( + event.currentTarget, + this._getDelegateConfig() + ) + $(event.currentTarget).data(dataKey, context) + } - $(this.element).off(this.constructor.EVENT_KEY) - $(this.element).closest('.modal').off('hide.bs.modal') + context._activeTrigger.click = !context._activeTrigger.click - if (this.tip) { - $(this.tip).remove() + if (context._isWithActiveTrigger()) { + context._enter(null, context) + } else { + context._leave(null, context) } - - this._isEnabled = null - this._timeout = null - this._hoverState = null - this._activeTrigger = null - if (this._popper !== null) { - this._popper.destroy() + } else { + if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { + this._leave(null, this) + return } - this._popper = null - this.element = null - this.config = null - this.tip = null + this._enter(null, this) } + } - show() { - if ($(this.element).css('display') === 'none') { - throw new Error('Please use show on visible elements') - } + dispose() { + clearTimeout(this._timeout) - const showEvent = $.Event(this.constructor.Event.SHOW) - if (this.isWithContent() && this._isEnabled) { - $(this.element).trigger(showEvent) + $.removeData(this.element, this.constructor.DATA_KEY) - const isInTheDom = $.contains( - this.element.ownerDocument.documentElement, - this.element - ) + $(this.element).off(this.constructor.EVENT_KEY) + $(this.element).closest('.modal').off('hide.bs.modal') - if (showEvent.isDefaultPrevented() || !isInTheDom) { - return - } + if (this.tip) { + $(this.tip).remove() + } - const tip = this.getTipElement() - const tipId = Util.getUID(this.constructor.NAME) + this._isEnabled = null + this._timeout = null + this._hoverState = null + this._activeTrigger = null + if (this._popper !== null) { + this._popper.destroy() + } - tip.setAttribute('id', tipId) - this.element.setAttribute('aria-describedby', tipId) + this._popper = null + this.element = null + this.config = null + this.tip = null + } - this.setContent() + show() { + if ($(this.element).css('display') === 'none') { + throw new Error('Please use show on visible elements') + } - if (this.config.animation) { - $(tip).addClass(ClassName.FADE) - } + const showEvent = $.Event(this.constructor.Event.SHOW) + if (this.isWithContent() && this._isEnabled) { + $(this.element).trigger(showEvent) - const placement = typeof this.config.placement === 'function' - ? this.config.placement.call(this, tip, this.element) - : this.config.placement + const shadowRoot = Util.findShadowRoot(this.element) + const isInTheDom = $.contains( + shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, + this.element + ) - const attachment = this._getAttachment(placement) - this.addAttachmentClass(attachment) + if (showEvent.isDefaultPrevented() || !isInTheDom) { + return + } - const container = this.config.container === false ? document.body : $(document).find(this.config.container) + const tip = this.getTipElement() + const tipId = Util.getUID(this.constructor.NAME) - $(tip).data(this.constructor.DATA_KEY, this) + tip.setAttribute('id', tipId) + this.element.setAttribute('aria-describedby', tipId) - if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { - $(tip).appendTo(container) - } + this.setContent() - $(this.element).trigger(this.constructor.Event.INSERTED) - - this._popper = new Popper(this.element, tip, { - placement: attachment, - modifiers: { - offset: { - offset: this.config.offset - }, - flip: { - behavior: this.config.fallbackPlacement - }, - arrow: { - element: Selector.ARROW - }, - preventOverflow: { - boundariesElement: this.config.boundary - } - }, - onCreate: (data) => { - if (data.originalPlacement !== data.placement) { - this._handlePopperPlacementChange(data) - } - }, - onUpdate: (data) => { - this._handlePopperPlacementChange(data) - } - }) + if (this.config.animation) { + $(tip).addClass(ClassName.FADE) + } - $(tip).addClass(ClassName.SHOW) + const placement = typeof this.config.placement === 'function' + ? this.config.placement.call(this, tip, this.element) + : this.config.placement - // If this is a touch-enabled device we add extra - // empty mouseover listeners to the body's immediate children; - // only needed because of broken event delegation on iOS - // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html - if ('ontouchstart' in document.documentElement) { - $(document.body).children().on('mouseover', null, $.noop) - } + const attachment = this._getAttachment(placement) + this.addAttachmentClass(attachment) - const complete = () => { - if (this.config.animation) { - this._fixTransition() - } - const prevHoverState = this._hoverState - this._hoverState = null + const container = this._getContainer() + $(tip).data(this.constructor.DATA_KEY, this) + + if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { + $(tip).appendTo(container) + } - $(this.element).trigger(this.constructor.Event.SHOWN) + $(this.element).trigger(this.constructor.Event.INSERTED) - if (prevHoverState === HoverState.OUT) { - this._leave(null, this) + this._popper = new Popper(this.element, tip, { + placement: attachment, + modifiers: { + offset: this._getOffset(), + flip: { + behavior: this.config.fallbackPlacement + }, + arrow: { + element: Selector.ARROW + }, + preventOverflow: { + boundariesElement: this.config.boundary } - } + }, + onCreate: (data) => { + if (data.originalPlacement !== data.placement) { + this._handlePopperPlacementChange(data) + } + }, + onUpdate: (data) => this._handlePopperPlacementChange(data) + }) - if ($(this.tip).hasClass(ClassName.FADE)) { - const transitionDuration = Util.getTransitionDurationFromElement(this.tip) + $(tip).addClass(ClassName.SHOW) - $(this.tip) - .one(Util.TRANSITION_END, complete) - .emulateTransitionEnd(transitionDuration) - } else { - complete() - } + // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + if ('ontouchstart' in document.documentElement) { + $(document.body).children().on('mouseover', null, $.noop) } - } - hide(callback) { - const tip = this.getTipElement() - const hideEvent = $.Event(this.constructor.Event.HIDE) const complete = () => { - if (this._hoverState !== HoverState.SHOW && tip.parentNode) { - tip.parentNode.removeChild(tip) + if (this.config.animation) { + this._fixTransition() } + const prevHoverState = this._hoverState + this._hoverState = null - this._cleanTipClass() - this.element.removeAttribute('aria-describedby') - $(this.element).trigger(this.constructor.Event.HIDDEN) - if (this._popper !== null) { - this._popper.destroy() - } + $(this.element).trigger(this.constructor.Event.SHOWN) - if (callback) { - callback() + if (prevHoverState === HoverState.OUT) { + this._leave(null, this) } } - $(this.element).trigger(hideEvent) - - if (hideEvent.isDefaultPrevented()) { - return - } - - $(tip).removeClass(ClassName.SHOW) - - // If this is a touch-enabled device we remove the extra - // empty mouseover listeners we added for iOS support - if ('ontouchstart' in document.documentElement) { - $(document.body).children().off('mouseover', null, $.noop) - } - - this._activeTrigger[Trigger.CLICK] = false - this._activeTrigger[Trigger.FOCUS] = false - this._activeTrigger[Trigger.HOVER] = false - if ($(this.tip).hasClass(ClassName.FADE)) { - const transitionDuration = Util.getTransitionDurationFromElement(tip) + const transitionDuration = Util.getTransitionDurationFromElement(this.tip) - $(tip) + $(this.tip) .one(Util.TRANSITION_END, complete) .emulateTransitionEnd(transitionDuration) } else { complete() } - - this._hoverState = '' } + } - update() { + hide(callback) { + const tip = this.getTipElement() + const hideEvent = $.Event(this.constructor.Event.HIDE) + const complete = () => { + if (this._hoverState !== HoverState.SHOW && tip.parentNode) { + tip.parentNode.removeChild(tip) + } + + this._cleanTipClass() + this.element.removeAttribute('aria-describedby') + $(this.element).trigger(this.constructor.Event.HIDDEN) if (this._popper !== null) { - this._popper.scheduleUpdate() + this._popper.destroy() + } + + if (callback) { + callback() } } - // Protected + $(this.element).trigger(hideEvent) - isWithContent() { - return Boolean(this.getTitle()) + if (hideEvent.isDefaultPrevented()) { + return } - addAttachmentClass(attachment) { - $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + $(tip).removeClass(ClassName.SHOW) + + // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + $(document.body).children().off('mouseover', null, $.noop) } - getTipElement() { - this.tip = this.tip || $(this.config.template)[0] - return this.tip + this._activeTrigger[Trigger.CLICK] = false + this._activeTrigger[Trigger.FOCUS] = false + this._activeTrigger[Trigger.HOVER] = false + + if ($(this.tip).hasClass(ClassName.FADE)) { + const transitionDuration = Util.getTransitionDurationFromElement(tip) + + $(tip) + .one(Util.TRANSITION_END, complete) + .emulateTransitionEnd(transitionDuration) + } else { + complete() } - setContent() { - const tip = this.getTipElement() - this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()) - $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) + this._hoverState = '' + } + + update() { + if (this._popper !== null) { + this._popper.scheduleUpdate() } + } - setElementContent($element, content) { - const html = this.config.html - if (typeof content === 'object' && (content.nodeType || content.jquery)) { - // Content is a DOM node or a jQuery - if (html) { - if (!$(content).parent().is($element)) { - $element.empty().append(content) - } - } else { - $element.text($(content).text()) + // Protected + + isWithContent() { + return Boolean(this.getTitle()) + } + + addAttachmentClass(attachment) { + $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + } + + getTipElement() { + this.tip = this.tip || $(this.config.template)[0] + return this.tip + } + + setContent() { + const tip = this.getTipElement() + this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()) + $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) + } + + setElementContent($element, content) { + if (typeof content === 'object' && (content.nodeType || content.jquery)) { + // Content is a DOM node or a jQuery + if (this.config.html) { + if (!$(content).parent().is($element)) { + $element.empty().append(content) } } else { - $element[html ? 'html' : 'text'](content) + $element.text($(content).text()) } - } - getTitle() { - let title = this.element.getAttribute('data-original-title') + return + } - if (!title) { - title = typeof this.config.title === 'function' - ? this.config.title.call(this.element) - : this.config.title + if (this.config.html) { + if (this.config.sanitize) { + content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn) } - return title + $element.html(content) + } else { + $element.text(content) } + } - // Private + getTitle() { + let title = this.element.getAttribute('data-original-title') - _getAttachment(placement) { - return AttachmentMap[placement.toUpperCase()] + if (!title) { + title = typeof this.config.title === 'function' + ? this.config.title.call(this.element) + : this.config.title } - _setListeners() { - const triggers = this.config.trigger.split(' ') + return title + } - triggers.forEach((trigger) => { - if (trigger === 'click') { - $(this.element).on( - this.constructor.Event.CLICK, - this.config.selector, - (event) => this.toggle(event) - ) - } else if (trigger !== Trigger.MANUAL) { - const eventIn = trigger === Trigger.HOVER - ? this.constructor.Event.MOUSEENTER - : this.constructor.Event.FOCUSIN - const eventOut = trigger === Trigger.HOVER - ? this.constructor.Event.MOUSELEAVE - : this.constructor.Event.FOCUSOUT - - $(this.element) - .on( - eventIn, - this.config.selector, - (event) => this._enter(event) - ) - .on( - eventOut, - this.config.selector, - (event) => this._leave(event) - ) - } + // Private - $(this.element).closest('.modal').on( - 'hide.bs.modal', - () => this.hide() - ) - }) + _getOffset() { + const offset = {} - if (this.config.selector) { - this.config = { - ...this.config, - trigger: 'manual', - selector: '' + if (typeof this.config.offset === 'function') { + offset.fn = (data) => { + data.offsets = { + ...data.offsets, + ...this.config.offset(data.offsets, this.element) || {} } - } else { - this._fixTitle() + + return data } + } else { + offset.offset = this.config.offset } - _fixTitle() { - const titleType = typeof this.element.getAttribute('data-original-title') - if (this.element.getAttribute('title') || - titleType !== 'string') { - this.element.setAttribute( - 'data-original-title', - this.element.getAttribute('title') || '' - ) - this.element.setAttribute('title', '') - } + return offset + } + + _getContainer() { + if (this.config.container === false) { + return document.body } - _enter(event, context) { - const dataKey = this.constructor.DATA_KEY + if (Util.isElement(this.config.container)) { + return $(this.config.container) + } - context = context || $(event.currentTarget).data(dataKey) + return $(document).find(this.config.container) + } - if (!context) { - context = new this.constructor( - event.currentTarget, - this._getDelegateConfig() + _getAttachment(placement) { + return AttachmentMap[placement.toUpperCase()] + } + + _setListeners() { + const triggers = this.config.trigger.split(' ') + + triggers.forEach((trigger) => { + if (trigger === 'click') { + $(this.element).on( + this.constructor.Event.CLICK, + this.config.selector, + (event) => this.toggle(event) ) - $(event.currentTarget).data(dataKey, context) + } else if (trigger !== Trigger.MANUAL) { + const eventIn = trigger === Trigger.HOVER + ? this.constructor.Event.MOUSEENTER + : this.constructor.Event.FOCUSIN + const eventOut = trigger === Trigger.HOVER + ? this.constructor.Event.MOUSELEAVE + : this.constructor.Event.FOCUSOUT + + $(this.element) + .on( + eventIn, + this.config.selector, + (event) => this._enter(event) + ) + .on( + eventOut, + this.config.selector, + (event) => this._leave(event) + ) } + }) - if (event) { - context._activeTrigger[ - event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER - ] = true + $(this.element).closest('.modal').on( + 'hide.bs.modal', + () => { + if (this.element) { + this.hide() + } } + ) - if ($(context.getTipElement()).hasClass(ClassName.SHOW) || - context._hoverState === HoverState.SHOW) { - context._hoverState = HoverState.SHOW - return + if (this.config.selector) { + this.config = { + ...this.config, + trigger: 'manual', + selector: '' } + } else { + this._fixTitle() + } + } - clearTimeout(context._timeout) + _fixTitle() { + const titleType = typeof this.element.getAttribute('data-original-title') - context._hoverState = HoverState.SHOW + if (this.element.getAttribute('title') || titleType !== 'string') { + this.element.setAttribute( + 'data-original-title', + this.element.getAttribute('title') || '' + ) - if (!context.config.delay || !context.config.delay.show) { - context.show() - return - } + this.element.setAttribute('title', '') + } + } - context._timeout = setTimeout(() => { - if (context._hoverState === HoverState.SHOW) { - context.show() - } - }, context.config.delay.show) + _enter(event, context) { + const dataKey = this.constructor.DATA_KEY + context = context || $(event.currentTarget).data(dataKey) + + if (!context) { + context = new this.constructor( + event.currentTarget, + this._getDelegateConfig() + ) + $(event.currentTarget).data(dataKey, context) } - _leave(event, context) { - const dataKey = this.constructor.DATA_KEY + if (event) { + context._activeTrigger[ + event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER + ] = true + } - context = context || $(event.currentTarget).data(dataKey) + if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { + context._hoverState = HoverState.SHOW + return + } - if (!context) { - context = new this.constructor( - event.currentTarget, - this._getDelegateConfig() - ) - $(event.currentTarget).data(dataKey, context) - } + clearTimeout(context._timeout) - if (event) { - context._activeTrigger[ - event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER - ] = false - } + context._hoverState = HoverState.SHOW - if (context._isWithActiveTrigger()) { - return + if (!context.config.delay || !context.config.delay.show) { + context.show() + return + } + + context._timeout = setTimeout(() => { + if (context._hoverState === HoverState.SHOW) { + context.show() } + }, context.config.delay.show) + } - clearTimeout(context._timeout) + _leave(event, context) { + const dataKey = this.constructor.DATA_KEY + context = context || $(event.currentTarget).data(dataKey) - context._hoverState = HoverState.OUT + if (!context) { + context = new this.constructor( + event.currentTarget, + this._getDelegateConfig() + ) + $(event.currentTarget).data(dataKey, context) + } - if (!context.config.delay || !context.config.delay.hide) { - context.hide() - return - } + if (event) { + context._activeTrigger[ + event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER + ] = false + } - context._timeout = setTimeout(() => { - if (context._hoverState === HoverState.OUT) { - context.hide() - } - }, context.config.delay.hide) + if (context._isWithActiveTrigger()) { + return } - _isWithActiveTrigger() { - for (const trigger in this._activeTrigger) { - if (this._activeTrigger[trigger]) { - return true - } - } + clearTimeout(context._timeout) + + context._hoverState = HoverState.OUT - return false + if (!context.config.delay || !context.config.delay.hide) { + context.hide() + return } - _getConfig(config) { - config = { - ...this.constructor.Default, - ...$(this.element).data(), - ...typeof config === 'object' && config ? config : {} + context._timeout = setTimeout(() => { + if (context._hoverState === HoverState.OUT) { + context.hide() } + }, context.config.delay.hide) + } - if (typeof config.delay === 'number') { - config.delay = { - show: config.delay, - hide: config.delay - } + _isWithActiveTrigger() { + for (const trigger in this._activeTrigger) { + if (this._activeTrigger[trigger]) { + return true } + } - if (typeof config.title === 'number') { - config.title = config.title.toString() - } + return false + } - if (typeof config.content === 'number') { - config.content = config.content.toString() - } + _getConfig(config) { + const dataAttributes = $(this.element).data() - Util.typeCheckConfig( - NAME, - config, - this.constructor.DefaultType - ) + Object.keys(dataAttributes) + .forEach((dataAttr) => { + if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) { + delete dataAttributes[dataAttr] + } + }) - return config + config = { + ...this.constructor.Default, + ...dataAttributes, + ...typeof config === 'object' && config ? config : {} } - _getDelegateConfig() { - const config = {} - - if (this.config) { - for (const key in this.config) { - if (this.constructor.Default[key] !== this.config[key]) { - config[key] = this.config[key] - } - } + if (typeof config.delay === 'number') { + config.delay = { + show: config.delay, + hide: config.delay } + } - return config + if (typeof config.title === 'number') { + config.title = config.title.toString() } - _cleanTipClass() { - const $tip = $(this.getTipElement()) - const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) - if (tabClass !== null && tabClass.length) { - $tip.removeClass(tabClass.join('')) - } + if (typeof config.content === 'number') { + config.content = config.content.toString() } - _handlePopperPlacementChange(popperData) { - const popperInstance = popperData.instance - this.tip = popperInstance.popper - this._cleanTipClass() - this.addAttachmentClass(this._getAttachment(popperData.placement)) + Util.typeCheckConfig( + NAME, + config, + this.constructor.DefaultType + ) + + if (config.sanitize) { + config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn) } - _fixTransition() { - const tip = this.getTipElement() - const initConfigAnimation = this.config.animation - if (tip.getAttribute('x-placement') !== null) { - return + return config + } + + _getDelegateConfig() { + const config = {} + + if (this.config) { + for (const key in this.config) { + if (this.constructor.Default[key] !== this.config[key]) { + config[key] = this.config[key] + } } - $(tip).removeClass(ClassName.FADE) - this.config.animation = false - this.hide() - this.show() - this.config.animation = initConfigAnimation } - // Static + return config + } - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = typeof config === 'object' && config + _cleanTipClass() { + const $tip = $(this.getTipElement()) + const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) + if (tabClass !== null && tabClass.length) { + $tip.removeClass(tabClass.join('')) + } + } - if (!data && /dispose|hide/.test(config)) { - return - } + _handlePopperPlacementChange(popperData) { + const popperInstance = popperData.instance + this.tip = popperInstance.popper + this._cleanTipClass() + this.addAttachmentClass(this._getAttachment(popperData.placement)) + } - if (!data) { - data = new Tooltip(this, _config) - $(this).data(DATA_KEY, data) - } + _fixTransition() { + const tip = this.getTipElement() + const initConfigAnimation = this.config.animation - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() - } - }) + if (tip.getAttribute('x-placement') !== null) { + return } + + $(tip).removeClass(ClassName.FADE) + this.config.animation = false + this.hide() + this.show() + this.config.animation = initConfigAnimation } - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ + // Static + + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' && config + + if (!data && /dispose|hide/.test(config)) { + return + } - $.fn[NAME] = Tooltip._jQueryInterface - $.fn[NAME].Constructor = Tooltip - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Tooltip._jQueryInterface + if (!data) { + data = new Tooltip(this, _config) + $(this).data(DATA_KEY, data) + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) + } + data[config]() + } + }) } +} + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return Tooltip -})($, Popper) +$.fn[NAME] = Tooltip._jQueryInterface +$.fn[NAME].Constructor = Tooltip +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Tooltip._jQueryInterface +} export default Tooltip diff --git a/vendor/twbs/bootstrap/js/src/util.js b/vendor/twbs/bootstrap/js/src/util.js index eb98d449c..d459aa266 100644 --- a/vendor/twbs/bootstrap/js/src/util.js +++ b/vendor/twbs/bootstrap/js/src/util.js @@ -1,152 +1,177 @@ -import $ from 'jquery' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): util.js + * Bootstrap (v4.3.1): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const Util = (($) => { - /** - * ------------------------------------------------------------------------ - * Private TransitionEnd Helpers - * ------------------------------------------------------------------------ - */ - - const TRANSITION_END = 'transitionend' - const MAX_UID = 1000000 - const MILLISECONDS_MULTIPLIER = 1000 +import $ from 'jquery' - // Shoutout AngusCroll (https://goo.gl/pxwQGp) - function toType(obj) { - return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase() - } +/** + * ------------------------------------------------------------------------ + * Private TransitionEnd Helpers + * ------------------------------------------------------------------------ + */ - function getSpecialTransitionEndEvent() { - return { - bindType: TRANSITION_END, - delegateType: TRANSITION_END, - handle(event) { - if ($(event.target).is(this)) { - return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params - } - return undefined // eslint-disable-line no-undefined +const TRANSITION_END = 'transitionend' +const MAX_UID = 1000000 +const MILLISECONDS_MULTIPLIER = 1000 + +// Shoutout AngusCroll (https://goo.gl/pxwQGp) +function toType(obj) { + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase() +} + +function getSpecialTransitionEndEvent() { + return { + bindType: TRANSITION_END, + delegateType: TRANSITION_END, + handle(event) { + if ($(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params } + return undefined // eslint-disable-line no-undefined } } +} - function transitionEndEmulator(duration) { - let called = false +function transitionEndEmulator(duration) { + let called = false - $(this).one(Util.TRANSITION_END, () => { - called = true - }) + $(this).one(Util.TRANSITION_END, () => { + called = true + }) - setTimeout(() => { - if (!called) { - Util.triggerTransitionEnd(this) - } - }, duration) + setTimeout(() => { + if (!called) { + Util.triggerTransitionEnd(this) + } + }, duration) - return this - } + return this +} - function setTransitionEndSupport() { - $.fn.emulateTransitionEnd = transitionEndEmulator - $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent() - } +function setTransitionEndSupport() { + $.fn.emulateTransitionEnd = transitionEndEmulator + $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent() +} - /** - * -------------------------------------------------------------------------- - * Public Util Api - * -------------------------------------------------------------------------- - */ +/** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ - const Util = { +const Util = { - TRANSITION_END: 'bsTransitionEnd', + TRANSITION_END: 'bsTransitionEnd', - getUID(prefix) { - do { - // eslint-disable-next-line no-bitwise - prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here - } while (document.getElementById(prefix)) - return prefix - }, + getUID(prefix) { + do { + // eslint-disable-next-line no-bitwise + prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here + } while (document.getElementById(prefix)) + return prefix + }, - getSelectorFromElement(element) { - let selector = element.getAttribute('data-target') - if (!selector || selector === '#') { - selector = element.getAttribute('href') || '' - } + getSelectorFromElement(element) { + let selector = element.getAttribute('data-target') - try { - return document.querySelector(selector) ? selector : null - } catch (err) { - return null - } - }, + if (!selector || selector === '#') { + const hrefAttr = element.getAttribute('href') + selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '' + } - getTransitionDurationFromElement(element) { - if (!element) { - return 0 - } + try { + return document.querySelector(selector) ? selector : null + } catch (err) { + return null + } + }, - // Get transition-duration of the element - let transitionDuration = $(element).css('transition-duration') - const floatTransitionDuration = parseFloat(transitionDuration) + getTransitionDurationFromElement(element) { + if (!element) { + return 0 + } - // Return 0 if element or transition duration is not found - if (!floatTransitionDuration) { - return 0 - } + // Get transition-duration of the element + let transitionDuration = $(element).css('transition-duration') + let transitionDelay = $(element).css('transition-delay') - // If multiple durations are defined, take the first - transitionDuration = transitionDuration.split(',')[0] - - return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER - }, - - reflow(element) { - return element.offsetHeight - }, - - triggerTransitionEnd(element) { - $(element).trigger(TRANSITION_END) - }, - - // TODO: Remove in v5 - supportsTransitionEnd() { - return Boolean(TRANSITION_END) - }, - - isElement(obj) { - return (obj[0] || obj).nodeType - }, - - typeCheckConfig(componentName, config, configTypes) { - for (const property in configTypes) { - if (Object.prototype.hasOwnProperty.call(configTypes, property)) { - const expectedTypes = configTypes[property] - const value = config[property] - const valueType = value && Util.isElement(value) - ? 'element' : toType(value) - - if (!new RegExp(expectedTypes).test(valueType)) { - throw new Error( - `${componentName.toUpperCase()}: ` + - `Option "${property}" provided type "${valueType}" ` + - `but expected type "${expectedTypes}".`) - } + const floatTransitionDuration = parseFloat(transitionDuration) + const floatTransitionDelay = parseFloat(transitionDelay) + + // Return 0 if element or transition duration is not found + if (!floatTransitionDuration && !floatTransitionDelay) { + return 0 + } + + // If multiple durations are defined, take the first + transitionDuration = transitionDuration.split(',')[0] + transitionDelay = transitionDelay.split(',')[0] + + return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER + }, + + reflow(element) { + return element.offsetHeight + }, + + triggerTransitionEnd(element) { + $(element).trigger(TRANSITION_END) + }, + + // TODO: Remove in v5 + supportsTransitionEnd() { + return Boolean(TRANSITION_END) + }, + + isElement(obj) { + return (obj[0] || obj).nodeType + }, + + typeCheckConfig(componentName, config, configTypes) { + for (const property in configTypes) { + if (Object.prototype.hasOwnProperty.call(configTypes, property)) { + const expectedTypes = configTypes[property] + const value = config[property] + const valueType = value && Util.isElement(value) + ? 'element' : toType(value) + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error( + `${componentName.toUpperCase()}: ` + + `Option "${property}" provided type "${valueType}" ` + + `but expected type "${expectedTypes}".`) } } } - } + }, - setTransitionEndSupport() + findShadowRoot(element) { + if (!document.documentElement.attachShadow) { + return null + } + + // Can find the shadow root otherwise it'll return the document + if (typeof element.getRootNode === 'function') { + const root = element.getRootNode() + return root instanceof ShadowRoot ? root : null + } + + if (element instanceof ShadowRoot) { + return element + } + + // when we don't find a shadow root + if (!element.parentNode) { + return null + } + + return Util.findShadowRoot(element.parentNode) + } +} - return Util -})($) +setTransitionEndSupport() export default Util |