mirror of
https://github.com/twbs/bootstrap.git
synced 2024-12-01 13:24:25 +01:00
Extract Component config functionality to a separate class (#33872)
Co-authored-by: XhmikosR <xhmikosr@gmail.com>
This commit is contained in:
parent
68f226750d
commit
886b940796
@ -6,11 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Data from './dom/data'
|
import Data from './dom/data'
|
||||||
import {
|
import { executeAfterTransition, getElement } from './util/index'
|
||||||
executeAfterTransition,
|
|
||||||
getElement
|
|
||||||
} from './util/index'
|
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
|
import Config from './util/config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -22,15 +20,18 @@ const VERSION = '5.1.3'
|
|||||||
* Class definition
|
* Class definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BaseComponent {
|
class BaseComponent extends Config {
|
||||||
constructor(element) {
|
constructor(element, config) {
|
||||||
element = getElement(element)
|
super()
|
||||||
|
|
||||||
|
element = getElement(element)
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._element = element
|
this._element = element
|
||||||
|
this._config = this._getConfig(config)
|
||||||
|
|
||||||
Data.set(this._element, this.constructor.DATA_KEY, this)
|
Data.set(this._element, this.constructor.DATA_KEY, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +49,13 @@ class BaseComponent {
|
|||||||
executeAfterTransition(callback, element, isAnimated)
|
executeAfterTransition(callback, element, isAnimated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getConfig(config) {
|
||||||
|
config = this._mergeConfigObj(config, this._element)
|
||||||
|
config = this._configAfterMerge(config)
|
||||||
|
this._typeCheckConfig(config)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
static getInstance(element) {
|
static getInstance(element) {
|
||||||
return Data.get(getElement(element), this.DATA_KEY)
|
return Data.get(getElement(element), this.DATA_KEY)
|
||||||
@ -61,10 +69,6 @@ class BaseComponent {
|
|||||||
return VERSION
|
return VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
static get NAME() {
|
|
||||||
throw new Error('You have to implement the static method "NAME" for each component!')
|
|
||||||
}
|
|
||||||
|
|
||||||
static get DATA_KEY() {
|
static get DATA_KEY() {
|
||||||
return `bs.${this.NAME}`
|
return `bs.${this.NAME}`
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ import {
|
|||||||
isRTL,
|
isRTL,
|
||||||
isVisible,
|
isVisible,
|
||||||
reflow,
|
reflow,
|
||||||
triggerTransitionEnd,
|
triggerTransitionEnd
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
@ -95,7 +94,7 @@ const DefaultType = {
|
|||||||
|
|
||||||
class Carousel extends BaseComponent {
|
class Carousel extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._items = null
|
this._items = null
|
||||||
this._interval = null
|
this._interval = null
|
||||||
@ -105,7 +104,6 @@ class Carousel extends BaseComponent {
|
|||||||
this.touchTimeout = null
|
this.touchTimeout = null
|
||||||
this._swipeHelper = null
|
this._swipeHelper = null
|
||||||
|
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
|
this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
|
||||||
this._addEventListeners()
|
this._addEventListeners()
|
||||||
}
|
}
|
||||||
@ -115,6 +113,10 @@ class Carousel extends BaseComponent {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -205,16 +207,6 @@ class Carousel extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
_addEventListeners() {
|
_addEventListeners() {
|
||||||
if (this._config.keyboard) {
|
if (this._config.keyboard) {
|
||||||
EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))
|
EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))
|
||||||
|
@ -10,11 +10,9 @@ import {
|
|||||||
getElement,
|
getElement,
|
||||||
getElementFromSelector,
|
getElementFromSelector,
|
||||||
getSelectorFromElement,
|
getSelectorFromElement,
|
||||||
reflow,
|
reflow
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
|
|
||||||
@ -62,10 +60,9 @@ const DefaultType = {
|
|||||||
|
|
||||||
class Collapse extends BaseComponent {
|
class Collapse extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._isTransitioning = false
|
this._isTransitioning = false
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._triggerArray = []
|
this._triggerArray = []
|
||||||
|
|
||||||
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
|
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
|
||||||
@ -96,6 +93,10 @@ class Collapse extends BaseComponent {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -210,15 +211,9 @@ class Collapse extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
_configAfterMerge(config) {
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...config
|
|
||||||
}
|
|
||||||
config.toggle = Boolean(config.toggle) // Coerce string values
|
config.toggle = Boolean(config.toggle) // Coerce string values
|
||||||
config.parent = getElement(config.parent)
|
config.parent = getElement(config.parent)
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@ import {
|
|||||||
isElement,
|
isElement,
|
||||||
isRTL,
|
isRTL,
|
||||||
isVisible,
|
isVisible,
|
||||||
noop,
|
noop
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
@ -88,10 +87,9 @@ const DefaultType = {
|
|||||||
|
|
||||||
class Dropdown extends BaseComponent {
|
class Dropdown extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._popper = null
|
this._popper = null
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._menu = this._getMenuElement()
|
this._menu = this._getMenuElement()
|
||||||
this._inNavbar = this._detectNavbar()
|
this._inNavbar = this._detectNavbar()
|
||||||
}
|
}
|
||||||
@ -205,13 +203,7 @@ class Dropdown extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getConfig(config) {
|
_getConfig(config) {
|
||||||
config = {
|
config = super._getConfig(config)
|
||||||
...this.constructor.Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...config
|
|
||||||
}
|
|
||||||
|
|
||||||
typeCheckConfig(NAME, config, this.constructor.DefaultType)
|
|
||||||
|
|
||||||
if (typeof config.reference === 'object' && !isElement(config.reference) &&
|
if (typeof config.reference === 'object' && !isElement(config.reference) &&
|
||||||
typeof config.reference.getBoundingClientRect !== 'function'
|
typeof config.reference.getBoundingClientRect !== 'function'
|
||||||
|
@ -5,16 +5,8 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { defineJQueryPlugin, getElementFromSelector, isRTL, isVisible, reflow } from './util/index'
|
||||||
defineJQueryPlugin,
|
|
||||||
getElementFromSelector,
|
|
||||||
isRTL,
|
|
||||||
isVisible,
|
|
||||||
reflow,
|
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
import ScrollBarHelper from './util/scrollbar'
|
import ScrollBarHelper from './util/scrollbar'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
@ -70,9 +62,8 @@ const DefaultType = {
|
|||||||
|
|
||||||
class Modal extends BaseComponent {
|
class Modal extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element)
|
this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element)
|
||||||
this._backdrop = this._initializeBackDrop()
|
this._backdrop = this._initializeBackDrop()
|
||||||
this._focustrap = this._initializeFocusTrap()
|
this._focustrap = this._initializeFocusTrap()
|
||||||
@ -86,6 +77,10 @@ class Modal extends BaseComponent {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -175,16 +170,6 @@ class Modal extends BaseComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
_showElement(relatedTarget) {
|
_showElement(relatedTarget) {
|
||||||
// try to append dynamic modal
|
// try to append dynamic modal
|
||||||
if (!document.body.contains(this._element)) {
|
if (!document.body.contains(this._element)) {
|
||||||
|
@ -9,14 +9,12 @@ import {
|
|||||||
defineJQueryPlugin,
|
defineJQueryPlugin,
|
||||||
getElementFromSelector,
|
getElementFromSelector,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
isVisible,
|
isVisible
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import ScrollBarHelper from './util/scrollbar'
|
import ScrollBarHelper from './util/scrollbar'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
import Manipulator from './dom/manipulator'
|
|
||||||
import Backdrop from './util/backdrop'
|
import Backdrop from './util/backdrop'
|
||||||
import FocusTrap from './util/focustrap'
|
import FocusTrap from './util/focustrap'
|
||||||
import { enableDismissTrigger } from './util/component-functions'
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
@ -63,9 +61,8 @@ const DefaultType = {
|
|||||||
|
|
||||||
class Offcanvas extends BaseComponent {
|
class Offcanvas extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._isShown = false
|
this._isShown = false
|
||||||
this._backdrop = this._initializeBackDrop()
|
this._backdrop = this._initializeBackDrop()
|
||||||
this._focustrap = this._initializeFocusTrap()
|
this._focustrap = this._initializeFocusTrap()
|
||||||
@ -73,14 +70,18 @@ class Offcanvas extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
static get NAME() {
|
|
||||||
return NAME
|
|
||||||
}
|
|
||||||
|
|
||||||
static get Default() {
|
static get Default() {
|
||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
toggle(relatedTarget) {
|
toggle(relatedTarget) {
|
||||||
return this._isShown ? this.hide() : this.show(relatedTarget)
|
return this._isShown ? this.hide() : this.show(relatedTarget)
|
||||||
@ -162,16 +163,6 @@ class Offcanvas extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
_initializeBackDrop() {
|
_initializeBackDrop() {
|
||||||
return new Backdrop({
|
return new Backdrop({
|
||||||
className: CLASS_NAME_BACKDROP,
|
className: CLASS_NAME_BACKDROP,
|
||||||
|
@ -60,6 +60,10 @@ class Popover extends Tooltip {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -68,10 +72,6 @@ class Popover extends Tooltip {
|
|||||||
return Event
|
return Event
|
||||||
}
|
}
|
||||||
|
|
||||||
static get DefaultType() {
|
|
||||||
return DefaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
_isWithContent() {
|
_isWithContent() {
|
||||||
return this._getTitle() || this._getContent()
|
return this._getTitle() || this._getContent()
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
import {
|
import {
|
||||||
defineJQueryPlugin,
|
defineJQueryPlugin,
|
||||||
getElement,
|
getElement,
|
||||||
getSelectorFromElement,
|
getSelectorFromElement
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
@ -62,9 +61,8 @@ const DefaultType = {
|
|||||||
|
|
||||||
class ScrollSpy extends BaseComponent {
|
class ScrollSpy extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
|
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._offsets = []
|
this._offsets = []
|
||||||
this._targets = []
|
this._targets = []
|
||||||
this._activeTarget = null
|
this._activeTarget = null
|
||||||
@ -81,6 +79,10 @@ class ScrollSpy extends BaseComponent {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -135,17 +137,10 @@ class ScrollSpy extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...(typeof config === 'object' && config ? config : {})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_configAfterMerge(config) {
|
||||||
config.target = getElement(config.target) || document.documentElement
|
config.target = getElement(config.target) || document.documentElement
|
||||||
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineJQueryPlugin, reflow, typeCheckConfig } from './util/index'
|
import { defineJQueryPlugin, reflow } from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
import { enableDismissTrigger } from './util/component-functions'
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
|
|
||||||
@ -51,9 +50,8 @@ const Default = {
|
|||||||
|
|
||||||
class Toast extends BaseComponent {
|
class Toast extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element)
|
super(element, config)
|
||||||
|
|
||||||
this._config = this._getConfig(config)
|
|
||||||
this._timeout = null
|
this._timeout = null
|
||||||
this._hasMouseInteraction = false
|
this._hasMouseInteraction = false
|
||||||
this._hasKeyboardInteraction = false
|
this._hasKeyboardInteraction = false
|
||||||
@ -61,14 +59,14 @@ class Toast extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
static get DefaultType() {
|
|
||||||
return DefaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
static get Default() {
|
static get Default() {
|
||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -133,17 +131,6 @@ class Toast extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...Manipulator.getDataAttributes(this._element),
|
|
||||||
...(typeof config === 'object' && config ? config : {})
|
|
||||||
}
|
|
||||||
|
|
||||||
typeCheckConfig(NAME, config, this.constructor.DefaultType)
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
_maybeScheduleHide() {
|
_maybeScheduleHide() {
|
||||||
if (!this._config.autohide) {
|
if (!this._config.autohide) {
|
||||||
|
@ -12,8 +12,7 @@ import {
|
|||||||
getElement,
|
getElement,
|
||||||
getUID,
|
getUID,
|
||||||
isRTL,
|
isRTL,
|
||||||
noop,
|
noop
|
||||||
typeCheckConfig
|
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import { DefaultAllowlist } from './util/sanitizer'
|
import { DefaultAllowlist } from './util/sanitizer'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
@ -140,6 +139,10 @@ class Tooltip extends BaseComponent {
|
|||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
static get NAME() {
|
static get NAME() {
|
||||||
return NAME
|
return NAME
|
||||||
}
|
}
|
||||||
@ -148,10 +151,6 @@ class Tooltip extends BaseComponent {
|
|||||||
return Event
|
return Event
|
||||||
}
|
}
|
||||||
|
|
||||||
static get DefaultType() {
|
|
||||||
return DefaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
enable() {
|
enable() {
|
||||||
this._isEnabled = true
|
this._isEnabled = true
|
||||||
@ -571,11 +570,16 @@ class Tooltip extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
...this.constructor.Default,
|
|
||||||
...dataAttributes,
|
...dataAttributes,
|
||||||
...(typeof config === 'object' && config ? config : {})
|
...(typeof config === 'object' && config ? config : {})
|
||||||
}
|
}
|
||||||
|
config = this._mergeConfigObj(config)
|
||||||
|
config = this._configAfterMerge(config)
|
||||||
|
this._typeCheckConfig(config)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
_configAfterMerge(config) {
|
||||||
config.container = config.container === false ? document.body : getElement(config.container)
|
config.container = config.container === false ? document.body : getElement(config.container)
|
||||||
|
|
||||||
if (typeof config.delay === 'number') {
|
if (typeof config.delay === 'number') {
|
||||||
@ -595,7 +599,6 @@ class Tooltip extends BaseComponent {
|
|||||||
config.content = config.content.toString()
|
config.content = config.content.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
typeCheckConfig(NAME, config, this.constructor.DefaultType)
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index'
|
import { execute, executeAfterTransition, getElement, reflow } from './index'
|
||||||
|
import Config from './config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -37,13 +38,27 @@ const DefaultType = {
|
|||||||
* Class definition
|
* Class definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Backdrop {
|
class Backdrop extends Config {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
super()
|
||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
this._isAppended = false
|
this._isAppended = false
|
||||||
this._element = null
|
this._element = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
static get Default() {
|
||||||
|
return Default
|
||||||
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
show(callback) {
|
show(callback) {
|
||||||
if (!this._config.isVisible) {
|
if (!this._config.isVisible) {
|
||||||
@ -104,15 +119,9 @@ class Backdrop {
|
|||||||
return this._element
|
return this._element
|
||||||
}
|
}
|
||||||
|
|
||||||
_getConfig(config) {
|
_configAfterMerge(config) {
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
|
|
||||||
// use getElement() with the default "body" to get a fresh Element on each instantiation
|
// use getElement() with the default "body" to get a fresh Element on each instantiation
|
||||||
config.rootElement = getElement(config.rootElement)
|
config.rootElement = getElement(config.rootElement)
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
63
js/src/util/config.js
Normal file
63
js/src/util/config.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* Bootstrap (v5.1.3): util/config.js
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { isElement, toType } from './index'
|
||||||
|
import Manipulator from '../dom/manipulator'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
// Getters
|
||||||
|
static get Default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
throw new Error('You have to implement the static method "NAME", for each component!')
|
||||||
|
}
|
||||||
|
|
||||||
|
_getConfig(config) {
|
||||||
|
config = this._mergeConfigObj(config)
|
||||||
|
config = this._configAfterMerge(config)
|
||||||
|
this._typeCheckConfig(config)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
_configAfterMerge(config) {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
_mergeConfigObj(config, element) {
|
||||||
|
return {
|
||||||
|
...this.constructor.Default,
|
||||||
|
...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),
|
||||||
|
...(typeof config === 'object' ? config : {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_typeCheckConfig(config, configTypes = this.constructor.DefaultType) {
|
||||||
|
for (const property of Object.keys(configTypes)) {
|
||||||
|
const expectedTypes = configTypes[property]
|
||||||
|
const value = config[property]
|
||||||
|
const valueType = isElement(value) ? 'element' : toType(value)
|
||||||
|
|
||||||
|
if (!new RegExp(expectedTypes).test(valueType)) {
|
||||||
|
throw new TypeError(
|
||||||
|
`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Config
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import SelectorEngine from '../dom/selector-engine'
|
import SelectorEngine from '../dom/selector-engine'
|
||||||
import { typeCheckConfig } from './index'
|
import Config from './config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -37,13 +37,27 @@ const DefaultType = {
|
|||||||
* Class definition
|
* Class definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FocusTrap {
|
class FocusTrap extends Config {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
super()
|
||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
this._isActive = false
|
this._isActive = false
|
||||||
this._lastTabNavDirection = null
|
this._lastTabNavDirection = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
static get Default() {
|
||||||
|
return Default
|
||||||
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
activate() {
|
activate() {
|
||||||
const { trapElement, autofocus } = this._config
|
const { trapElement, autofocus } = this._config
|
||||||
@ -99,15 +113,6 @@ class FocusTrap {
|
|||||||
|
|
||||||
this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD
|
this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD
|
||||||
}
|
}
|
||||||
|
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FocusTrap
|
export default FocusTrap
|
||||||
|
@ -123,20 +123,6 @@ const getElement = object => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeCheckConfig = (componentName, config, configTypes) => {
|
|
||||||
for (const property of Object.keys(configTypes)) {
|
|
||||||
const expectedTypes = configTypes[property]
|
|
||||||
const value = config[property]
|
|
||||||
const valueType = value && isElement(value) ? 'element' : toType(value)
|
|
||||||
|
|
||||||
if (!new RegExp(expectedTypes).test(valueType)) {
|
|
||||||
throw new TypeError(
|
|
||||||
`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isVisible = element => {
|
const isVisible = element => {
|
||||||
if (!isElement(element) || element.getClientRects().length === 0) {
|
if (!isElement(element) || element.getClientRects().length === 0) {
|
||||||
return false
|
return false
|
||||||
@ -327,5 +313,5 @@ export {
|
|||||||
onDOMContentLoaded,
|
onDOMContentLoaded,
|
||||||
reflow,
|
reflow,
|
||||||
triggerTransitionEnd,
|
triggerTransitionEnd,
|
||||||
typeCheckConfig
|
toType
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Config from './config'
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import { execute, typeCheckConfig } from './index'
|
import { execute } from './index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -40,8 +41,9 @@ const DefaultType = {
|
|||||||
* Class definition
|
* Class definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Swipe {
|
class Swipe extends Config {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
|
super()
|
||||||
this._element = element
|
this._element = element
|
||||||
|
|
||||||
if (!element || !Swipe.isSupported()) {
|
if (!element || !Swipe.isSupported()) {
|
||||||
@ -54,6 +56,19 @@ class Swipe {
|
|||||||
this._initEvents()
|
this._initEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
static get Default() {
|
||||||
|
return Default
|
||||||
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
dispose() {
|
dispose() {
|
||||||
EventHandler.off(this._element, EVENT_KEY)
|
EventHandler.off(this._element, EVENT_KEY)
|
||||||
@ -118,15 +133,6 @@ class Swipe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getConfig(config) {
|
|
||||||
config = {
|
|
||||||
...Default,
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
_eventIsPointerPenTouch(event) {
|
_eventIsPointerPenTouch(event) {
|
||||||
return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
|
return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DefaultAllowlist, sanitizeHtml } from './sanitizer'
|
import { DefaultAllowlist, sanitizeHtml } from './sanitizer'
|
||||||
import { getElement, isElement, typeCheckConfig } from '../util/index'
|
import { getElement, isElement } from '../util/index'
|
||||||
import SelectorEngine from '../dom/selector-engine'
|
import SelectorEngine from '../dom/selector-engine'
|
||||||
|
import Config from './config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -44,20 +45,25 @@ const DefaultContentType = {
|
|||||||
* Class definition
|
* Class definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TemplateFactory {
|
class TemplateFactory extends Config {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
super()
|
||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
static get NAME() {
|
|
||||||
return NAME
|
|
||||||
}
|
|
||||||
|
|
||||||
static get Default() {
|
static get Default() {
|
||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get DefaultType() {
|
||||||
|
return DefaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
static get NAME() {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
getContent() {
|
getContent() {
|
||||||
return Object.values(this._config.content)
|
return Object.values(this._config.content)
|
||||||
@ -94,21 +100,14 @@ class TemplateFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_getConfig(config) {
|
_typeCheckConfig(config) {
|
||||||
config = {
|
super._typeCheckConfig(config)
|
||||||
...Default,
|
|
||||||
...(typeof config === 'object' ? config : {})
|
|
||||||
}
|
|
||||||
|
|
||||||
typeCheckConfig(NAME, config, DefaultType)
|
|
||||||
this._checkContent(config.content)
|
this._checkContent(config.content)
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkContent(arg) {
|
_checkContent(arg) {
|
||||||
for (const [selector, content] of Object.entries(arg)) {
|
for (const [selector, content] of Object.entries(arg)) {
|
||||||
typeCheckConfig(NAME, { selector, entry: content }, DefaultContentType)
|
super._typeCheckConfig({ selector, entry: content }, DefaultContentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
78
js/tests/unit/util/config.spec.js
Normal file
78
js/tests/unit/util/config.spec.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import Config from '../../../src/util/config'
|
||||||
|
|
||||||
|
class DummyConfigClass extends Config {
|
||||||
|
static get NAME() {
|
||||||
|
return 'dummy'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Config', () => {
|
||||||
|
const name = 'dummy'
|
||||||
|
describe('NAME', () => {
|
||||||
|
it('should return plugin NAME', () => {
|
||||||
|
expect(DummyConfigClass.NAME).toEqual(name)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('DefaultType', () => {
|
||||||
|
it('should return plugin default type', () => {
|
||||||
|
expect(DummyConfigClass.DefaultType).toEqual(jasmine.any(Object))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Default', () => {
|
||||||
|
it('should return plugin defaults', () => {
|
||||||
|
expect(DummyConfigClass.Default).toEqual(jasmine.any(Object))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('typeCheckConfig', () => {
|
||||||
|
it('should check type of the config object', () => {
|
||||||
|
spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({
|
||||||
|
toggle: 'boolean',
|
||||||
|
parent: '(string|element)'
|
||||||
|
})
|
||||||
|
const config = {
|
||||||
|
toggle: true,
|
||||||
|
parent: 777
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = new DummyConfigClass()
|
||||||
|
expect(() => {
|
||||||
|
obj._typeCheckConfig(config)
|
||||||
|
}).toThrowError(TypeError, obj.constructor.NAME.toUpperCase() + ': Option "parent" provided type "number" but expected type "(string|element)".')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return null stringified when null is passed', () => {
|
||||||
|
spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({
|
||||||
|
toggle: 'boolean',
|
||||||
|
parent: '(null|element)'
|
||||||
|
})
|
||||||
|
|
||||||
|
const obj = new DummyConfigClass()
|
||||||
|
const config = {
|
||||||
|
toggle: true,
|
||||||
|
parent: null
|
||||||
|
}
|
||||||
|
|
||||||
|
obj._typeCheckConfig(config)
|
||||||
|
expect().nothing()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return undefined stringified when undefined is passed', () => {
|
||||||
|
spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({
|
||||||
|
toggle: 'boolean',
|
||||||
|
parent: '(undefined|element)'
|
||||||
|
})
|
||||||
|
|
||||||
|
const obj = new DummyConfigClass()
|
||||||
|
const config = {
|
||||||
|
toggle: true,
|
||||||
|
parent: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
obj._typeCheckConfig(config)
|
||||||
|
expect().nothing()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -223,53 +223,6 @@ describe('Util', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('typeCheckConfig', () => {
|
|
||||||
const namePlugin = 'collapse'
|
|
||||||
|
|
||||||
it('should check type of the config object', () => {
|
|
||||||
const defaultType = {
|
|
||||||
toggle: 'boolean',
|
|
||||||
parent: '(string|element)'
|
|
||||||
}
|
|
||||||
const config = {
|
|
||||||
toggle: true,
|
|
||||||
parent: 777
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
Util.typeCheckConfig(namePlugin, config, defaultType)
|
|
||||||
}).toThrowError(TypeError, 'COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return null stringified when null is passed', () => {
|
|
||||||
const defaultType = {
|
|
||||||
toggle: 'boolean',
|
|
||||||
parent: '(null|element)'
|
|
||||||
}
|
|
||||||
const config = {
|
|
||||||
toggle: true,
|
|
||||||
parent: null
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.typeCheckConfig(namePlugin, config, defaultType)
|
|
||||||
expect().nothing()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return undefined stringified when undefined is passed', () => {
|
|
||||||
const defaultType = {
|
|
||||||
toggle: 'boolean',
|
|
||||||
parent: '(undefined|element)'
|
|
||||||
}
|
|
||||||
const config = {
|
|
||||||
toggle: true,
|
|
||||||
parent: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.typeCheckConfig(namePlugin, config, defaultType)
|
|
||||||
expect().nothing()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('isVisible', () => {
|
describe('isVisible', () => {
|
||||||
it('should return false if the element is not defined', () => {
|
it('should return false if the element is not defined', () => {
|
||||||
expect(Util.isVisible(null)).toBeFalse()
|
expect(Util.isVisible(null)).toBeFalse()
|
||||||
|
Loading…
Reference in New Issue
Block a user