diff options
Diffstat (limited to 'js')
33 files changed, 796 insertions, 727 deletions
diff --git a/js/src/alert.js b/js/src/alert.js index 9d8f69c465..f60ccfc911 100644 --- a/js/src/alert.js +++ b/js/src/alert.js @@ -22,26 +22,26 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 NAME = 'alert' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.alert' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' const Selector = { - DISMISS : '[data-dismiss="alert"]' + DISMISS: '[data-dismiss="alert"]' } const Event = { - CLOSE : `close${EVENT_KEY}`, - CLOSED : `closed${EVENT_KEY}`, - CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` + 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' + ALERT: 'alert', + FADE: 'fade', + SHOW: 'show' } /** @@ -90,7 +90,7 @@ class Alert { _getRootElement(element) { const selector = getSelectorFromElement(element) - let parent = false + let parent = false if (selector) { parent = SelectorEngine.findOne(selector) @@ -118,7 +118,7 @@ class Alert { const transitionDuration = getTransitionDurationFromElement(element) EventHandler - .one(element, TRANSITION_END, (event) => this._destroyElement(element, event)) + .one(element, TRANSITION_END, event => this._destroyElement(element, event)) emulateTransitionEnd(element, transitionDuration) } @@ -178,9 +178,9 @@ EventHandler if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Alert._jQueryInterface - $.fn[NAME].Constructor = Alert - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Alert._jQueryInterface + $.fn[NAME].Constructor = Alert + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Alert._jQueryInterface } diff --git a/js/src/button.js b/js/src/button.js index 489fe9de35..08d0f20308 100644 --- a/js/src/button.js +++ b/js/src/button.js @@ -18,30 +18,30 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 NAME = 'button' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.button' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' const ClassName = { - ACTIVE : 'active', - BUTTON : 'btn', - FOCUS : 'focus' + 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' + 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_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY}`, - BLUR_DATA_API : `blur${EVENT_KEY}${DATA_API_KEY}` + CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, + FOCUS_DATA_API: `focus${EVENT_KEY}${DATA_API_KEY}`, + BLUR_DATA_API: `blur${EVENT_KEY}${DATA_API_KEY}` } /** @@ -149,7 +149,7 @@ class Button { * ------------------------------------------------------------------------ */ -EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { +EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { event.preventDefault() let button = event.target @@ -162,15 +162,16 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (ev data = new Button(button) Data.setData(button, DATA_KEY, data) } + data.toggle() }) -EventHandler.on(document, Event.FOCUS_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { +EventHandler.on(document, Event.FOCUS_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { const button = SelectorEngine.closest(event.target, Selector.BUTTON) button.classList.add(ClassName.FOCUS) }) -EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { +EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { const button = SelectorEngine.closest(event.target, Selector.BUTTON) button.classList.remove(ClassName.FOCUS) }) @@ -183,11 +184,11 @@ EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (eve */ if (typeof $ !== 'undefined') { - const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Button._jQueryInterface - $.fn[NAME].Constructor = Button + const JQUERY_NO_CONFLICT = $.fn[NAME] + $.fn[NAME] = Button._jQueryInterface + $.fn[NAME].Constructor = Button - $.fn[NAME].noConflict = () => { + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Button._jQueryInterface } diff --git a/js/src/carousel.js b/js/src/carousel.js index d253d51dfd..3a9c4a47cb 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -28,83 +28,83 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key -const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key +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 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 SWIPE_THRESHOLD = 40 const Default = { - interval : 5000, - keyboard : true, - slide : false, - pause : 'hover', - wrap : true, - touch : true + 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' + 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' + 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}` + 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' + 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"]' + 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' + TOUCH: 'touch', + PEN: 'pen' } /** @@ -114,20 +114,20 @@ const PointerType = { */ class Carousel { constructor(element, config) { - this._items = null - this._interval = null + 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._isPaused = false + this._isSliding = false + this.touchTimeout = null + this.touchStartX = 0 + this.touchDeltaX = 0 + + this._config = this._getConfig(config) + this._element = element this._indicatorsElement = SelectorEngine.findOne(Selector.INDICATORS, this._element) - this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 - this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent) + this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 + this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent) this._addEventListeners() Data.setData(element, DATA_KEY, this) @@ -216,9 +216,9 @@ class Carousel { return } - const direction = index > activeIndex - ? Direction.NEXT - : Direction.PREV + const direction = index > activeIndex ? + Direction.NEXT : + Direction.PREV this._slide(direction, this._items[index]) } @@ -227,13 +227,13 @@ class Carousel { EventHandler.off(this._element, EVENT_KEY) Data.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._items = null + this._config = null + this._element = null + this._interval = null + this._isPaused = null + this._isSliding = null + this._activeElement = null this._indicatorsElement = null } @@ -271,14 +271,14 @@ class Carousel { _addEventListeners() { if (this._config.keyboard) { EventHandler - .on(this._element, Event.KEYDOWN, (event) => this._keydown(event)) + .on(this._element, Event.KEYDOWN, event => this._keydown(event)) } if (this._config.pause === 'hover') { EventHandler - .on(this._element, Event.MOUSEENTER, (event) => this.pause(event)) + .on(this._element, Event.MOUSEENTER, event => this.pause(event)) EventHandler - .on(this._element, Event.MOUSELEAVE, (event) => this.cycle(event)) + .on(this._element, Event.MOUSELEAVE, event => this.cycle(event)) } if (this._config.touch) { @@ -291,7 +291,7 @@ class Carousel { return } - const start = (event) => { + const start = event => { if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) { this.touchStartX = event.clientX } else if (!this._pointerEvent) { @@ -299,7 +299,7 @@ class Carousel { } } - const move = (event) => { + const move = event => { // ensure swiping with one touch and not pinching if (event.touches && event.touches.length > 1) { this.touchDeltaX = 0 @@ -308,7 +308,7 @@ class Carousel { } } - const end = (event) => { + const end = event => { if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) { this.touchDeltaX = event.clientX - this.touchStartX } @@ -327,23 +327,24 @@ class Carousel { if (this.touchTimeout) { clearTimeout(this.touchTimeout) } - this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) + + this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) } } - makeArray(SelectorEngine.find(Selector.ITEM_IMG, this._element)).forEach((itemImg) => { - EventHandler.on(itemImg, Event.DRAG_START, (e) => e.preventDefault()) + makeArray(SelectorEngine.find(Selector.ITEM_IMG, this._element)).forEach(itemImg => { + EventHandler.on(itemImg, Event.DRAG_START, e => e.preventDefault()) }) if (this._pointerEvent) { - EventHandler.on(this._element, Event.POINTERDOWN, (event) => start(event)) - EventHandler.on(this._element, Event.POINTERUP, (event) => end(event)) + EventHandler.on(this._element, Event.POINTERDOWN, event => start(event)) + EventHandler.on(this._element, Event.POINTERUP, event => end(event)) this._element.classList.add(ClassName.POINTER_EVENT) } else { - EventHandler.on(this._element, Event.TOUCHSTART, (event) => start(event)) - EventHandler.on(this._element, Event.TOUCHMOVE, (event) => move(event)) - EventHandler.on(this._element, Event.TOUCHEND, (event) => end(event)) + EventHandler.on(this._element, Event.TOUCHSTART, event => start(event)) + EventHandler.on(this._element, Event.TOUCHMOVE, event => move(event)) + EventHandler.on(this._element, Event.TOUCHEND, event => end(event)) } } @@ -366,9 +367,9 @@ class Carousel { } _getItemIndex(element) { - this._items = element && element.parentNode - ? makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode)) - : [] + this._items = element && element.parentNode ? + makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode)) : + [] return this._items.indexOf(element) } @@ -376,20 +377,21 @@ class Carousel { _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 || + 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 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] + return itemIndex === -1 ? + this._items[this._items.length - 1] : + this._items[itemIndex] } _triggerSlideEvent(relatedTarget, eventDirectionName) { @@ -424,7 +426,7 @@ class Carousel { _slide(direction, element) { const activeElement = SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) const activeElementIndex = this._getItemIndex(activeElement) - const nextElement = element || activeElement && + const nextElement = element || activeElement && this._getItemByDirection(direction, activeElement) const nextElementIndex = this._getItemIndex(nextElement) @@ -529,7 +531,7 @@ class Carousel { // Static static _carouselInterface(element, config) { - let data = Data.getData(element, DATA_KEY) + let data = Data.getData(element, DATA_KEY) let _config = { ...Default, ...Manipulator.getDataAttributes(element) @@ -552,8 +554,9 @@ class Carousel { data.to(config) } else if (typeof action === 'string') { if (typeof data[action] === 'undefined') { - throw new Error(`No method named "${action}"`) + throw new TypeError(`No method named "${action}"`) } + data[action]() } else if (_config.interval && _config.ride) { data.pause() @@ -629,9 +632,9 @@ EventHandler.on(window, Event.LOAD_DATA_API, () => { if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Carousel._jQueryInterface - $.fn[NAME].Constructor = Carousel - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Carousel._jQueryInterface + $.fn[NAME].Constructor = Carousel + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Carousel._jQueryInterface } diff --git a/js/src/collapse.js b/js/src/collapse.js index 847062d8d1..10f1ec9bab 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -27,45 +27,45 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 NAME = 'collapse' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.collapse' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' const Default = { - toggle : true, - parent : '' + toggle: true, + parent: '' } const DefaultType = { - toggle : 'boolean', - parent : '(string|element)' + 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}` + 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' + SHOW: 'show', + COLLAPSE: 'collapse', + COLLAPSING: 'collapsing', + COLLAPSED: 'collapsed' } const Dimension = { - WIDTH : 'width', - HEIGHT : 'height' + WIDTH: 'width', + HEIGHT: 'height' } const Selector = { - ACTIVES : '.show, .collapsing', - DATA_TOGGLE : '[data-toggle="collapse"]' + ACTIVES: '.show, .collapsing', + DATA_TOGGLE: '[data-toggle="collapse"]' } /** @@ -77,9 +77,9 @@ const Selector = { class Collapse { constructor(element, config) { this._isTransitioning = false - this._element = element - this._config = this._getConfig(config) - this._triggerArray = makeArray(SelectorEngine.find( + this._element = element + this._config = this._getConfig(config) + this._triggerArray = makeArray(SelectorEngine.find( `[data-toggle="collapse"][href="#${element.id}"],` + `[data-toggle="collapse"][data-target="#${element.id}"]` )) @@ -89,7 +89,7 @@ class Collapse { const elem = toggleList[i] const selector = getSelectorFromElement(elem) const filterElement = makeArray(SelectorEngine.find(selector)) - .filter((foundElem) => foundElem === element) + .filter(foundElem => foundElem === element) if (selector !== null && filterElement.length) { this._selector = selector @@ -141,7 +141,7 @@ class Collapse { if (this._parent) { actives = makeArray(SelectorEngine.find(Selector.ACTIVES, this._parent)) - .filter((elem) => { + .filter(elem => { if (typeof this._config.parent === 'string') { return elem.getAttribute('data-parent') === this._config.parent } @@ -156,7 +156,7 @@ class Collapse { const container = SelectorEngine.findOne(this._selector) if (actives) { - const tempActiveData = actives.filter((elem) => container !== elem) + const tempActiveData = actives.filter(elem => container !== elem) activesData = tempActiveData[0] ? Data.getData(tempActiveData[0], DATA_KEY) : null if (activesData && activesData._isTransitioning) { @@ -170,7 +170,7 @@ class Collapse { } if (actives) { - actives.forEach((elemActive) => { + actives.forEach(elemActive => { if (container !== elemActive) { Collapse._collapseInterface(elemActive, 'hide') } @@ -189,7 +189,7 @@ class Collapse { this._element.style[dimension] = 0 if (this._triggerArray.length) { - this._triggerArray.forEach((element) => { + this._triggerArray.forEach(element => { element.classList.remove(ClassName.COLLAPSED) element.setAttribute('aria-expanded', true) }) @@ -280,10 +280,10 @@ class Collapse { dispose() { Data.removeData(this._element, DATA_KEY) - this._config = null - this._parent = null - this._element = null - this._triggerArray = null + this._config = null + this._parent = null + this._element = null + this._triggerArray = null this._isTransitioning = null } @@ -308,7 +308,7 @@ class Collapse { let parent if (isElement(this._config.parent)) { - parent = this._config.parent + { parent } = this._config // it's a jQuery object if (typeof this._config.parent.jquery !== 'undefined' || typeof this._config.parent[0] !== 'undefined') { @@ -318,11 +318,10 @@ class Collapse { parent = SelectorEngine.findOne(this._config.parent) } - const selector = - `[data-toggle="collapse"][data-parent="${this._config.parent}"]` + const selector = `[data-toggle="collapse"][data-parent="${parent}"]` makeArray(SelectorEngine.find(selector, parent)) - .forEach((element) => { + .forEach(element => { this._addAriaAndCollapsedClass( Collapse._getTargetFromElement(element), [element] @@ -337,12 +336,13 @@ class Collapse { const isOpen = element.classList.contains(ClassName.SHOW) if (triggerArray.length) { - triggerArray.forEach((elem) => { - if (!isOpen) { - elem.classList.add(ClassName.COLLAPSED) - } else { + triggerArray.forEach(elem => { + if (isOpen) { elem.classList.remove(ClassName.COLLAPSED) + } else { + elem.classList.add(ClassName.COLLAPSED) } + elem.setAttribute('aria-expanded', isOpen) }) } @@ -357,7 +357,7 @@ class Collapse { } static _collapseInterface(element, config) { - let data = Data.getData(element, DATA_KEY) + let data = Data.getData(element, DATA_KEY) const _config = { ...Default, ...Manipulator.getDataAttributes(element), @@ -374,8 +374,9 @@ class Collapse { if (typeof config === 'string') { if (typeof data[config] === 'undefined') { - throw new Error(`No method named "${config}"`) + throw new TypeError(`No method named "${config}"`) } + data[config]() } } @@ -403,11 +404,11 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( event.preventDefault() } - const triggerData = Manipulator.getDataAttributes(this) - const selector = getSelectorFromElement(this) + const triggerData = Manipulator.getDataAttributes(this) + const selector = getSelectorFromElement(this) const selectorElements = makeArray(SelectorEngine.find(selector)) - selectorElements.forEach((element) => { + selectorElements.forEach(element => { const data = Data.getData(element, DATA_KEY) let config if (data) { @@ -416,6 +417,7 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( data._config.parent = triggerData.parent data._parent = data._getParent() } + config = 'toggle' } else { config = triggerData @@ -433,10 +435,10 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( */ if (typeof $ !== 'undefined') { - const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Collapse._jQueryInterface - $.fn[NAME].Constructor = Collapse - $.fn[NAME].noConflict = () => { + const JQUERY_NO_CONFLICT = $.fn[NAME] + $.fn[NAME] = Collapse._jQueryInterface + $.fn[NAME].Constructor = Collapse + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Collapse._jQueryInterface } diff --git a/js/src/dom/data.js b/js/src/dom/data.js index 43a917b0e3..6dd5a5bb22 100644 --- a/js/src/dom/data.js +++ b/js/src/dom/data.js @@ -35,6 +35,7 @@ const mapData = (() => { if (keyProperties.key === key) { return storeData[keyProperties.id] } + return null }, delete(element, key) { diff --git a/js/src/dom/eventHandler.js b/js/src/dom/eventHandler.js index d92920cdaa..2a326a55bf 100644 --- a/js/src/dom/eventHandler.js +++ b/js/src/dom/eventHandler.js @@ -18,26 +18,61 @@ import Polyfill from './polyfill' const namespaceRegex = /[^.]*(?=\..*)\.|.*/ const stripNameRegex = /\..*/ -const keyEventRegex = /^key/ -const stripUidRegex = /::\d+$/ -const eventRegistry = {} // Events storage -let uidEvent = 1 -const customEvents = { +const keyEventRegex = /^key/ +const stripUidRegex = /::\d+$/ +const eventRegistry = {} // Events storage +let uidEvent = 1 +const customEvents = { mouseenter: 'mouseover', mouseleave: 'mouseout' } -const nativeEvents = [ - 'click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', - 'mousewheel', 'DOMMouseScroll', - 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', - 'keydown', 'keypress', 'keyup', +const nativeEvents = [ + 'click', + 'dblclick', + 'mouseup', + 'mousedown', + 'contextmenu', + 'mousewheel', + 'DOMMouseScroll', + 'mouseover', + 'mouseout', + 'mousemove', + 'selectstart', + 'selectend', + 'keydown', + 'keypress', + 'keyup', 'orientationchange', - 'touchstart', 'touchmove', 'touchend', 'touchcancel', - 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', - 'gesturestart', 'gesturechange', 'gestureend', - 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', - 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', - 'error', 'abort', 'scroll' + 'touchstart', + 'touchmove', + 'touchend', + 'touchcancel', + 'pointerdown', + 'pointermove', + 'pointerup', + 'pointerleave', + 'pointercancel', + 'gesturestart', + 'gesturechange', + 'gestureend', + 'focus', + 'blur', + 'change', + 'reset', + 'select', + 'submit', + 'focusin', + 'focusout', + 'load', + 'unload', + 'beforeunload', + 'resize', + 'move', + 'DOMContentLoaded', + 'readystatechange', + 'error', + 'abort', + 'scroll' ] /** @@ -60,7 +95,7 @@ function getEvent(element) { function fixEvent(event, element) { // Add which for key events if (event.which === null && keyEventRegex.test(event.type)) { - event.which = event.charCode !== null ? event.charCode : event.keyCode + event.which = event.charCode === null ? event.keyCode : event.charCode } event.delegateTarget = element @@ -81,7 +116,7 @@ function bootstrapDelegationHandler(element, selector, fn) { return function handler(event) { const domElements = element.querySelectorAll(selector) - for (let target = event.target; target && target !== this; target = target.parentNode) { + for (let { target } = event; target && target !== this; target = target.parentNode) { for (let i = domElements.length; i--;) { if (domElements[i] === target) { fixEvent(event, target) @@ -147,8 +182,8 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { } const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) - const events = getEvent(element) - const handlers = events[typeEvent] || (events[typeEvent] = {}) + const events = getEvent(element) + const handlers = events[typeEvent] || (events[typeEvent] = {}) const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null) if (previousFn) { @@ -158,7 +193,7 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { } const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, '')) - const fn = !delegation ? bootstrapHandler(element, handler) : bootstrapDelegationHandler(element, handler, delegationFn) + const fn = delegation ? bootstrapDelegationHandler(element, handler, delegationFn) : bootstrapHandler(element, handler) fn.delegationSelector = delegation ? handler : null fn.originalHandler = originalHandler @@ -184,7 +219,7 @@ function removeNamespacedHandlers(element, events, typeEvent, namespace) { const storeElementEvent = events[typeEvent] || {} Object.keys(storeElementEvent) - .forEach((handlerKey) => { + .forEach(handlerKey => { if (handlerKey.indexOf(namespace) > -1) { const event = storeElementEvent[handlerKey] @@ -224,14 +259,14 @@ const EventHandler = { if (isNamespace) { Object.keys(events) - .forEach((elementEvent) => { + .forEach(elementEvent => { removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1)) }) } const storeElementEvent = events[typeEvent] || {} Object.keys(storeElementEvent) - .forEach((keyHandlers) => { + .forEach(keyHandlers => { const handlerKey = keyHandlers.replace(stripUidRegex, '') if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) { @@ -247,9 +282,9 @@ const EventHandler = { return null } - const typeEvent = event.replace(stripNameRegex, '') + const typeEvent = event.replace(stripNameRegex, '') const inNamespace = event !== typeEvent - const isNative = nativeEvents.indexOf(typeEvent) > -1 + const isNative = nativeEvents.indexOf(typeEvent) > -1 let jQueryEvent let bubbles = true @@ -279,7 +314,7 @@ const EventHandler = { // merge custom informations in our event if (typeof args !== 'undefined') { Object.keys(args) - .forEach((key) => { + .forEach(key => { Object.defineProperty(evt, key, { get() { return args[key] diff --git a/js/src/dom/manipulator.js b/js/src/dom/manipulator.js index 6c7df69425..9768473b59 100644 --- a/js/src/dom/manipulator.js +++ b/js/src/dom/manipulator.js @@ -26,7 +26,7 @@ function normalizeData(val) { } function normalizeDataKey(key) { - return key.replace(/[A-Z]/g, (chr) => chr.toLowerCase()) + return key.replace(/[A-Z]/g, chr => chr.toLowerCase()) } const Manipulator = { @@ -47,7 +47,7 @@ const Manipulator = { ...element.dataset } - Object.keys(attributes).forEach((key) => { + Object.keys(attributes).forEach(key => { attributes[key] = normalizeData(attributes[key]) }) diff --git a/js/src/dom/polyfill.js b/js/src/dom/polyfill.js index 579b7a10ed..eaf07552e8 100644 --- a/js/src/dom/polyfill.js +++ b/js/src/dom/polyfill.js @@ -34,7 +34,7 @@ const Polyfill = (() => { try { element.querySelectorAll(':scope *') - } catch (e) { + } catch (error) { return false } diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js index 151bb54c75..f674319d1c 100644 --- a/js/src/dom/selectorEngine.js +++ b/js/src/dom/selectorEngine.js @@ -16,8 +16,7 @@ import { * ------------------------------------------------------------------------ */ -const findFn = Polyfill.find -const findOne = Polyfill.findOne +const { find: findFn, findOne } = Polyfill const NODE_TEXT = 3 const SelectorEngine = { @@ -48,7 +47,7 @@ const SelectorEngine = { const children = makeArray(element.children) - return children.filter((child) => this.matches(child, selector)) + return children.filter(child => this.matches(child, selector)) }, parents(element, selector) { diff --git a/js/src/dropdown.js b/js/src/dropdown.js index f5150a016f..1492f48275 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -25,74 +25,74 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 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 NAME = 'dropdown' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.dropdown' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +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 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}` + 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' + 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)' + 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' + 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' + 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' + offset: '(number|string|function)', + flip: 'boolean', + boundary: '(string|element)', + reference: '(string|element)', + display: 'string' } /** @@ -103,10 +103,10 @@ const DefaultType = { class Dropdown { constructor(element, config) { - this._element = element - this._popper = null - this._config = this._getConfig(config) - this._menu = this._getMenuElement() + this._element = element + this._popper = null + this._config = this._getConfig(config) + this._menu = this._getMenuElement() this._inNavbar = this._detectNavbar() this._addEventListeners() @@ -134,7 +134,7 @@ class Dropdown { return } - const parent = Dropdown._getParentFromElement(this._element) + const parent = Dropdown._getParentFromElement(this._element) const isActive = this._menu.classList.contains(ClassName.SHOW) Dropdown._clearMenus() @@ -181,6 +181,7 @@ class Dropdown { if (this._config.boundary !== 'scrollParent') { parent.classList.add(ClassName.POSITION_STATIC) } + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) } @@ -191,7 +192,7 @@ class Dropdown { if ('ontouchstart' in document.documentElement && !makeArray(SelectorEngine.closest(parent, Selector.NAVBAR_NAV)).length) { makeArray(document.body.children) - .forEach((elem) => EventHandler.on(elem, 'mouseover', null, noop())) + .forEach(elem => EventHandler.on(elem, 'mouseover', null, noop())) } this._element.focus() @@ -265,7 +266,7 @@ class Dropdown { // Private _addEventListeners() { - EventHandler.on(this._element, Event.CLICK, (event) => { + EventHandler.on(this._element, Event.CLICK, event => { event.preventDefault() event.stopPropagation() this.toggle() @@ -296,12 +297,13 @@ class Dropdown { this._menu = SelectorEngine.findOne(Selector.MENU, parent) } } + return this._menu } _getPlacement() { const parentDropdown = this._element.parentNode - let placement = AttachmentMap.BOTTOM + let placement = AttachmentMap.BOTTOM // Handle dropup if (parentDropdown.classList.contains(ClassName.DROPUP)) { @@ -316,6 +318,7 @@ class Dropdown { } else if (this._menu.classList.contains(ClassName.MENURIGHT)) { placement = AttachmentMap.BOTTOMEND } + return placement } @@ -327,7 +330,7 @@ class Dropdown { const offset = {} if (typeof this._config.offset === 'function') { - offset.fn = (data) => { + offset.fn = data => { data.offsets = { ...data.offsets, ...this._config.offset(data.offsets, this._element) || {} @@ -378,8 +381,9 @@ class Dropdown { if (typeof config === 'string') { if (typeof data[config] === 'undefined') { - throw new Error(`No method named "${config}"`) + throw new TypeError(`No method named "${config}"`) } + data[config]() } } @@ -398,8 +402,8 @@ class Dropdown { const toggles = makeArray(SelectorEngine.find(Selector.DATA_TOGGLE)) for (let i = 0, len = toggles.length; i < len; i++) { - const parent = Dropdown._getParentFromElement(toggles[i]) - const context = Data.getData(toggles[i], DATA_KEY) + const parent = Dropdown._getParentFromElement(toggles[i]) + const context = Data.getData(toggles[i], DATA_KEY) const relatedTarget = { relatedTarget: toggles[i] } @@ -433,7 +437,7 @@ class Dropdown { // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { makeArray(document.body.children) - .forEach((elem) => EventHandler.off(elem, 'mouseover', null, noop())) + .forEach(elem => EventHandler.off(elem, 'mouseover', null, noop())) } toggles[i].setAttribute('aria-expanded', 'false') @@ -463,10 +467,11 @@ class Dropdown { // - 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 && + 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 || - SelectorEngine.closest(event.target, Selector.MENU)) : !REGEXP_KEYDOWN.test(event.which)) { + SelectorEngine.closest(event.target, Selector.MENU)) : + !REGEXP_KEYDOWN.test(event.which)) { return } @@ -477,7 +482,7 @@ class Dropdown { return } - const parent = Dropdown._getParentFromElement(this) + const parent = Dropdown._getParentFromElement(this) const isActive = parent.classList.contains(ClassName.SHOW) if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { @@ -533,7 +538,7 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( Dropdown._dropdownInterface(this, 'toggle') }) EventHandler - .on(document, Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => e.stopPropagation()) + .on(document, Event.CLICK_DATA_API, Selector.FORM_CHILD, e => e.stopPropagation()) /** * ------------------------------------------------------------------------ @@ -544,9 +549,9 @@ EventHandler if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Dropdown._jQueryInterface - $.fn[NAME].Constructor = Dropdown - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Dropdown._jQueryInterface + $.fn[NAME].Constructor = Dropdown + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Dropdown._jQueryInterface } diff --git a/js/src/modal.js b/js/src/modal.js index 7efb24f842..ec85746ee7 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -27,57 +27,57 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key +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 ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key const Default = { - backdrop : true, - keyboard : true, - focus : true, - show : true + backdrop: true, + keyboard: true, + focus: true, + show: true } const DefaultType = { - backdrop : '(boolean|string)', - keyboard : 'boolean', - focus : 'boolean', - show : 'boolean' + 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}` + 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' + 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' + 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' } /** @@ -88,15 +88,15 @@ const Selector = { class Modal { constructor(element, config) { - this._config = this._getConfig(config) - this._element = element - this._dialog = SelectorEngine.findOne(Selector.DIALOG, element) - this._backdrop = null - this._isShown = false - this._isBodyOverflowing = false + this._config = this._getConfig(config) + this._element = element + this._dialog = SelectorEngine.findOne(Selector.DIALOG, element) + this._backdrop = null + this._isShown = false + this._isBodyOverflowing = false this._ignoreBackdropClick = false - this._isTransitioning = false - this._scrollbarWidth = 0 + this._isTransitioning = false + this._scrollbarWidth = 0 Data.setData(element, DATA_KEY, this) } @@ -146,11 +146,11 @@ class Modal { EventHandler.on(this._element, Event.CLICK_DISMISS, Selector.DATA_DISMISS, - (event) => this.hide(event) + event => this.hide(event) ) EventHandler.on(this._dialog, Event.MOUSEDOWN_DISMISS, () => { - EventHandler.one(this._element, Event.MOUSEUP_DISMISS, (event) => { + EventHandler.one(this._element, Event.MOUSEUP_DISMISS, event => { if (event.target === this._element) { this._ignoreBackdropClick = true } @@ -192,11 +192,10 @@ class Modal { EventHandler.off(this._element, Event.CLICK_DISMISS) EventHandler.off(this._dialog, Event.MOUSEDOWN_DISMISS) - if (transition) { const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, (event) => this._hideModal(event)) + EventHandler.one(this._element, TRANSITION_END, event => this._hideModal(event)) emulateTransitionEnd(this._element, transitionDuration) } else { this._hideModal() @@ -205,7 +204,7 @@ class Modal { dispose() { [window, this._element, this._dialog] - .forEach((htmlElement) => EventHandler.off(htmlElement, EVENT_KEY)) + .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) /** * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` @@ -216,15 +215,15 @@ class Modal { Data.removeData(this._element, DATA_KEY) - this._config = null - this._element = null - this._dialog = null - this._backdrop = null - this._isShown = null - this._isBodyOverflowing = null + 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 + this._isTransitioning = null + this._scrollbarWidth = null } handleUpdate() { @@ -275,6 +274,7 @@ class Modal { if (this._config.focus) { this._element.focus() } + this._isTransitioning = false EventHandler.trigger(this._element, Event.SHOWN, { relatedTarget @@ -282,7 +282,7 @@ class Modal { } if (transition) { - const transitionDuration = getTransitionDurationFromElement(this._dialog) + const transitionDuration = getTransitionDurationFromElement(this._dialog) EventHandler.one(this._dialog, TRANSITION_END, transitionComplete) emulateTransitionEnd(this._dialog, transitionDuration) @@ -293,7 +293,7 @@ class Modal { _enforceFocus() { EventHandler.off(document, Event.FOCUSIN) // guard against infinite focus loop - EventHandler.on(document, Event.FOCUSIN, (event) => { + EventHandler.on(document, Event.FOCUSIN, event => { if (document !== event.target && this._element !== event.target && !this._element.contains(event.target)) { @@ -304,7 +304,7 @@ class Modal { _setEscapeEvent() { if (this._isShown && this._config.keyboard) { - EventHandler.on(this._element, Event.KEYDOWN_DISMISS, (event) => { + EventHandler.on(this._element, Event.KEYDOWN_DISMISS, event => { if (event.which === ESCAPE_KEYCODE) { event.preventDefault() this.hide() @@ -317,7 +317,7 @@ class Modal { _setResizeEvent() { if (this._isShown) { - EventHandler.on(window, Event.RESIZE, (event) => this.handleUpdate(event)) + EventHandler.on(window, Event.RESIZE, event => this.handleUpdate(event)) } else { EventHandler.off(window, Event.RESIZE) } @@ -344,9 +344,9 @@ class Modal { } _showBackdrop(callback) { - const animate = this._element.classList.contains(ClassName.FADE) - ? ClassName.FADE - : '' + const animate = this._element.classList.contains(ClassName.FADE) ? + ClassName.FADE : + '' if (this._isShown && this._config.backdrop) { this._backdrop = document.createElement('div') @@ -358,14 +358,16 @@ class Modal { document.body.appendChild(this._backdrop) - EventHandler.on(this._element, Event.CLICK_DISMISS, (event) => { + EventHandler.on(this._element, 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 { @@ -450,7 +452,7 @@ class Modal { // Adjust fixed content padding makeArray(SelectorEngine.find(Selector.FIXED_CONTENT)) - .forEach((element) => { + .forEach(element => { const actualPadding = element.style.paddingRight const calculatedPadding = window.getComputedStyle(element)['padding-right'] Manipulator.setDataAttribute(element, 'padding-right', actualPadding) @@ -459,7 +461,7 @@ class Modal { // Adjust sticky content margin makeArray(SelectorEngine.find(Selector.STICKY_CONTENT)) - .forEach((element) => { + .forEach(element => { const actualMargin = element.style.marginRight const calculatedMargin = window.getComputedStyle(element)['margin-right'] Manipulator.setDataAttribute(element, 'margin-right', actualMargin) @@ -480,7 +482,7 @@ class Modal { _resetScrollbar() { // Restore fixed content padding makeArray(SelectorEngine.find(Selector.FIXED_CONTENT)) - .forEach((element) => { + .forEach(element => { const padding = Manipulator.getDataAttribute(element, 'padding-right') if (typeof padding !== 'undefined') { Manipulator.removeDataAttribute(element, 'padding-right') @@ -490,7 +492,7 @@ class Modal { // Restore sticky content and navbar-toggler margin makeArray(SelectorEngine.find(`${Selector.STICKY_CONTENT}`)) - .forEach((element) => { + .forEach(element => { const margin = Manipulator.getDataAttribute(element, 'margin-right') if (typeof margin !== 'undefined') { Manipulator.removeDataAttribute(element, 'margin-right') @@ -500,11 +502,11 @@ class Modal { // Restore body padding const padding = Manipulator.getDataAttribute(document.body, 'padding-right') - if (typeof padding !== 'undefined') { + if (typeof padding === 'undefined') { + document.body.style.paddingRight = '' + } else { Manipulator.removeDataAttribute(document.body, 'padding-right') document.body.style.paddingRight = padding - } else { - document.body.style.paddingRight = '' } } @@ -536,6 +538,7 @@ class Modal { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } + data[config](relatedTarget) } else if (_config.show) { data.show(relatedTarget) @@ -562,8 +565,9 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( target = SelectorEngine.findOne(selector) } - const config = Data.getData(target, DATA_KEY) - ? 'toggle' : { + const config = Data.getData(target, DATA_KEY) ? + 'toggle' : + { ...Manipulator.getDataAttributes(target), ...Manipulator.getDataAttributes(this) } @@ -572,7 +576,7 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( event.preventDefault() } - EventHandler.one(target, Event.SHOW, (showEvent) => { + EventHandler.one(target, Event.SHOW, showEvent => { if (showEvent.defaultPrevented) { // only register focus restorer if modal will actually get shown return @@ -601,9 +605,9 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Modal._jQueryInterface - $.fn[NAME].Constructor = Modal - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Modal._jQueryInterface + $.fn[NAME].Constructor = Modal + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Modal._jQueryInterface } diff --git a/js/src/popover.js b/js/src/popover.js index 958beaa3d0..bee07d5e29 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -18,19 +18,19 @@ import Tooltip from './tooltip' * ------------------------------------------------------------------------ */ -const NAME = 'popover' -const VERSION = '4.3.1' -const DATA_KEY = 'bs.popover' -const EVENT_KEY = `.${DATA_KEY}` -const CLASS_PREFIX = 'bs-popover' -const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') +const NAME = 'popover' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.popover' +const EVENT_KEY = `.${DATA_KEY}` +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">' + + placement: 'right', + trigger: 'click', + content: '', + template: '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>' @@ -38,30 +38,30 @@ const Default = { const DefaultType = { ...Tooltip.DefaultType, - content : '(string|element|function)' + content: '(string|element|function)' } const ClassName = { - FADE : 'fade', - SHOW : 'show' + FADE: 'fade', + SHOW: 'show' } const Selector = { - TITLE : '.popover-header', - CONTENT : '.popover-body' + 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}` + 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}` } /** @@ -120,6 +120,7 @@ class Popover extends Tooltip { if (typeof content === 'function') { content = content.call(this.element) } + this.setElementContent(SelectorEngine.findOne(Selector.CONTENT, tip), content) tip.classList.remove(ClassName.FADE) @@ -138,8 +139,8 @@ class Popover extends Tooltip { const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX) if (tabClass !== null && tabClass.length > 0) { - tabClass.map((token) => token.trim()) - .forEach((tClass) => tip.classList.remove(tClass)) + tabClass.map(token => token.trim()) + .forEach(tClass => tip.classList.remove(tClass)) } } @@ -147,7 +148,7 @@ class Popover extends Tooltip { static _jQueryInterface(config) { return this.each(function () { - let data = Data.getData(this, DATA_KEY) + let data = Data.getData(this, DATA_KEY) const _config = typeof config === 'object' ? config : null if (!data && /dispose|hide/.test(config)) { @@ -163,6 +164,7 @@ class Popover extends Tooltip { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } + data[config]() } }) @@ -181,9 +183,9 @@ class Popover extends Tooltip { if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Popover._jQueryInterface - $.fn[NAME].Constructor = Popover - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Popover._jQueryInterface + $.fn[NAME].Constructor = Popover + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Popover._jQueryInterface } diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js index 74b60b7348..010af89bd8 100644 --- a/js/src/scrollspy.js +++ b/js/src/scrollspy.js @@ -23,51 +23,51 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 NAME = 'scrollspy' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.scrollspy' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' const Default = { - offset : 10, - method : 'auto', - target : '' + offset: 10, + method: 'auto', + target: '' } const DefaultType = { - offset : 'number', - method : 'string', - target : '(string|element)' + 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}` + 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' + 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' + 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' + OFFSET: 'offset', + POSITION: 'position' } /** @@ -78,18 +78,18 @@ const OffsetMethod = { class ScrollSpy { constructor(element, config) { - this._element = element + 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 = 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._offsets = [] + this._targets = [] + this._activeTarget = null + this._scrollHeight = 0 - EventHandler.on(this._scrollElement, Event.SCROLL, (event) => this._process(event)) + EventHandler.on(this._scrollElement, Event.SCROLL, event => this._process(event)) this.refresh() this._process() @@ -110,14 +110,17 @@ class ScrollSpy { // Public refresh() { - const autoMethod = this._scrollElement === this._scrollElement.window - ? OffsetMethod.OFFSET : OffsetMethod.POSITION + const autoMethod = this._scrollElement === this._scrollElement.window ? + OffsetMethod.OFFSET : + OffsetMethod.POSITION - const offsetMethod = this._config.method === 'auto' - ? autoMethod : this._config.method + const offsetMethod = this._config.method === 'auto' ? + autoMethod : + this._config.method - const offsetBase = offsetMethod === OffsetMethod.POSITION - ? this._getScrollTop() : 0 + const offsetBase = offsetMethod === OffsetMethod.POSITION ? + this._getScrollTop() : + 0 this._offsets = [] this._targets = [] @@ -127,7 +130,7 @@ class ScrollSpy { const targets = makeArray(SelectorEngine.find(this._selector)) targets - .map((element) => { + .map(element => { let target const targetSelector = getSelectorFromElement(element) @@ -145,11 +148,12 @@ class ScrollSpy { ] } } + return null }) - .filter((item) => item) + .filter(item => item) .sort((a, b) => a[0] - b[0]) - .forEach((item) => { + .forEach(item => { this._offsets.push(item[0]) this._targets.push(item[1]) }) @@ -159,14 +163,14 @@ class ScrollSpy { Data.removeData(this._element, DATA_KEY) EventHandler.off(this._scrollElement, EVENT_KEY) - this._element = null + this._element = null this._scrollElement = null - this._config = null - this._selector = null - this._offsets = null - this._targets = null - this._activeTarget = null - this._scrollHeight = null + this._config = null + this._selector = null + this._offsets = null + this._targets = null + this._activeTarget = null + this._scrollHeight = null } // Private @@ -178,11 +182,12 @@ class ScrollSpy { } if (typeof config.target !== 'string') { - let id = config.target.id + let { id } = config.target if (!id) { id = getUID(NAME) config.target.id = id } + config.target = `#${id}` } @@ -192,8 +197,9 @@ class ScrollSpy { } _getScrollTop() { - return this._scrollElement === window - ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop + return this._scrollElement === window ? + this._scrollElement.pageYOffset : + this._scrollElement.scrollTop } _getScrollHeight() { @@ -204,14 +210,15 @@ class ScrollSpy { } _getOffsetHeight() { - return this._scrollElement === window - ? window.innerHeight : this._scrollElement.getBoundingClientRect().height + return this._scrollElement === window ? + window.innerHeight : + this._scrollElement.getBoundingClientRect().height } _process() { - const scrollTop = this._getScrollTop() + this._config.offset + const scrollTop = this._getScrollTop() + this._config.offset const scrollHeight = this._getScrollHeight() - const maxScroll = this._config.offset + + const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight() @@ -225,6 +232,7 @@ class ScrollSpy { if (this._activeTarget !== target) { this._activate(target) } + return } @@ -253,7 +261,7 @@ class ScrollSpy { this._clear() const queries = this._selector.split(',') - .map((selector) => `${selector}[data-target="${target}"],${selector}[href="${target}"]`) + .map(selector => `${selector}[data-target="${target}"],${selector}[href="${target}"]`) const link = SelectorEngine.findOne(queries.join(',')) @@ -269,17 +277,17 @@ class ScrollSpy { SelectorEngine .parents(link, Selector.NAV_LIST_GROUP) - .forEach((listGroup) => { + .forEach(listGroup => { // Set triggered links parents as active // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor SelectorEngine.prev(listGroup, `${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`) - .forEach((item) => item.classList.add(ClassName.ACTIVE)) + .forEach(item => item.classList.add(ClassName.ACTIVE)) // Handle special case when .nav-link is inside .nav-item SelectorEngine.prev(listGroup, Selector.NAV_ITEMS) - .forEach((navItem) => { + .forEach(navItem => { SelectorEngine.children(navItem, Selector.NAV_LINKS) - .forEach((item) => item.classList.add(ClassName.ACTIVE)) + .forEach(item => item.classList.add(ClassName.ACTIVE)) }) }) } @@ -291,8 +299,8 @@ class ScrollSpy { _clear() { makeArray(SelectorEngine.find(this._selector)) - .filter((node) => node.classList.contains(ClassName.ACTIVE)) - .forEach((node) => node.classList.remove(ClassName.ACTIVE)) + .filter(node => node.classList.contains(ClassName.ACTIVE)) + .forEach(node => node.classList.remove(ClassName.ACTIVE)) } // Static @@ -310,6 +318,7 @@ class ScrollSpy { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } + data[config]() } }) @@ -328,7 +337,7 @@ class ScrollSpy { EventHandler.on(window, Event.LOAD_DATA_API, () => { makeArray(SelectorEngine.find(Selector.DATA_SPY)) - .forEach((spy) => new ScrollSpy(spy, Manipulator.getDataAttributes(spy))) + .forEach(spy => new ScrollSpy(spy, Manipulator.getDataAttributes(spy))) }) /** @@ -339,9 +348,9 @@ EventHandler.on(window, Event.LOAD_DATA_API, () => { if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = ScrollSpy._jQueryInterface - $.fn[NAME].Constructor = ScrollSpy - $.fn[NAME].noConflict = () => { + $.fn[NAME] = ScrollSpy._jQueryInterface + $.fn[NAME].Constructor = ScrollSpy + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return ScrollSpy._jQueryInterface } diff --git a/js/src/tab.js b/js/src/tab.js index 4320ee9eab..cebc52df25 100644 --- a/js/src/tab.js +++ b/js/src/tab.js @@ -24,36 +24,36 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -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 NAME = 'tab' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.tab' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' 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}` + 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' + 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 : ':scope > li > .active', - DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', - DROPDOWN_TOGGLE : '.dropdown-toggle', - DROPDOWN_ACTIVE_CHILD : ':scope > .dropdown-menu .active' + DROPDOWN: '.dropdown', + NAV_LIST_GROUP: '.nav, .list-group', + ACTIVE: '.active', + ACTIVE_UL: ':scope > li > .active', + DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', + DROPDOWN_TOGGLE: '.dropdown-toggle', + DROPDOWN_ACTIVE_CHILD: ':scope > .dropdown-menu .active' } /** @@ -146,11 +146,11 @@ class Tab { // Private _activate(element, container, callback) { - const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') - ? SelectorEngine.find(Selector.ACTIVE_UL, container) - : SelectorEngine.children(container, Selector.ACTIVE) + const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? + SelectorEngine.find(Selector.ACTIVE_UL, container) : + SelectorEngine.children(container, Selector.ACTIVE) - const active = activeElements[0] + const active = activeElements[0] const isTransitioning = callback && (active && active.classList.contains(ClassName.FADE)) @@ -202,7 +202,7 @@ class Tab { if (dropdownElement) { makeArray(SelectorEngine.find(Selector.DROPDOWN_TOGGLE)) - .forEach((dropdown) => dropdown.classList.add(ClassName.ACTIVE)) + .forEach(dropdown => dropdown.classList.add(ClassName.ACTIVE)) } element.setAttribute('aria-expanded', true) @@ -223,6 +223,7 @@ class Tab { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } + data[config]() } }) @@ -255,9 +256,9 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function ( if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Tab._jQueryInterface - $.fn[NAME].Constructor = Tab - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Tab._jQueryInterface + $.fn[NAME].Constructor = Tab + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Tab._jQueryInterface } diff --git a/js/src/toast.js b/js/src/toast.js index fba559197f..cbf29a104b 100644 --- a/js/src/toast.js +++ b/js/src/toast.js @@ -22,40 +22,40 @@ import Manipulator from './dom/manipulator' * ------------------------------------------------------------------------ */ -const NAME = 'toast' -const VERSION = '4.3.1' -const DATA_KEY = 'bs.toast' +const NAME = 'toast' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.toast' const EVENT_KEY = `.${DATA_KEY}` const Event = { - CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, - HIDE : `hide${EVENT_KEY}`, - HIDDEN : `hidden${EVENT_KEY}`, - SHOW : `show${EVENT_KEY}`, - SHOWN : `shown${EVENT_KEY}` + 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' + FADE: 'fade', + HIDE: 'hide', + SHOW: 'show', + SHOWING: 'showing' } const DefaultType = { - animation : 'boolean', - autohide : 'boolean', - delay : 'number' + animation: 'boolean', + autohide: 'boolean', + delay: 'number' } const Default = { - animation : true, - autohide : true, - delay : 500 + animation: true, + autohide: true, + delay: 500 } const Selector = { - DATA_DISMISS : '[data-dismiss="toast"]' + DATA_DISMISS: '[data-dismiss="toast"]' } /** @@ -67,7 +67,7 @@ const Selector = { class Toast { constructor(element, config) { this._element = element - this._config = this._getConfig(config) + this._config = this._getConfig(config) this._timeout = null this._setListeners() Data.setData(element, DATA_KEY, this) @@ -147,7 +147,7 @@ class Toast { Data.removeData(this._element, DATA_KEY) this._element = null - this._config = null + this._config = null } // Private @@ -198,8 +198,8 @@ class Toast { static _jQueryInterface(config) { return this.each(function () { - let data = Data.getData(this, DATA_KEY) - const _config = typeof config === 'object' && config + let data = Data.getData(this, DATA_KEY) + const _config = typeof config === 'object' && config if (!data) { data = new Toast(this, _config) @@ -229,9 +229,9 @@ class Toast { if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Toast._jQueryInterface - $.fn[NAME].Constructor = Toast - $.fn[NAME].noConflict = () => { + $.fn[NAME] = Toast._jQueryInterface + $.fn[NAME].Constructor = Toast + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Toast._jQueryInterface } diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 13a5c62b7e..950401deac 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -33,98 +33,96 @@ import SelectorEngine from './dom/selectorEngine' * ------------------------------------------------------------------------ */ -const NAME = 'tooltip' -const VERSION = '4.3.1' -const DATA_KEY = 'bs.tooltip' -const EVENT_KEY = `.${DATA_KEY}` -const CLASS_PREFIX = 'bs-tooltip' -const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') +const NAME = 'tooltip' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.tooltip' +const EVENT_KEY = `.${DATA_KEY}` +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' + 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' + AUTO: 'auto', + TOP: 'top', + RIGHT: 'right', + BOTTOM: 'bottom', + LEFT: 'left' } const Default = { - animation : true, - template : '<div class="tooltip" role="tooltip">' + + animation: true, + template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-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 + 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' + 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}` + 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' + FADE: 'fade', + SHOW: 'show' } const Selector = { - TOOLTIP : '.tooltip', - TOOLTIP_INNER : '.tooltip-inner', - TOOLTIP_ARROW : '.tooltip-arrow' + TOOLTIP: '.tooltip', + TOOLTIP_INNER: '.tooltip-inner', + TOOLTIP_ARROW: '.tooltip-arrow' } const Trigger = { - HOVER : 'hover', - FOCUS : 'focus', - CLICK : 'click', - MANUAL : 'manual' + HOVER: 'hover', + FOCUS: 'focus', + CLICK: 'click', + MANUAL: 'manual' } - /** * ------------------------------------------------------------------------ * Class Definition @@ -142,16 +140,16 @@ class Tooltip { } // private - this._isEnabled = true - this._timeout = 0 - this._hoverState = '' + this._isEnabled = true + this._timeout = 0 + this._hoverState = '' this._activeTrigger = {} - this._popper = null + this._popper = null // Protected this.element = element - this.config = this._getConfig(config) - this.tip = null + this.config = this._getConfig(config) + this.tip = null this._setListeners() Data.setData(element, this.constructor.DATA_KEY, this) @@ -247,9 +245,9 @@ class Tooltip { this.tip.parentNode.removeChild(this.tip) } - this._isEnabled = null - this._timeout = null - this._hoverState = null + this._isEnabled = null + this._timeout = null + this._hoverState = null this._activeTrigger = null if (this._popper !== null) { this._popper.destroy() @@ -257,8 +255,8 @@ class Tooltip { this._popper = null this.element = null - this.config = null - this.tip = null + this.config = null + this.tip = null } show() { @@ -269,15 +267,15 @@ class Tooltip { if (this.isWithContent() && this._isEnabled) { const showEvent = EventHandler.trigger(this.element, this.constructor.Event.SHOW) const shadowRoot = findShadowRoot(this.element) - const isInTheDom = shadowRoot !== null - ? shadowRoot.contains(this.element) - : this.element.ownerDocument.documentElement.contains(this.element) + const isInTheDom = shadowRoot === null ? + this.element.ownerDocument.documentElement.contains(this.element) : + shadowRoot.contains(this.element) if (showEvent.defaultPrevented || !isInTheDom) { return } - const tip = this.getTipElement() + const tip = this.getTipElement() const tipId = getUID(this.constructor.NAME) tip.setAttribute('id', tipId) @@ -289,9 +287,9 @@ class Tooltip { tip.classList.add(ClassName.FADE) } - const placement = typeof this.config.placement === 'function' - ? this.config.placement.call(this, tip, this.element) - : this.config.placement + const placement = typeof this.config.placement === 'function' ? + this.config.placement.call(this, tip, this.element) : + this.config.placement const attachment = this._getAttachment(placement) this.addAttachmentClass(attachment) @@ -319,12 +317,12 @@ class Tooltip { boundariesElement: this.config.boundary } }, - onCreate: (data) => { + onCreate: data => { if (data.originalPlacement !== data.placement) { this._handlePopperPlacementChange(data) } }, - onUpdate: (data) => this._handlePopperPlacementChange(data) + onUpdate: data => this._handlePopperPlacementChange(data) }) tip.classList.add(ClassName.SHOW) @@ -334,7 +332,7 @@ class Tooltip { // 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) { - makeArray(document.body.children).forEach((element) => { + makeArray(document.body.children).forEach(element => { EventHandler.on(element, 'mouseover', noop()) }) } @@ -343,8 +341,9 @@ class Tooltip { if (this.config.animation) { this._fixTransition() } + const prevHoverState = this._hoverState - this._hoverState = null + this._hoverState = null EventHandler.trigger(this.element, this.constructor.Event.SHOWN) @@ -364,8 +363,8 @@ class Tooltip { } hide(callback) { - const tip = this.getTipElement() - const complete = () => { + const tip = this.getTipElement() + const complete = () => { if (this._hoverState !== HoverState.SHOW && tip.parentNode) { tip.parentNode.removeChild(tip) } @@ -393,7 +392,7 @@ class Tooltip { // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { makeArray(document.body.children) - .forEach((element) => EventHandler.off(element, 'mouseover', noop)) + .forEach(element => EventHandler.off(element, 'mouseover', noop)) } this._activeTrigger[Trigger.CLICK] = false @@ -485,9 +484,9 @@ class Tooltip { let title = this.element.getAttribute('data-original-title') if (!title) { - title = typeof this.config.title === 'function' - ? this.config.title.call(this.element) - : this.config.title + title = typeof this.config.title === 'function' ? + this.config.title.call(this.element) : + this.config.title } return title @@ -499,7 +498,7 @@ class Tooltip { const offset = {} if (typeof this.config.offset === 'function') { - offset.fn = (data) => { + offset.fn = data => { data.offsets = { ...data.offsets, ...this.config.offset(data.offsets, this.element) || {} @@ -533,30 +532,30 @@ class Tooltip { _setListeners() { const triggers = this.config.trigger.split(' ') - triggers.forEach((trigger) => { + triggers.forEach(trigger => { if (trigger === 'click') { EventHandler.on(this.element, this.constructor.Event.CLICK, this.config.selector, - (event) => this.toggle(event) + 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 + 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 EventHandler.on(this.element, eventIn, this.config.selector, - (event) => this._enter(event) + event => this._enter(event) ) EventHandler.on(this.element, eventOut, this.config.selector, - (event) => this._leave(event) + event => this._leave(event) ) } }) @@ -686,7 +685,7 @@ class Tooltip { const dataAttributes = Manipulator.getDataAttributes(this.element) Object.keys(dataAttributes) - .forEach((dataAttr) => { + .forEach(dataAttr => { if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) { delete dataAttributes[dataAttr] } @@ -749,8 +748,8 @@ class Tooltip { const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX) if (tabClass !== null && tabClass.length) { tabClass - .map((token) => token.trim()) - .forEach((tClass) => tip.classList.remove(tClass)) + .map(token => token.trim()) + .forEach(tClass => tip.classList.remove(tClass)) } } @@ -767,6 +766,7 @@ class Tooltip { if (tip.getAttribute('x-placement') !== null) { return } + tip.classList.remove(ClassName.FADE) this.config.animation = false this.hide() @@ -778,7 +778,7 @@ class Tooltip { static _jQueryInterface(config) { return this.each(function () { - let data = Data.getData(this, DATA_KEY) + let data = Data.getData(this, DATA_KEY) const _config = typeof config === 'object' && config if (!data && /dispose|hide/.test(config)) { @@ -793,6 +793,7 @@ class Tooltip { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } + data[config]() } }) @@ -811,10 +812,10 @@ class Tooltip { */ if (typeof $ !== 'undefined') { - const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Tooltip._jQueryInterface - $.fn[NAME].Constructor = Tooltip - $.fn[NAME].noConflict = () => { + const JQUERY_NO_CONFLICT = $.fn[NAME] + $.fn[NAME] = Tooltip._jQueryInterface + $.fn[NAME].Constructor = Tooltip + $.fn[NAME].noConflict = () => { $.fn[NAME] = JQUERY_NO_CONFLICT return Tooltip._jQueryInterface } diff --git a/js/src/util/index.js b/js/src/util/index.js index 7c86a95ffa..aea369558a 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -8,10 +8,10 @@ const MAX_UID = 1000000 const MILLISECONDS_MULTIPLIER = 1000 const TRANSITION_END = 'transitionend' -const jQuery = window.jQuery +const { jQuery } = window // Shoutout AngusCroll (https://goo.gl/pxwQGp) -const toType = (obj) => ({}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()) +const toType = obj => ({}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()) /** * -------------------------------------------------------------------------- @@ -19,15 +19,16 @@ const toType = (obj) => ({}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCa * -------------------------------------------------------------------------- */ -const getUID = (prefix) => { +const 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 } -const getSelectorFromElement = (element) => { +const getSelectorFromElement = element => { let selector = element.getAttribute('data-target') if (!selector || selector === '#') { @@ -38,12 +39,12 @@ const getSelectorFromElement = (element) => { try { return document.querySelector(selector) ? selector : null - } catch (err) { + } catch (error) { return null } } -const getTransitionDurationFromElement = (element) => { +const getTransitionDurationFromElement = element => { if (!element) { return 0 } @@ -69,11 +70,11 @@ const getTransitionDurationFromElement = (element) => { return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER } -const triggerTransitionEnd = (element) => { +const triggerTransitionEnd = element => { element.dispatchEvent(new Event(TRANSITION_END)) } -const isElement = (obj) => (obj[0] || obj).nodeType +const isElement = obj => (obj[0] || obj).nodeType const emulateTransitionEnd = (element, duration) => { let called = false @@ -94,11 +95,12 @@ const emulateTransitionEnd = (element, duration) => { const typeCheckConfig = (componentName, config, configTypes) => { Object.keys(configTypes) - .forEach((property) => { + .forEach(property => { const expectedTypes = configTypes[property] - const value = config[property] - const valueType = value && isElement(value) - ? 'element' : toType(value) + const value = config[property] + const valueType = value && isElement(value) ? + 'element' : + toType(value) if (!new RegExp(expectedTypes).test(valueType)) { throw new Error( @@ -109,7 +111,7 @@ const typeCheckConfig = (componentName, config, configTypes) => { }) } -const makeArray = (nodeList) => { +const makeArray = nodeList => { if (!nodeList) { return [] } @@ -117,7 +119,7 @@ const makeArray = (nodeList) => { return [].slice.call(nodeList) } -const isVisible = (element) => { +const isVisible = element => { if (!element) { return false } @@ -131,7 +133,7 @@ const isVisible = (element) => { return false } -const findShadowRoot = (element) => { +const findShadowRoot = element => { if (!document.documentElement.attachShadow) { return null } @@ -157,7 +159,7 @@ const findShadowRoot = (element) => { // eslint-disable-next-line no-empty-function const noop = () => function () {} -const reflow = (element) => element.offsetHeight +const reflow = element => element.offsetHeight export { jQuery, diff --git a/js/src/util/sanitizer.js b/js/src/util/sanitizer.js index f8bb172a95..b2a1d0548b 100644 --- a/js/src/util/sanitizer.js +++ b/js/src/util/sanitizer.js @@ -47,7 +47,7 @@ const allowedAttribute = (attr, allowedAttributeList) => { return true } - const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp) + 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++) { @@ -120,7 +120,7 @@ export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { const attributeList = makeArray(el.attributes) const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) - attributeList.forEach((attr) => { + attributeList.forEach(attr => { if (!allowedAttribute(attr, whitelistedAttributes)) { el.removeAttribute(attr.nodeName) } diff --git a/js/tests/browsers.js b/js/tests/browsers.js index 2341f58ab2..859f9505cc 100644 --- a/js/tests/browsers.js +++ b/js/tests/browsers.js @@ -13,8 +13,8 @@ const browsers = { base: 'BrowserStack', os: 'OS X', os_version: 'High Sierra', - browser : 'Chrome', - browser_version : 'latest' + browser: 'Chrome', + browser_version: 'latest' }, firefoxMac: { base: 'BrowserStack', diff --git a/js/tests/integration/bundle.js b/js/tests/integration/bundle.js index f2d3b0d7be..5597cd063c 100644 --- a/js/tests/integration/bundle.js +++ b/js/tests/integration/bundle.js @@ -2,6 +2,6 @@ import 'popper.js' import bootstrap from '../../../dist/js/bootstrap' window.addEventListener('load', () => { - Array.from(document.querySelectorAll('[data-toggle="tooltip"]')) - .map((tooltipNode) => new bootstrap.Tooltip(tooltipNode)) + [...document.querySelectorAll('[data-toggle="tooltip"]')] + .map(tooltipNode => new bootstrap.Tooltip(tooltipNode)) }) diff --git a/js/tests/karma.conf.js b/js/tests/karma.conf.js index 46df7ae106..122d95753b 100644 --- a/js/tests/karma.conf.js +++ b/js/tests/karma.conf.js @@ -8,7 +8,7 @@ const { browsersKeys } = require('./browsers') -const env = process.env +const { env } = process const bundle = env.BUNDLE === 'true' const browserStack = env.BROWSER === 'true' const debug = env.DEBUG === 'true' @@ -173,7 +173,7 @@ conf.plugins = plugins conf.reporters = reporters conf.files = files -module.exports = (karmaConfig) => { +module.exports = karmaConfig => { // possible values: karmaConfig.LOG_DISABLE || karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN || karmaConfig.LOG_INFO || karmaConfig.LOG_DEBUG conf.logLevel = karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN karmaConfig.set(conf) diff --git a/js/tests/unit/alert.js b/js/tests/unit/alert.js index 4fa9ca19f7..c034356187 100644 --- a/js/tests/unit/alert.js +++ b/js/tests/unit/alert.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Alert = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Alert : window.Alert + var Alert = typeof window.bootstrap === 'undefined' ? window.Alert : window.bootstrap.Alert QUnit.module('alert plugin') diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js index bd393078ba..d351cc7705 100644 --- a/js/tests/unit/button.js +++ b/js/tests/unit/button.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Button = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Button : window.Button + var Button = typeof window.bootstrap === 'undefined' ? window.Button : window.bootstrap.Button QUnit.module('button plugin') diff --git a/js/tests/unit/carousel.js b/js/tests/unit/carousel.js index a45ef4564c..02a0c8a777 100644 --- a/js/tests/unit/carousel.js +++ b/js/tests/unit/carousel.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - window.Carousel = typeof bootstrap !== 'undefined' ? bootstrap.Carousel : Carousel + window.Carousel = typeof bootstrap === 'undefined' ? Carousel : bootstrap.Carousel var originWinPointerEvent = window.PointerEvent window.MSPointerEvent = null @@ -65,8 +65,8 @@ $(function () { $el.bootstrapCarousel() try { $el.bootstrapCarousel('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -89,8 +89,8 @@ $(function () { try { $('<div/>').bootstrapCarousel(config) - } catch (err) { - message = err.message + } catch (error) { + message = error.message } assert.ok(message === expectedMessage, 'correct error message') @@ -102,8 +102,8 @@ $(function () { try { $('<div/>').bootstrapCarousel(config) - } catch (err) { - message = err.message + } catch (error) { + message = error.message } assert.ok(message === expectedMessage, 'correct error message') @@ -161,6 +161,7 @@ $(function () { }, 0) $carousel[0].removeEventListener('slide.bs.carousel', onSlide) } + $carousel[0].addEventListener('slide.bs.carousel', onSlide) function onSlid() { @@ -173,6 +174,7 @@ $(function () { }, 0) $carousel[0].removeEventListener('slid.bs.carousel', onSlid) } + $carousel[0].addEventListener('slid.bs.carousel', onSlid) $carousel.bootstrapCarousel('next') @@ -682,6 +684,7 @@ $(function () { assert.strictEqual(event.defaultPrevented, false) $template[0].removeEventListener('keydown', handlerKeydown) } + $template[0].addEventListener('keydown', handlerKeydown) // arrow down @@ -694,6 +697,7 @@ $(function () { $template[0].addEventListener('keydown', handlerKeydown2) done() } + $template[0].addEventListener('keydown', handlerKeydown2) // arrow up diff --git a/js/tests/unit/collapse.js b/js/tests/unit/collapse.js index b21c18b8ec..a051d4f5c6 100644 --- a/js/tests/unit/collapse.js +++ b/js/tests/unit/collapse.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Collapse = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Collapse : window.Collapse + var Collapse = typeof window.bootstrap === 'undefined' ? window.Collapse : window.bootstrap.Collapse QUnit.module('collapse plugin') @@ -33,8 +33,8 @@ $(function () { $el.bootstrapCollapse() try { $el.bootstrapCollapse('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -459,7 +459,7 @@ $(function () { '<div class="card"/>' + '</div>' var showFired = false - var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') + var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') var $target1 = $('<a role="button" data-toggle="collapse" href="#body1"/>').appendTo($groups.eq(0)) @@ -470,7 +470,7 @@ $(function () { }) var $target2 = $('<a role="button" data-toggle="collapse" href="#body2"/>').appendTo($groups.eq(1)) - var $body2 = $('<div id="body2" class="collapse" data-parent="#accordion"/>').appendTo($groups.eq(1)) + var $body2 = $('<div id="body2" class="collapse" data-parent="#accordion"/>').appendTo($groups.eq(1)) $target2[0].dispatchEvent(new Event('click')) @@ -607,8 +607,8 @@ $(function () { var $collapseTwoOne = $('#collapseTwoOne') var $collapseTwoTwo = $('#collapseTwoTwo') var collapsedElements = { - one : false, - two : false + one: false, + two: false } function firstTest() { @@ -838,7 +838,7 @@ $(function () { parent: $('.my-collapse') }) assert.ok(true, 'collapse correctly created') - } catch (err) { + } catch (error) { assert.ok(false, 'collapse not created') } }) @@ -859,7 +859,7 @@ $(function () { parent: $('.my-collapse')[0] }) assert.ok(true, 'collapse correctly created') - } catch (err) { + } catch (error) { assert.ok(false, 'collapse not created') } }) diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js index d1f13c8eec..63f83b3bb6 100644 --- a/js/tests/unit/dropdown.js +++ b/js/tests/unit/dropdown.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Dropdown = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Dropdown : window.Dropdown + var Dropdown = typeof window.bootstrap === 'undefined' ? window.Dropdown : window.bootstrap.Dropdown QUnit.module('dropdowns plugin') @@ -34,8 +34,8 @@ $(function () { $el.bootstrapDropdown() try { $el.bootstrapDropdown('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) diff --git a/js/tests/unit/modal.js b/js/tests/unit/modal.js index 6025a65708..87d778b868 100644 --- a/js/tests/unit/modal.js +++ b/js/tests/unit/modal.js @@ -1,8 +1,8 @@ $(function () { 'use strict' - window.Util = typeof bootstrap !== 'undefined' ? bootstrap.Util : Util - var Modal = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Modal : window.Modal + window.Util = typeof bootstrap === 'undefined' ? Util : bootstrap.Util + var Modal = typeof window.bootstrap === 'undefined' ? window.Modal : window.bootstrap.Modal QUnit.module('modal plugin') @@ -45,8 +45,8 @@ $(function () { $el.bootstrapModal() try { $el.bootstrapModal('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -460,8 +460,8 @@ $(function () { var originalPadding = $body.css('padding-right') // Hide scrollbars to prevent the body overflowing - $body.css('overflow', 'hidden') // Real scrollbar (for in-browser testing) - $('html').css('padding-right', '0px') // Simulated scrollbar (for PhantomJS) + $body.css('overflow', 'hidden') // Real scrollbar (for in-browser testing) + $('html').css('padding-right', '0px') // Simulated scrollbar (for PhantomJS) $('<div id="modal-test"><div class="modal-dialog" /></div>') .on('shown.bs.modal', function () { @@ -758,6 +758,7 @@ $(function () { document.removeEventListener('focusin', focusInListener) done() } + document.addEventListener('focusin', focusInListener) var focusInEvent = new Event('focusin') diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js index ac5c547573..3782ed7eed 100644 --- a/js/tests/unit/popover.js +++ b/js/tests/unit/popover.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Popover = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Popover : window.Popover + var Popover = typeof window.bootstrap === 'undefined' ? window.Popover : window.bootstrap.Popover QUnit.module('popover plugin') @@ -34,8 +34,8 @@ $(function () { $el.bootstrapPopover() try { $el.bootstrapPopover('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -367,8 +367,8 @@ $(function () { try { $('<div data-toggle="popover" data-title="some title" data-content="@Johann-S" style="display: none"/>').bootstrapPopover('show') - } catch (err) { - assert.strictEqual(err.message, 'Please use show on visible elements') + } catch (error) { + assert.strictEqual(error.message, 'Please use show on visible elements') done() } }) diff --git a/js/tests/unit/scrollspy.js b/js/tests/unit/scrollspy.js index 1530676998..41a155b7a7 100644 --- a/js/tests/unit/scrollspy.js +++ b/js/tests/unit/scrollspy.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var ScrollSpy = typeof window.bootstrap !== 'undefined' ? window.bootstrap.ScrollSpy : window.ScrollSpy + var ScrollSpy = typeof window.bootstrap === 'undefined' ? window.ScrollSpy : window.bootstrap.ScrollSpy QUnit.module('scrollspy plugin') @@ -33,8 +33,8 @@ $(function () { $el.bootstrapScrollspy() try { $el.bootstrapScrollspy('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) diff --git a/js/tests/unit/tab.js b/js/tests/unit/tab.js index 0675126f8f..827fb707c1 100644 --- a/js/tests/unit/tab.js +++ b/js/tests/unit/tab.js @@ -33,8 +33,8 @@ $(function () { $el.bootstrapTab() try { $el.bootstrapTab('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -96,7 +96,7 @@ $(function () { QUnit.test('should activate element by tab id in nav list', function (assert) { assert.expect(2) - var tabsHTML = '<nav class="nav">' + + var tabsHTML = '<nav class="nav">' + '<a href="#home">Home</a>' + '<a href="#profile">Profile</a>' + '</nav>' @@ -112,7 +112,7 @@ $(function () { QUnit.test('should activate element by tab id in list group', function (assert) { assert.expect(2) - var tabsHTML = '<div class="list-group">' + + var tabsHTML = '<div class="list-group">' + '<a href="#home">Home</a>' + '<a href="#profile">Profile</a>' + '</div>' diff --git a/js/tests/unit/toast.js b/js/tests/unit/toast.js index ffd929646e..57f953bd17 100644 --- a/js/tests/unit/toast.js +++ b/js/tests/unit/toast.js @@ -41,8 +41,8 @@ $(function () { try { $el.bootstrapToast('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -208,7 +208,6 @@ $(function () { .bootstrapToast('show') }) - QUnit.test('should close toast when close element with data-dismiss attribute is set', function (assert) { assert.expect(2) var done = assert.async() diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index 3bc91046b4..c9cd2a10cd 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -1,7 +1,7 @@ $(function () { 'use strict' - var Tooltip = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Tooltip : window.Tooltip + var Tooltip = typeof window.bootstrap === 'undefined' ? window.Tooltip : window.bootstrap.Tooltip QUnit.module('tooltip plugin') @@ -34,8 +34,8 @@ $(function () { $el.bootstrapTooltip() try { $el.bootstrapTooltip('noMethod') - } catch (err) { - assert.strictEqual(err.message, 'No method named "noMethod"') + } catch (error) { + assert.strictEqual(error.message, 'No method named "noMethod"') } }) @@ -231,8 +231,8 @@ $(function () { try { $('<div title="tooltip title" style="display: none"/>').bootstrapTooltip('show') - } catch (err) { - assert.strictEqual(err.message, 'Please use show on visible elements') + } catch (error) { + assert.strictEqual(error.message, 'Please use show on visible elements') done() } }) @@ -336,7 +336,7 @@ $(function () { assert.expect(3) var $tooltip = $('<div/>') .bootstrapTooltip() - .on('click.foo', function () {}) // eslint-disable-line no-empty-function + .on('click.foo', function () {}) // eslint-disable-line no-empty-function assert.ok(Tooltip._getInstance($tooltip[0]), 'tooltip has data') @@ -557,7 +557,7 @@ $(function () { try { $tooltip.bootstrapTooltip('show') - } catch (err) { + } catch (error) { passed = false } diff --git a/js/tests/unit/util/index.js b/js/tests/unit/util/index.js index 2d52ca59a0..19d3891d3a 100644 --- a/js/tests/unit/util/index.js +++ b/js/tests/unit/util/index.js @@ -44,8 +44,8 @@ $(function () { try { Util.typeCheckConfig(namePlugin, config, defaultType) - } catch (err) { - assert.strictEqual(err.message, 'COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".') + } catch (error) { + assert.strictEqual(error.message, 'COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".') } }) @@ -139,9 +139,7 @@ $(function () { assert.expect(1) var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture')) - if (!document.documentElement.attachShadow) { - assert.equal(null, Util.findShadowRoot($div[0])) - } else { + if (document.documentElement.attachShadow) { var sandbox = sinon.createSandbox() sandbox.replace(document.documentElement, 'attachShadow', function () { @@ -151,6 +149,8 @@ $(function () { assert.equal(null, Util.findShadowRoot($div[0])) sandbox.restore() + } else { + assert.equal(null, Util.findShadowRoot($div[0])) } }) |