From 38333feda548fa973e034de03d34429a1f214089 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sat, 7 Mar 2020 11:31:42 +0200 Subject: [PATCH] Switch to strings constants. This allows the minifier to mangle the constants. It also allows the linter to find unused strings properly. While at it, remove a few unused properties. File Before After Diff -------------------------------------------------------- bootstrap.bundle.min.js 23.61 kB 22.61 kB -1.00 kB (-4.23 %) bootstrap.min.js 17.04 kB 16.08 kB -0.96 kB (-5.63 %) --- js/src/alert.js | 32 ++++----- js/src/button.js | 68 ++++++++---------- js/src/carousel.js | 172 +++++++++++++++++++++----------------------- js/src/collapse.js | 98 ++++++++++++------------- js/src/dropdown.js | 156 +++++++++++++++++++--------------------- js/src/modal.js | 152 +++++++++++++++++++-------------------- js/src/popover.js | 24 +++---- js/src/scrollspy.js | 82 ++++++++++----------- js/src/tab.js | 86 +++++++++++----------- js/src/toast.js | 60 +++++++--------- js/src/tooltip.js | 88 +++++++++++------------ 11 files changed, 472 insertions(+), 546 deletions(-) diff --git a/js/src/alert.js b/js/src/alert.js index dbd931b52e..6de3fa7f87 100644 --- a/js/src/alert.js +++ b/js/src/alert.js @@ -28,21 +28,15 @@ const DATA_KEY = 'bs.alert' const EVENT_KEY = `.${DATA_KEY}` const DATA_API_KEY = '.data-api' -const Selector = { - DISMISS: '[data-dismiss="alert"]' -} +const SELECTOR_DISMISS = '[data-dismiss="alert"]' -const Event = { - CLOSE: `close${EVENT_KEY}`, - CLOSED: `closed${EVENT_KEY}`, - CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}` -} +const EVENT_CLOSE = `close${EVENT_KEY}` +const EVENT_CLOSED = `closed${EVENT_KEY}` +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const ClassName = { - ALERT: 'alert', - FADE: 'fade', - SHOW: 'show' -} +const CLASSNAME_ALERT = 'alert' +const CLASSNAME_FADE = 'fade' +const CLASSNAME_SHOW = 'show' /** * ------------------------------------------------------------------------ @@ -93,20 +87,20 @@ class Alert { let parent = getElementFromSelector(element) if (!parent) { - parent = SelectorEngine.closest(element, `.${ClassName.ALERT}`) + parent = SelectorEngine.closest(element, `.${CLASSNAME_ALERT}`) } return parent } _triggerCloseEvent(element) { - return EventHandler.trigger(element, Event.CLOSE) + return EventHandler.trigger(element, EVENT_CLOSE) } _removeElement(element) { - element.classList.remove(ClassName.SHOW) + element.classList.remove(CLASSNAME_SHOW) - if (!element.classList.contains(ClassName.FADE)) { + if (!element.classList.contains(CLASSNAME_FADE)) { this._destroyElement(element) return } @@ -123,7 +117,7 @@ class Alert { element.parentNode.removeChild(element) } - EventHandler.trigger(element, Event.CLOSED) + EventHandler.trigger(element, EVENT_CLOSED) } // Static @@ -163,7 +157,7 @@ class Alert { * ------------------------------------------------------------------------ */ EventHandler - .on(document, Event.CLICK_DATA_API, Selector.DISMISS, Alert.handleDismiss(new Alert())) + .on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())) const $ = getjQuery() diff --git a/js/src/button.js b/js/src/button.js index 314d2a22a0..9c68862b21 100644 --- a/js/src/button.js +++ b/js/src/button.js @@ -22,26 +22,20 @@ const DATA_KEY = 'bs.button' const EVENT_KEY = `.${DATA_KEY}` const DATA_API_KEY = '.data-api' -const ClassName = { - ACTIVE: 'active', - BUTTON: 'btn', - DISABLED: 'disabled', - FOCUS: 'focus' -} +const CLASS_NAME_ACTIVE = 'active' +const CLASS_NAME_BUTTON = 'btn' +const CLASS_NAME_DISABLED = 'disabled' +const CLASS_NAME_FOCUS = 'focus' -const Selector = { - DATA_TOGGLE_CARROT: '[data-toggle^="button"]', - DATA_TOGGLE: '[data-toggle="buttons"]', - INPUT: 'input:not([type="hidden"])', - ACTIVE: '.active', - BUTTON: '.btn' -} +const SELECTOR_DATA_TOGGLE_CARROT = '[data-toggle^="button"]' +const SELECTOR_DATA_TOGGLE = '[data-toggle="buttons"]' +const SELECTOR_INPUT = 'input:not([type="hidden"])' +const SELECTOR_ACTIVE = '.active' +const SELECTOR_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}` -} +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` +const EVENT_FOCUS_DATA_API = `focus${EVENT_KEY}${DATA_API_KEY}` +const EVENT_BLUR_DATA_API = `blur${EVENT_KEY}${DATA_API_KEY}` /** * ------------------------------------------------------------------------ @@ -69,33 +63,33 @@ class Button { const rootElement = SelectorEngine.closest( this._element, - Selector.DATA_TOGGLE + SELECTOR_DATA_TOGGLE ) if (rootElement) { - const input = SelectorEngine.findOne(Selector.INPUT, this._element) + const input = SelectorEngine.findOne(SELECTOR_INPUT, this._element) if (input && input.type === 'radio') { if (input.checked && - this._element.classList.contains(ClassName.ACTIVE)) { + this._element.classList.contains(CLASS_NAME_ACTIVE)) { triggerChangeEvent = false } else { - const activeElement = SelectorEngine.findOne(Selector.ACTIVE, rootElement) + const activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE, rootElement) if (activeElement) { - activeElement.classList.remove(ClassName.ACTIVE) + activeElement.classList.remove(CLASS_NAME_ACTIVE) } } if (triggerChangeEvent) { if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || - input.classList.contains(ClassName.DISABLED) || - rootElement.classList.contains(ClassName.DISABLED)) { + input.classList.contains(CLASS_NAME_DISABLED) || + rootElement.classList.contains(CLASS_NAME_DISABLED)) { return } - input.checked = !this._element.classList.contains(ClassName.ACTIVE) + input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE) EventHandler.trigger(input, 'change') } @@ -106,11 +100,11 @@ class Button { if (addAriaPressed) { this._element.setAttribute('aria-pressed', - !this._element.classList.contains(ClassName.ACTIVE)) + !this._element.classList.contains(CLASS_NAME_ACTIVE)) } if (triggerChangeEvent) { - this._element.classList.toggle(ClassName.ACTIVE) + this._element.classList.toggle(CLASS_NAME_ACTIVE) } } @@ -146,12 +140,12 @@ 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 - if (!button.classList.contains(ClassName.BUTTON)) { - button = SelectorEngine.closest(button, Selector.BUTTON) + if (!button.classList.contains(CLASS_NAME_BUTTON)) { + button = SelectorEngine.closest(button, SELECTOR_BUTTON) } let data = Data.getData(button, DATA_KEY) @@ -162,19 +156,19 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, eve data.toggle() }) -EventHandler.on(document, Event.FOCUS_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { - const button = SelectorEngine.closest(event.target, Selector.BUTTON) +EventHandler.on(document, EVENT_FOCUS_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, event => { + const button = SelectorEngine.closest(event.target, SELECTOR_BUTTON) if (button) { - button.classList.add(ClassName.FOCUS) + button.classList.add(CLASS_NAME_FOCUS) } }) -EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { - const button = SelectorEngine.closest(event.target, Selector.BUTTON) +EventHandler.on(document, EVENT_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, event => { + const button = SelectorEngine.closest(event.target, SELECTOR_BUTTON) if (button) { - button.classList.remove(ClassName.FOCUS) + button.classList.remove(CLASS_NAME_FOCUS) } }) diff --git a/js/src/carousel.js b/js/src/carousel.js index 5034f17984..7230d5aaf7 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -33,6 +33,7 @@ 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 @@ -56,51 +57,42 @@ const DefaultType = { touch: 'boolean' } -const Direction = { - NEXT: 'next', - PREV: 'prev', - LEFT: 'left', - RIGHT: 'right' -} +const DIRECTION_NEXT = 'next' +const DIRECTION_PREV = 'prev' +const DIRECTION_LEFT = 'left' +const DIRECTION_RIGHT = 'right' -const Event = { - SLIDE: `slide${EVENT_KEY}`, - SLID: `slid${EVENT_KEY}`, - KEYDOWN: `keydown${EVENT_KEY}`, - MOUSEENTER: `mouseenter${EVENT_KEY}`, - MOUSELEAVE: `mouseleave${EVENT_KEY}`, - TOUCHSTART: `touchstart${EVENT_KEY}`, - TOUCHMOVE: `touchmove${EVENT_KEY}`, - TOUCHEND: `touchend${EVENT_KEY}`, - POINTERDOWN: `pointerdown${EVENT_KEY}`, - POINTERUP: `pointerup${EVENT_KEY}`, - DRAG_START: `dragstart${EVENT_KEY}`, - LOAD_DATA_API: `load${EVENT_KEY}${DATA_API_KEY}`, - CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}` -} +const EVENT_SLIDE = `slide${EVENT_KEY}` +const EVENT_SLID = `slid${EVENT_KEY}` +const EVENT_KEYDOWN = `keydown${EVENT_KEY}` +const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}` +const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}` +const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}` +const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}` +const EVENT_TOUCHEND = `touchend${EVENT_KEY}` +const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}` +const EVENT_POINTERUP = `pointerup${EVENT_KEY}` +const EVENT_DRAG_START = `dragstart${EVENT_KEY}` +const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}` +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const ClassName = { - CAROUSEL: 'carousel', - ACTIVE: 'active', - SLIDE: 'slide', - RIGHT: 'carousel-item-right', - LEFT: 'carousel-item-left', - NEXT: 'carousel-item-next', - PREV: 'carousel-item-prev', - ITEM: 'carousel-item', - POINTER_EVENT: 'pointer-event' -} +const CLASS_NAME_CAROUSEL = 'carousel' +const CLASS_NAME_ACTIVE = 'active' +const CLASS_NAME_SLIDE = 'slide' +const CLASS_NAME_RIGHT = 'carousel-item-right' +const CLASS_NAME_LEFT = 'carousel-item-left' +const CLASS_NAME_NEXT = 'carousel-item-next' +const CLASS_NAME_PREV = 'carousel-item-prev' +const CLASS_NAME_POINTER_EVENT = 'pointer-event' -const Selector = { - ACTIVE: '.active', - ACTIVE_ITEM: '.active.carousel-item', - ITEM: '.carousel-item', - ITEM_IMG: '.carousel-item img', - NEXT_PREV: '.carousel-item-next, .carousel-item-prev', - INDICATORS: '.carousel-indicators', - DATA_SLIDE: '[data-slide], [data-slide-to]', - DATA_RIDE: '[data-ride="carousel"]' -} +const SELECTOR_ACTIVE = '.active' +const SELECTOR_ACTIVE_ITEM = '.active.carousel-item' +const SELECTOR_ITEM = '.carousel-item' +const SELECTOR_ITEM_IMG = '.carousel-item img' +const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev' +const SELECTOR_INDICATORS = '.carousel-indicators' +const SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]' +const SELECTOR_DATA_RIDE = '[data-ride="carousel"]' const PointerType = { TOUCH: 'touch', @@ -125,7 +117,7 @@ class Carousel { this._config = this._getConfig(config) this._element = element - this._indicatorsElement = SelectorEngine.findOne(Selector.INDICATORS, this._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) @@ -147,7 +139,7 @@ class Carousel { next() { if (!this._isSliding) { - this._slide(Direction.NEXT) + this._slide(DIRECTION_NEXT) } } @@ -161,7 +153,7 @@ class Carousel { prev() { if (!this._isSliding) { - this._slide(Direction.PREV) + this._slide(DIRECTION_PREV) } } @@ -170,7 +162,7 @@ class Carousel { this._isPaused = true } - if (SelectorEngine.findOne(Selector.NEXT_PREV, this._element)) { + if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) { triggerTransitionEnd(this._element) this.cycle(true) } @@ -198,7 +190,7 @@ class Carousel { } to(index) { - this._activeElement = SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) + this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element) const activeIndex = this._getItemIndex(this._activeElement) if (index > this._items.length - 1 || index < 0) { @@ -206,7 +198,7 @@ class Carousel { } if (this._isSliding) { - EventHandler.one(this._element, Event.SLID, () => this.to(index)) + EventHandler.one(this._element, EVENT_SLID, () => this.to(index)) return } @@ -217,8 +209,8 @@ class Carousel { } const direction = index > activeIndex ? - Direction.NEXT : - Direction.PREV + DIRECTION_NEXT : + DIRECTION_PREV this._slide(direction, this._items[index]) } @@ -273,14 +265,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 && this._touchSupported) { @@ -330,19 +322,19 @@ class Carousel { } } - 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) + this._element.classList.add(CLASS_NAME_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,15 +358,15 @@ class Carousel { _getItemIndex(element) { this._items = element && element.parentNode ? - makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode)) : + makeArray(SelectorEngine.find(SELECTOR_ITEM, element.parentNode)) : [] return this._items.indexOf(element) } _getItemByDirection(direction, activeElement) { - const isNextDirection = direction === Direction.NEXT - const isPrevDirection = direction === Direction.PREV + 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) || @@ -384,7 +376,7 @@ class Carousel { 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 ? @@ -394,9 +386,9 @@ class Carousel { _triggerSlideEvent(relatedTarget, eventDirectionName) { const targetIndex = this._getItemIndex(relatedTarget) - const fromIndex = this._getItemIndex(SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element)) + const fromIndex = this._getItemIndex(SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)) - return EventHandler.trigger(this._element, Event.SLIDE, { + return EventHandler.trigger(this._element, EVENT_SLIDE, { relatedTarget, direction: eventDirectionName, from: fromIndex, @@ -406,9 +398,9 @@ class Carousel { _setActiveIndicatorElement(element) { if (this._indicatorsElement) { - const indicators = SelectorEngine.find(Selector.ACTIVE, this._indicatorsElement) + const indicators = SelectorEngine.find(SELECTOR_ACTIVE, this._indicatorsElement) for (let i = 0; i < indicators.length; i++) { - indicators[i].classList.remove(ClassName.ACTIVE) + indicators[i].classList.remove(CLASS_NAME_ACTIVE) } const nextIndicator = this._indicatorsElement.children[ @@ -416,13 +408,13 @@ class Carousel { ] if (nextIndicator) { - nextIndicator.classList.add(ClassName.ACTIVE) + nextIndicator.classList.add(CLASS_NAME_ACTIVE) } } } _slide(direction, element) { - const activeElement = SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) + const activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element) const activeElementIndex = this._getItemIndex(activeElement) const nextElement = element || (activeElement && this._getItemByDirection(direction, activeElement)) @@ -434,17 +426,17 @@ class Carousel { let orderClassName let eventDirectionName - if (direction === Direction.NEXT) { - directionalClassName = ClassName.LEFT - orderClassName = ClassName.NEXT - eventDirectionName = Direction.LEFT + if (direction === DIRECTION_NEXT) { + directionalClassName = CLASS_NAME_LEFT + orderClassName = CLASS_NAME_NEXT + eventDirectionName = DIRECTION_LEFT } else { - directionalClassName = ClassName.RIGHT - orderClassName = ClassName.PREV - eventDirectionName = Direction.RIGHT + directionalClassName = CLASS_NAME_RIGHT + orderClassName = CLASS_NAME_PREV + eventDirectionName = DIRECTION_RIGHT } - if (nextElement && nextElement.classList.contains(ClassName.ACTIVE)) { + if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) { this._isSliding = false return } @@ -467,7 +459,7 @@ class Carousel { this._setActiveIndicatorElement(nextElement) - if (this._element.classList.contains(ClassName.SLIDE)) { + if (this._element.classList.contains(CLASS_NAME_SLIDE)) { nextElement.classList.add(orderClassName) reflow(nextElement) @@ -489,16 +481,16 @@ class Carousel { .one(activeElement, TRANSITION_END, () => { nextElement.classList.remove(directionalClassName) nextElement.classList.remove(orderClassName) - nextElement.classList.add(ClassName.ACTIVE) + nextElement.classList.add(CLASS_NAME_ACTIVE) - activeElement.classList.remove(ClassName.ACTIVE) + activeElement.classList.remove(CLASS_NAME_ACTIVE) activeElement.classList.remove(orderClassName) activeElement.classList.remove(directionalClassName) this._isSliding = false setTimeout(() => { - EventHandler.trigger(this._element, Event.SLID, { + EventHandler.trigger(this._element, EVENT_SLID, { relatedTarget: nextElement, direction: eventDirectionName, from: activeElementIndex, @@ -509,11 +501,11 @@ class Carousel { emulateTransitionEnd(activeElement, transitionDuration) } else { - activeElement.classList.remove(ClassName.ACTIVE) - nextElement.classList.add(ClassName.ACTIVE) + activeElement.classList.remove(CLASS_NAME_ACTIVE) + nextElement.classList.add(CLASS_NAME_ACTIVE) this._isSliding = false - EventHandler.trigger(this._element, Event.SLID, { + EventHandler.trigger(this._element, EVENT_SLID, { relatedTarget: nextElement, direction: eventDirectionName, from: activeElementIndex, @@ -571,7 +563,7 @@ class Carousel { static dataApiClickHandler(event) { const target = getElementFromSelector(this) - if (!target || !target.classList.contains(ClassName.CAROUSEL)) { + if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { return } @@ -606,10 +598,10 @@ class Carousel { */ EventHandler - .on(document, Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel.dataApiClickHandler) + .on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler) -EventHandler.on(window, Event.LOAD_DATA_API, () => { - const carousels = makeArray(SelectorEngine.find(Selector.DATA_RIDE)) +EventHandler.on(window, EVENT_LOAD_DATA_API, () => { + const carousels = makeArray(SelectorEngine.find(SELECTOR_DATA_RIDE)) for (let i = 0, len = carousels.length; i < len; i++) { Carousel.carouselInterface(carousels[i], Data.getData(carousels[i], DATA_KEY)) } diff --git a/js/src/collapse.js b/js/src/collapse.js index 27eef4ef72..3b78c5cdb3 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -44,30 +44,22 @@ const DefaultType = { parent: '(string|element)' } -const Event = { - SHOW: `show${EVENT_KEY}`, - SHOWN: `shown${EVENT_KEY}`, - HIDE: `hide${EVENT_KEY}`, - HIDDEN: `hidden${EVENT_KEY}`, - CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}` -} +const EVENT_SHOW = `show${EVENT_KEY}` +const EVENT_SHOWN = `shown${EVENT_KEY}` +const EVENT_HIDE = `hide${EVENT_KEY}` +const EVENT_HIDDEN = `hidden${EVENT_KEY}` +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const ClassName = { - SHOW: 'show', - COLLAPSE: 'collapse', - COLLAPSING: 'collapsing', - COLLAPSED: 'collapsed' -} +const CLASS_NAME_SHOW = 'show' +const CLASS_NAME_COLLAPSE = 'collapse' +const CLASS_NAME_COLLAPSING = 'collapsing' +const CLASS_NAME_COLLAPSED = 'collapsed' -const Dimension = { - WIDTH: 'width', - HEIGHT: 'height' -} +const WIDTH = 'width' +const HEIGHT = 'height' -const Selector = { - ACTIVES: '.show, .collapsing', - DATA_TOGGLE: '[data-toggle="collapse"]' -} +const SELECTOR_ACTIVES = '.show, .collapsing' +const SELECTOR_DATA_TOGGLE = '[data-toggle="collapse"]' /** * ------------------------------------------------------------------------ @@ -81,11 +73,11 @@ class Collapse { this._element = element this._config = this._getConfig(config) this._triggerArray = makeArray(SelectorEngine.find( - `${Selector.DATA_TOGGLE}[href="#${element.id}"],` + - `${Selector.DATA_TOGGLE}[data-target="#${element.id}"]` + `${SELECTOR_DATA_TOGGLE}[href="#${element.id}"],` + + `${SELECTOR_DATA_TOGGLE}[data-target="#${element.id}"]` )) - const toggleList = makeArray(SelectorEngine.find(Selector.DATA_TOGGLE)) + const toggleList = makeArray(SelectorEngine.find(SELECTOR_DATA_TOGGLE)) for (let i = 0, len = toggleList.length; i < len; i++) { const elem = toggleList[i] const selector = getSelectorFromElement(elem) @@ -124,7 +116,7 @@ class Collapse { // Public toggle() { - if (this._element.classList.contains(ClassName.SHOW)) { + if (this._element.classList.contains(CLASS_NAME_SHOW)) { this.hide() } else { this.show() @@ -133,7 +125,7 @@ class Collapse { show() { if (this._isTransitioning || - this._element.classList.contains(ClassName.SHOW)) { + this._element.classList.contains(CLASS_NAME_SHOW)) { return } @@ -141,13 +133,13 @@ class Collapse { let activesData if (this._parent) { - actives = makeArray(SelectorEngine.find(Selector.ACTIVES, this._parent)) + actives = makeArray(SelectorEngine.find(SELECTOR_ACTIVES, this._parent)) .filter(elem => { if (typeof this._config.parent === 'string') { return elem.getAttribute('data-parent') === this._config.parent } - return elem.classList.contains(ClassName.COLLAPSE) + return elem.classList.contains(CLASS_NAME_COLLAPSE) }) if (actives.length === 0) { @@ -165,7 +157,7 @@ class Collapse { } } - const startEvent = EventHandler.trigger(this._element, Event.SHOW) + const startEvent = EventHandler.trigger(this._element, EVENT_SHOW) if (startEvent.defaultPrevented) { return } @@ -184,14 +176,14 @@ class Collapse { const dimension = this._getDimension() - this._element.classList.remove(ClassName.COLLAPSE) - this._element.classList.add(ClassName.COLLAPSING) + this._element.classList.remove(CLASS_NAME_COLLAPSE) + this._element.classList.add(CLASS_NAME_COLLAPSING) this._element.style[dimension] = 0 if (this._triggerArray.length) { this._triggerArray.forEach(element => { - element.classList.remove(ClassName.COLLAPSED) + element.classList.remove(CLASS_NAME_COLLAPSED) element.setAttribute('aria-expanded', true) }) } @@ -199,15 +191,15 @@ class Collapse { this.setTransitioning(true) const complete = () => { - this._element.classList.remove(ClassName.COLLAPSING) - this._element.classList.add(ClassName.COLLAPSE) - this._element.classList.add(ClassName.SHOW) + this._element.classList.remove(CLASS_NAME_COLLAPSING) + this._element.classList.add(CLASS_NAME_COLLAPSE) + this._element.classList.add(CLASS_NAME_SHOW) this._element.style[dimension] = '' this.setTransitioning(false) - EventHandler.trigger(this._element, Event.SHOWN) + EventHandler.trigger(this._element, EVENT_SHOWN) } const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) @@ -222,11 +214,11 @@ class Collapse { hide() { if (this._isTransitioning || - !this._element.classList.contains(ClassName.SHOW)) { + !this._element.classList.contains(CLASS_NAME_SHOW)) { return } - const startEvent = EventHandler.trigger(this._element, Event.HIDE) + const startEvent = EventHandler.trigger(this._element, EVENT_HIDE) if (startEvent.defaultPrevented) { return } @@ -237,9 +229,9 @@ class Collapse { reflow(this._element) - this._element.classList.add(ClassName.COLLAPSING) - this._element.classList.remove(ClassName.COLLAPSE) - this._element.classList.remove(ClassName.SHOW) + this._element.classList.add(CLASS_NAME_COLLAPSING) + this._element.classList.remove(CLASS_NAME_COLLAPSE) + this._element.classList.remove(CLASS_NAME_SHOW) const triggerArrayLength = this._triggerArray.length if (triggerArrayLength > 0) { @@ -247,8 +239,8 @@ class Collapse { const trigger = this._triggerArray[i] const elem = getElementFromSelector(trigger) - if (elem && !elem.classList.contains(ClassName.SHOW)) { - trigger.classList.add(ClassName.COLLAPSED) + if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { + trigger.classList.add(CLASS_NAME_COLLAPSED) trigger.setAttribute('aria-expanded', false) } } @@ -258,9 +250,9 @@ class Collapse { const complete = () => { this.setTransitioning(false) - this._element.classList.remove(ClassName.COLLAPSING) - this._element.classList.add(ClassName.COLLAPSE) - EventHandler.trigger(this._element, Event.HIDDEN) + this._element.classList.remove(CLASS_NAME_COLLAPSING) + this._element.classList.add(CLASS_NAME_COLLAPSE) + EventHandler.trigger(this._element, EVENT_HIDDEN) } this._element.style[dimension] = '' @@ -297,8 +289,8 @@ class Collapse { } _getDimension() { - const hasWidth = this._element.classList.contains(Dimension.WIDTH) - return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT + const hasWidth = this._element.classList.contains(WIDTH) + return hasWidth ? WIDTH : HEIGHT } _getParent() { @@ -313,7 +305,7 @@ class Collapse { parent = SelectorEngine.findOne(parent) } - const selector = `${Selector.DATA_TOGGLE}[data-parent="${parent}"]` + const selector = `${SELECTOR_DATA_TOGGLE}[data-parent="${parent}"]` makeArray(SelectorEngine.find(selector, parent)) .forEach(element => { @@ -330,14 +322,14 @@ class Collapse { _addAriaAndCollapsedClass(element, triggerArray) { if (element) { - const isOpen = element.classList.contains(ClassName.SHOW) + const isOpen = element.classList.contains(CLASS_NAME_SHOW) if (triggerArray.length) { triggerArray.forEach(elem => { if (isOpen) { - elem.classList.remove(ClassName.COLLAPSED) + elem.classList.remove(CLASS_NAME_COLLAPSED) } else { - elem.classList.add(ClassName.COLLAPSED) + elem.classList.add(CLASS_NAME_COLLAPSED) } elem.setAttribute('aria-expanded', isOpen) @@ -390,7 +382,7 @@ class Collapse { * ------------------------------------------------------------------------ */ -EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { +EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.target.tagName === 'A') { event.preventDefault() diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 82a24405aa..9d6f8a3296 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -31,54 +31,46 @@ 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 Event = { - HIDE: `hide${EVENT_KEY}`, - HIDDEN: `hidden${EVENT_KEY}`, - SHOW: `show${EVENT_KEY}`, - SHOWN: `shown${EVENT_KEY}`, - CLICK: `click${EVENT_KEY}`, - CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, - KEYDOWN_DATA_API: `keydown${EVENT_KEY}${DATA_API_KEY}`, - KEYUP_DATA_API: `keyup${EVENT_KEY}${DATA_API_KEY}` -} +const EVENT_HIDE = `hide${EVENT_KEY}` +const EVENT_HIDDEN = `hidden${EVENT_KEY}` +const EVENT_SHOW = `show${EVENT_KEY}` +const EVENT_SHOWN = `shown${EVENT_KEY}` +const EVENT_CLICK = `click${EVENT_KEY}` +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` +const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}` +const EVENT_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', - NAVBAR: 'navbar', - POSITION_STATIC: 'position-static' -} +const CLASS_NAME_DISABLED = 'disabled' +const CLASS_NAME_SHOW = 'show' +const CLASS_NAME_DROPUP = 'dropup' +const CLASS_NAME_DROPRIGHT = 'dropright' +const CLASS_NAME_DROPLEFT = 'dropleft' +const CLASS_NAME_MENURIGHT = 'dropdown-menu-right' +const CLASS_NAME_NAVBAR = 'navbar' +const CLASS_NAME_POSITION_STATIC = 'position-static' -const Selector = { - DATA_TOGGLE: '[data-toggle="dropdown"]', - FORM_CHILD: '.dropdown form', - MENU: '.dropdown-menu', - NAVBAR_NAV: '.navbar-nav', - VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' -} +const SELECTOR_DATA_TOGGLE = '[data-toggle="dropdown"]' +const SELECTOR_FORM_CHILD = '.dropdown form' +const SELECTOR_MENU = '.dropdown-menu' +const SELECTOR_NAVBAR_NAV = '.navbar-nav' +const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' -const AttachmentMap = { - TOP: 'top-start', - TOPEND: 'top-end', - BOTTOM: 'bottom-start', - BOTTOMEND: 'bottom-end', - RIGHT: 'right-start', - RIGHTEND: 'right-end', - LEFT: 'left-start', - LEFTEND: 'left-end' -} +const PLACEMENT_TOP = 'top-start' +const PLACEMENT_TOPEND = 'top-end' +const PLACEMENT_BOTTOM = 'bottom-start' +const PLACEMENT_BOTTOMEND = 'bottom-end' +const PLACEMENT_RIGHT = 'right-start' +const PLACEMENT_LEFT = 'left-start' const Default = { offset: 0, @@ -133,11 +125,11 @@ class Dropdown { // Public toggle() { - if (this._element.disabled || this._element.classList.contains(ClassName.DISABLED)) { + if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED)) { return } - const isActive = this._menu.classList.contains(ClassName.SHOW) + const isActive = this._menu.classList.contains(CLASS_NAME_SHOW) Dropdown.clearMenus() @@ -149,7 +141,7 @@ class Dropdown { } show() { - if (this._element.disabled || this._element.classList.contains(ClassName.DISABLED) || this._menu.classList.contains(ClassName.SHOW)) { + if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || this._menu.classList.contains(CLASS_NAME_SHOW)) { return } @@ -158,7 +150,7 @@ class Dropdown { relatedTarget: this._element } - const showEvent = EventHandler.trigger(parent, Event.SHOW, relatedTarget) + const showEvent = EventHandler.trigger(parent, EVENT_SHOW, relatedTarget) if (showEvent.defaultPrevented) { return @@ -187,7 +179,7 @@ class Dropdown { // to allow the menu to "escape" the scroll parent's boundaries // https://github.com/twbs/bootstrap/issues/24251 if (this._config.boundary !== 'scrollParent') { - parent.classList.add(ClassName.POSITION_STATIC) + parent.classList.add(CLASS_NAME_POSITION_STATIC) } this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) @@ -198,7 +190,7 @@ class Dropdown { // 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(SelectorEngine.closest(parent, Selector.NAVBAR_NAV)).length) { + !makeArray(SelectorEngine.closest(parent, SELECTOR_NAVBAR_NAV)).length) { makeArray(document.body.children) .forEach(elem => EventHandler.on(elem, 'mouseover', null, noop())) } @@ -206,13 +198,13 @@ class Dropdown { this._element.focus() this._element.setAttribute('aria-expanded', true) - Manipulator.toggleClass(this._menu, ClassName.SHOW) - Manipulator.toggleClass(parent, ClassName.SHOW) - EventHandler.trigger(parent, Event.SHOWN, relatedTarget) + Manipulator.toggleClass(this._menu, CLASS_NAME_SHOW) + Manipulator.toggleClass(parent, CLASS_NAME_SHOW) + EventHandler.trigger(parent, EVENT_SHOWN, relatedTarget) } hide() { - if (this._element.disabled || this._element.classList.contains(ClassName.DISABLED) || !this._menu.classList.contains(ClassName.SHOW)) { + if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { return } @@ -221,7 +213,7 @@ class Dropdown { relatedTarget: this._element } - const hideEvent = EventHandler.trigger(parent, Event.HIDE, relatedTarget) + const hideEvent = EventHandler.trigger(parent, EVENT_HIDE, relatedTarget) if (hideEvent.defaultPrevented) { return @@ -231,9 +223,9 @@ class Dropdown { this._popper.destroy() } - Manipulator.toggleClass(this._menu, ClassName.SHOW) - Manipulator.toggleClass(parent, ClassName.SHOW) - EventHandler.trigger(parent, Event.HIDDEN, relatedTarget) + Manipulator.toggleClass(this._menu, CLASS_NAME_SHOW) + Manipulator.toggleClass(parent, CLASS_NAME_SHOW) + EventHandler.trigger(parent, EVENT_HIDDEN, relatedTarget) } dispose() { @@ -257,7 +249,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() @@ -283,32 +275,32 @@ class Dropdown { _getMenuElement() { const parent = Dropdown.getParentFromElement(this._element) - return SelectorEngine.findOne(Selector.MENU, parent) + return SelectorEngine.findOne(SELECTOR_MENU, parent) } _getPlacement() { const parentDropdown = this._element.parentNode - let placement = AttachmentMap.BOTTOM + let placement = PLACEMENT_BOTTOM // Handle dropup - if (parentDropdown.classList.contains(ClassName.DROPUP)) { - placement = AttachmentMap.TOP - if (this._menu.classList.contains(ClassName.MENURIGHT)) { - placement = AttachmentMap.TOPEND + if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { + placement = PLACEMENT_TOP + if (this._menu.classList.contains(CLASS_NAME_MENURIGHT)) { + placement = PLACEMENT_TOPEND } - } else if (parentDropdown.classList.contains(ClassName.DROPRIGHT)) { - placement = AttachmentMap.RIGHT - } else if (parentDropdown.classList.contains(ClassName.DROPLEFT)) { - placement = AttachmentMap.LEFT - } else if (this._menu.classList.contains(ClassName.MENURIGHT)) { - placement = AttachmentMap.BOTTOMEND + } else if (parentDropdown.classList.contains(CLASS_NAME_DROPRIGHT)) { + placement = PLACEMENT_RIGHT + } else if (parentDropdown.classList.contains(CLASS_NAME_DROPLEFT)) { + placement = PLACEMENT_LEFT + } else if (this._menu.classList.contains(CLASS_NAME_MENURIGHT)) { + placement = PLACEMENT_BOTTOMEND } return placement } _detectNavbar() { - return Boolean(SelectorEngine.closest(this._element, `.${ClassName.NAVBAR}`)) + return Boolean(SelectorEngine.closest(this._element, `.${CLASS_NAME_NAVBAR}`)) } _getOffset() { @@ -388,7 +380,7 @@ class Dropdown { return } - const toggles = makeArray(SelectorEngine.find(Selector.DATA_TOGGLE)) + 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) @@ -405,7 +397,7 @@ class Dropdown { } const dropdownMenu = context._menu - if (!parent.classList.contains(ClassName.SHOW)) { + if (!parent.classList.contains(CLASS_NAME_SHOW)) { continue } @@ -416,7 +408,7 @@ class Dropdown { continue } - const hideEvent = EventHandler.trigger(parent, Event.HIDE, relatedTarget) + const hideEvent = EventHandler.trigger(parent, EVENT_HIDE, relatedTarget) if (hideEvent.defaultPrevented) { continue } @@ -434,9 +426,9 @@ class Dropdown { context._popper.destroy() } - dropdownMenu.classList.remove(ClassName.SHOW) - parent.classList.remove(ClassName.SHOW) - EventHandler.trigger(parent, Event.HIDDEN, relatedTarget) + dropdownMenu.classList.remove(CLASS_NAME_SHOW) + parent.classList.remove(CLASS_NAME_SHOW) + EventHandler.trigger(parent, EVENT_HIDDEN, relatedTarget) } } @@ -455,7 +447,7 @@ class Dropdown { 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))) : + SelectorEngine.closest(event.target, SELECTOR_MENU))) : !REGEXP_KEYDOWN.test(event.which)) { return } @@ -463,23 +455,23 @@ class Dropdown { event.preventDefault() event.stopPropagation() - if (this.disabled || this.classList.contains(ClassName.DISABLED)) { + if (this.disabled || this.classList.contains(CLASS_NAME_DISABLED)) { return } const parent = Dropdown.getParentFromElement(this) - const isActive = parent.classList.contains(ClassName.SHOW) + const isActive = parent.classList.contains(CLASS_NAME_SHOW) if (!isActive || (isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE))) { if (event.which === ESCAPE_KEYCODE) { - SelectorEngine.findOne(Selector.DATA_TOGGLE, parent).focus() + SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, parent).focus() } Dropdown.clearMenus() return } - const items = makeArray(SelectorEngine.find(Selector.VISIBLE_ITEMS, parent)) + const items = makeArray(SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, parent)) .filter(isVisible) if (!items.length) { @@ -514,17 +506,17 @@ class Dropdown { * ------------------------------------------------------------------------ */ -EventHandler.on(document, Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown.dataApiKeydownHandler) -EventHandler.on(document, Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown.dataApiKeydownHandler) -EventHandler.on(document, Event.CLICK_DATA_API, Dropdown.clearMenus) -EventHandler.on(document, Event.KEYUP_DATA_API, Dropdown.clearMenus) -EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { +EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler) +EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler) +EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus) +EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus) +EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { event.preventDefault() event.stopPropagation() 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()) const $ = getjQuery() diff --git a/js/src/modal.js b/js/src/modal.js index 48ff5b8540..bcf13454fe 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -48,39 +48,33 @@ const DefaultType = { show: 'boolean' } -const Event = { - HIDE: `hide${EVENT_KEY}`, - HIDE_PREVENTED: `hidePrevented${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 EVENT_HIDE = `hide${EVENT_KEY}` +const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}` +const EVENT_HIDDEN = `hidden${EVENT_KEY}` +const EVENT_SHOW = `show${EVENT_KEY}` +const EVENT_SHOWN = `shown${EVENT_KEY}` +const EVENT_FOCUSIN = `focusin${EVENT_KEY}` +const EVENT_RESIZE = `resize${EVENT_KEY}` +const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` +const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}` +const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY}` +const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}` +const EVENT_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', - STATIC: 'modal-static' -} +const CLASS_NAME_SCROLLABLE = 'modal-dialog-scrollable' +const CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure' +const CLASS_NAME_BACKDROP = 'modal-backdrop' +const CLASS_NAME_OPEN = 'modal-open' +const CLASS_NAME_FADE = 'fade' +const CLASS_NAME_SHOW = 'show' +const CLASS_NAME_STATIC = 'modal-static' -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' -} +const SELECTOR_DIALOG = '.modal-dialog' +const SELECTOR_MODAL_BODY = '.modal-body' +const SELECTOR_DATA_TOGGLE = '[data-toggle="modal"]' +const SELECTOR_DATA_DISMISS = '[data-dismiss="modal"]' +const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' +const SELECTOR_STICKY_CONTENT = '.sticky-top' /** * ------------------------------------------------------------------------ @@ -92,7 +86,7 @@ class Modal { constructor(element, config) { this._config = this._getConfig(config) this._element = element - this._dialog = SelectorEngine.findOne(Selector.DIALOG, element) + this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element) this._backdrop = null this._isShown = false this._isBodyOverflowing = false @@ -123,11 +117,11 @@ class Modal { return } - if (this._element.classList.contains(ClassName.FADE)) { + if (this._element.classList.contains(CLASS_NAME_FADE)) { this._isTransitioning = true } - const showEvent = EventHandler.trigger(this._element, Event.SHOW, { + const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget }) @@ -146,13 +140,13 @@ class Modal { this._setResizeEvent() EventHandler.on(this._element, - Event.CLICK_DISMISS, - Selector.DATA_DISMISS, + EVENT_CLICK_DISMISS, + SELECTOR_DATA_DISMISS, event => this.hide(event) ) - EventHandler.on(this._dialog, Event.MOUSEDOWN_DISMISS, () => { - EventHandler.one(this._element, Event.MOUSEUP_DISMISS, event => { + EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { + EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, event => { if (event.target === this._element) { this._ignoreBackdropClick = true } @@ -171,14 +165,14 @@ class Modal { return } - const hideEvent = EventHandler.trigger(this._element, Event.HIDE) + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE) if (hideEvent.defaultPrevented) { return } this._isShown = false - const transition = this._element.classList.contains(ClassName.FADE) + const transition = this._element.classList.contains(CLASS_NAME_FADE) if (transition) { this._isTransitioning = true @@ -187,12 +181,12 @@ class Modal { this._setEscapeEvent() this._setResizeEvent() - EventHandler.off(document, Event.FOCUSIN) + EventHandler.off(document, EVENT_FOCUSIN) - this._element.classList.remove(ClassName.SHOW) + this._element.classList.remove(CLASS_NAME_SHOW) - EventHandler.off(this._element, Event.CLICK_DISMISS) - EventHandler.off(this._dialog, Event.MOUSEDOWN_DISMISS) + EventHandler.off(this._element, EVENT_CLICK_DISMISS) + EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS) if (transition) { const transitionDuration = getTransitionDurationFromElement(this._element) @@ -209,11 +203,11 @@ class Modal { .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) /** - * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` + * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API` * Do not move `document` in `htmlElements` array - * It will remove `Event.CLICK_DATA_API` event that should remain + * It will remove `EVENT_CLICK_DATA_API` event that should remain */ - EventHandler.off(document, Event.FOCUSIN) + EventHandler.off(document, EVENT_FOCUSIN) Data.removeData(this._element, DATA_KEY) @@ -244,8 +238,8 @@ class Modal { } _showElement(relatedTarget) { - const transition = this._element.classList.contains(ClassName.FADE) - const modalBody = SelectorEngine.findOne(Selector.MODAL_BODY, this._dialog) + const transition = this._element.classList.contains(CLASS_NAME_FADE) + const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog) if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { @@ -257,7 +251,7 @@ class Modal { this._element.removeAttribute('aria-hidden') this._element.setAttribute('aria-modal', true) - if (this._dialog.classList.contains(ClassName.SCROLLABLE) && modalBody) { + if (this._dialog.classList.contains(CLASS_NAME_SCROLLABLE) && modalBody) { modalBody.scrollTop = 0 } else { this._element.scrollTop = 0 @@ -267,7 +261,7 @@ class Modal { reflow(this._element) } - this._element.classList.add(ClassName.SHOW) + this._element.classList.add(CLASS_NAME_SHOW) if (this._config.focus) { this._enforceFocus() @@ -279,7 +273,7 @@ class Modal { } this._isTransitioning = false - EventHandler.trigger(this._element, Event.SHOWN, { + EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget }) } @@ -295,8 +289,8 @@ class Modal { } _enforceFocus() { - EventHandler.off(document, Event.FOCUSIN) // guard against infinite focus loop - EventHandler.on(document, Event.FOCUSIN, event => { + EventHandler.off(document, EVENT_FOCUSIN) // guard against infinite focus loop + EventHandler.on(document, EVENT_FOCUSIN, event => { if (document !== event.target && this._element !== event.target && !this._element.contains(event.target)) { @@ -307,7 +301,7 @@ class Modal { _setEscapeEvent() { if (this._isShown) { - EventHandler.on(this._element, Event.KEYDOWN_DISMISS, event => { + EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { if (this._config.keyboard && event.which === ESCAPE_KEYCODE) { event.preventDefault() this.hide() @@ -316,15 +310,15 @@ class Modal { } }) } else { - EventHandler.off(this._element, Event.KEYDOWN_DISMISS) + EventHandler.off(this._element, EVENT_KEYDOWN_DISMISS) } } _setResizeEvent() { if (this._isShown) { - EventHandler.on(window, Event.RESIZE, () => this._adjustDialog()) + EventHandler.on(window, EVENT_RESIZE, () => this._adjustDialog()) } else { - EventHandler.off(window, Event.RESIZE) + EventHandler.off(window, EVENT_RESIZE) } } @@ -334,10 +328,10 @@ class Modal { this._element.removeAttribute('aria-modal') this._isTransitioning = false this._showBackdrop(() => { - document.body.classList.remove(ClassName.OPEN) + document.body.classList.remove(CLASS_NAME_OPEN) this._resetAdjustments() this._resetScrollbar() - EventHandler.trigger(this._element, Event.HIDDEN) + EventHandler.trigger(this._element, EVENT_HIDDEN) }) } @@ -347,13 +341,13 @@ class Modal { } _showBackdrop(callback) { - const animate = this._element.classList.contains(ClassName.FADE) ? - ClassName.FADE : + const animate = this._element.classList.contains(CLASS_NAME_FADE) ? + CLASS_NAME_FADE : '' if (this._isShown && this._config.backdrop) { this._backdrop = document.createElement('div') - this._backdrop.className = ClassName.BACKDROP + this._backdrop.className = CLASS_NAME_BACKDROP if (animate) { this._backdrop.classList.add(animate) @@ -361,7 +355,7 @@ 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 @@ -378,7 +372,7 @@ class Modal { reflow(this._backdrop) } - this._backdrop.classList.add(ClassName.SHOW) + this._backdrop.classList.add(CLASS_NAME_SHOW) if (!animate) { callback() @@ -390,14 +384,14 @@ class Modal { EventHandler.one(this._backdrop, TRANSITION_END, callback) emulateTransitionEnd(this._backdrop, backdropTransitionDuration) } else if (!this._isShown && this._backdrop) { - this._backdrop.classList.remove(ClassName.SHOW) + this._backdrop.classList.remove(CLASS_NAME_SHOW) const callbackRemove = () => { this._removeBackdrop() callback() } - if (this._element.classList.contains(ClassName.FADE)) { + if (this._element.classList.contains(CLASS_NAME_FADE)) { const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove) emulateTransitionEnd(this._backdrop, backdropTransitionDuration) @@ -411,15 +405,15 @@ class Modal { _triggerBackdropTransition() { if (this._config.backdrop === 'static') { - const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED) if (hideEvent.defaultPrevented) { return } - this._element.classList.add(ClassName.STATIC) + this._element.classList.add(CLASS_NAME_STATIC) const modalTransitionDuration = getTransitionDurationFromElement(this._element) EventHandler.one(this._element, TRANSITION_END, () => { - this._element.classList.remove(ClassName.STATIC) + this._element.classList.remove(CLASS_NAME_STATIC) }) emulateTransitionEnd(this._element, modalTransitionDuration) this._element.focus() @@ -462,7 +456,7 @@ class Modal { // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set // Adjust fixed content padding - makeArray(SelectorEngine.find(Selector.FIXED_CONTENT)) + makeArray(SelectorEngine.find(SELECTOR_FIXED_CONTENT)) .forEach(element => { const actualPadding = element.style.paddingRight const calculatedPadding = window.getComputedStyle(element)['padding-right'] @@ -471,7 +465,7 @@ class Modal { }) // Adjust sticky content margin - makeArray(SelectorEngine.find(Selector.STICKY_CONTENT)) + makeArray(SelectorEngine.find(SELECTOR_STICKY_CONTENT)) .forEach(element => { const actualMargin = element.style.marginRight const calculatedMargin = window.getComputedStyle(element)['margin-right'] @@ -487,12 +481,12 @@ class Modal { document.body.style.paddingRight = `${parseFloat(calculatedPadding) + this._scrollbarWidth}px` } - document.body.classList.add(ClassName.OPEN) + document.body.classList.add(CLASS_NAME_OPEN) } _resetScrollbar() { // Restore fixed content padding - makeArray(SelectorEngine.find(Selector.FIXED_CONTENT)) + makeArray(SelectorEngine.find(SELECTOR_FIXED_CONTENT)) .forEach(element => { const padding = Manipulator.getDataAttribute(element, 'padding-right') if (typeof padding !== 'undefined') { @@ -502,7 +496,7 @@ class Modal { }) // Restore sticky content and navbar-toggler margin - makeArray(SelectorEngine.find(`${Selector.STICKY_CONTENT}`)) + makeArray(SelectorEngine.find(`${SELECTOR_STICKY_CONTENT}`)) .forEach(element => { const margin = Manipulator.getDataAttribute(element, 'margin-right') if (typeof margin !== 'undefined') { @@ -523,7 +517,7 @@ class Modal { _getScrollbarWidth() { // thx d.walsh const scrollDiv = document.createElement('div') - scrollDiv.className = ClassName.SCROLLBAR_MEASURER + scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER document.body.appendChild(scrollDiv) const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth document.body.removeChild(scrollDiv) @@ -568,20 +562,20 @@ class Modal { * ------------------------------------------------------------------------ */ -EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { +EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { const target = getElementFromSelector(this) if (this.tagName === 'A' || this.tagName === 'AREA') { 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 } - EventHandler.one(target, Event.HIDDEN, () => { + EventHandler.one(target, EVENT_HIDDEN, () => { if (isVisible(this)) { this.focus() } diff --git a/js/src/popover.js b/js/src/popover.js index d71a78236c..2d423f0dd5 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -39,16 +39,6 @@ const DefaultType = { content: '(string|element|function)' } -const ClassName = { - FADE: 'fade', - SHOW: 'show' -} - -const Selector = { - TITLE: '.popover-header', - CONTENT: '.popover-body' -} - const Event = { HIDE: `hide${EVENT_KEY}`, HIDDEN: `hidden${EVENT_KEY}`, @@ -62,6 +52,12 @@ const Event = { MOUSELEAVE: `mouseleave${EVENT_KEY}` } +const CLASS_NAME_FADE = 'fade' +const CLASS_NAME_SHOW = 'show' + +const SELECTOR_TITLE = '.popover-header' +const SELECTOR_CONTENT = '.popover-body' + /** * ------------------------------------------------------------------------ * Class Definition @@ -109,16 +105,16 @@ class Popover extends Tooltip { const tip = this.getTipElement() // we use append for html objects to maintain js events - this.setElementContent(SelectorEngine.findOne(Selector.TITLE, tip), this.getTitle()) + this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle()) let content = this._getContent() if (typeof content === 'function') { content = content.call(this.element) } - this.setElementContent(SelectorEngine.findOne(Selector.CONTENT, tip), content) + this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content) - tip.classList.remove(ClassName.FADE) - tip.classList.remove(ClassName.SHOW) + tip.classList.remove(CLASS_NAME_FADE) + tip.classList.remove(CLASS_NAME_SHOW) } _addAttachmentClass(attachment) { diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js index c379c62235..dd68ed386e 100644 --- a/js/src/scrollspy.js +++ b/js/src/scrollspy.js @@ -41,31 +41,23 @@ const DefaultType = { target: '(string|element)' } -const Event = { - ACTIVATE: `activate${EVENT_KEY}`, - SCROLL: `scroll${EVENT_KEY}`, - LOAD_DATA_API: `load${EVENT_KEY}${DATA_API_KEY}` -} +const EVENT_ACTIVATE = `activate${EVENT_KEY}` +const EVENT_SCROLL = `scroll${EVENT_KEY}` +const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}` -const ClassName = { - DROPDOWN_ITEM: 'dropdown-item', - ACTIVE: 'active' -} +const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item' +const CLASS_NAME_ACTIVE = 'active' -const Selector = { - DATA_SPY: '[data-spy="scroll"]', - NAV_LIST_GROUP: '.nav, .list-group', - NAV_LINKS: '.nav-link', - NAV_ITEMS: '.nav-item', - LIST_ITEMS: '.list-group-item', - DROPDOWN: '.dropdown', - DROPDOWN_TOGGLE: '.dropdown-toggle' -} +const SELECTOR_DATA_SPY = '[data-spy="scroll"]' +const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group' +const SELECTOR_NAV_LINKS = '.nav-link' +const SELECTOR_NAV_ITEMS = '.nav-item' +const SELECTOR_LIST_ITEMS = '.list-group-item' +const SELECTOR_DROPDOWN = '.dropdown' +const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle' -const OffsetMethod = { - OFFSET: 'offset', - POSITION: 'position' -} +const METHOD_OFFSET = 'offset' +const METHOD_POSITION = 'position' /** * ------------------------------------------------------------------------ @@ -78,15 +70,15 @@ class ScrollSpy { this._element = element this._scrollElement = element.tagName === 'BODY' ? window : element this._config = this._getConfig(config) - this._selector = `${this._config.target} ${Selector.NAV_LINKS},` + - `${this._config.target} ${Selector.LIST_ITEMS},` + - `${this._config.target} .${ClassName.DROPDOWN_ITEM}` + this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS},` + + `${this._config.target} ${SELECTOR_LIST_ITEMS},` + + `${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}` 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() @@ -108,14 +100,14 @@ class ScrollSpy { refresh() { const autoMethod = this._scrollElement === this._scrollElement.window ? - OffsetMethod.OFFSET : - OffsetMethod.POSITION + METHOD_OFFSET : + METHOD_POSITION const offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method - const offsetBase = offsetMethod === OffsetMethod.POSITION ? + const offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0 @@ -261,42 +253,42 @@ class ScrollSpy { const link = SelectorEngine.findOne(queries.join(',')) - if (link.classList.contains(ClassName.DROPDOWN_ITEM)) { + if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { SelectorEngine - .findOne(Selector.DROPDOWN_TOGGLE, SelectorEngine.closest(link, Selector.DROPDOWN)) - .classList.add(ClassName.ACTIVE) + .findOne(SELECTOR_DROPDOWN_TOGGLE, SelectorEngine.closest(link, SELECTOR_DROPDOWN)) + .classList.add(CLASS_NAME_ACTIVE) - link.classList.add(ClassName.ACTIVE) + link.classList.add(CLASS_NAME_ACTIVE) } else { // Set triggered link as active - link.classList.add(ClassName.ACTIVE) + link.classList.add(CLASS_NAME_ACTIVE) SelectorEngine - .parents(link, Selector.NAV_LIST_GROUP) + .parents(link, SELECTOR_NAV_LIST_GROUP) .forEach(listGroup => { // Set triggered links parents as active // With both