Merging upstream version 5.3.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a87fc4fcc7
commit
e92720b6a7
605 changed files with 15320 additions and 9495 deletions
|
@ -1,19 +1,19 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): index.esm.js
|
||||
* Bootstrap index.esm.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
export { default as Alert } from './src/alert'
|
||||
export { default as Button } from './src/button'
|
||||
export { default as Carousel } from './src/carousel'
|
||||
export { default as Collapse } from './src/collapse'
|
||||
export { default as Dropdown } from './src/dropdown'
|
||||
export { default as Modal } from './src/modal'
|
||||
export { default as Offcanvas } from './src/offcanvas'
|
||||
export { default as Popover } from './src/popover'
|
||||
export { default as ScrollSpy } from './src/scrollspy'
|
||||
export { default as Tab } from './src/tab'
|
||||
export { default as Toast } from './src/toast'
|
||||
export { default as Tooltip } from './src/tooltip'
|
||||
export { default as Alert } from './src/alert.js'
|
||||
export { default as Button } from './src/button.js'
|
||||
export { default as Carousel } from './src/carousel.js'
|
||||
export { default as Collapse } from './src/collapse.js'
|
||||
export { default as Dropdown } from './src/dropdown.js'
|
||||
export { default as Modal } from './src/modal.js'
|
||||
export { default as Offcanvas } from './src/offcanvas.js'
|
||||
export { default as Popover } from './src/popover.js'
|
||||
export { default as ScrollSpy } from './src/scrollspy.js'
|
||||
export { default as Tab } from './src/tab.js'
|
||||
export { default as Toast } from './src/toast.js'
|
||||
export { default as Tooltip } from './src/tooltip.js'
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): index.umd.js
|
||||
* Bootstrap index.umd.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Alert from './src/alert'
|
||||
import Button from './src/button'
|
||||
import Carousel from './src/carousel'
|
||||
import Collapse from './src/collapse'
|
||||
import Dropdown from './src/dropdown'
|
||||
import Modal from './src/modal'
|
||||
import Offcanvas from './src/offcanvas'
|
||||
import Popover from './src/popover'
|
||||
import ScrollSpy from './src/scrollspy'
|
||||
import Tab from './src/tab'
|
||||
import Toast from './src/toast'
|
||||
import Tooltip from './src/tooltip'
|
||||
import Alert from './src/alert.js'
|
||||
import Button from './src/button.js'
|
||||
import Carousel from './src/carousel.js'
|
||||
import Collapse from './src/collapse.js'
|
||||
import Dropdown from './src/dropdown.js'
|
||||
import Modal from './src/modal.js'
|
||||
import Offcanvas from './src/offcanvas.js'
|
||||
import Popover from './src/popover.js'
|
||||
import ScrollSpy from './src/scrollspy.js'
|
||||
import Tab from './src/tab.js'
|
||||
import Toast from './src/toast.js'
|
||||
import Tooltip from './src/tooltip.js'
|
||||
|
||||
export default {
|
||||
Alert,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): alert.js
|
||||
* Bootstrap alert.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import BaseComponent from './base-component'
|
||||
import { enableDismissTrigger } from './util/component-functions'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import { enableDismissTrigger } from './util/component-functions.js'
|
||||
import { defineJQueryPlugin } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): base-component.js
|
||||
* Bootstrap base-component.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Data from './dom/data'
|
||||
import { executeAfterTransition, getElement } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Config from './util/config'
|
||||
import Data from './dom/data.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import Config from './util/config.js'
|
||||
import { executeAfterTransition, getElement } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const VERSION = '5.2.3'
|
||||
const VERSION = '5.3.0'
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): button.js
|
||||
* Bootstrap button.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import BaseComponent from './base-component'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import { defineJQueryPlugin } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): carousel.js
|
||||
* Bootstrap carousel.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import Manipulator from './dom/manipulator.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import {
|
||||
defineJQueryPlugin,
|
||||
getElementFromSelector,
|
||||
getNextActiveElement,
|
||||
isRTL,
|
||||
isVisible,
|
||||
reflow,
|
||||
triggerTransitionEnd
|
||||
} from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Manipulator from './dom/manipulator'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import Swipe from './util/swipe'
|
||||
import BaseComponent from './base-component'
|
||||
} from './util/index.js'
|
||||
import Swipe from './util/swipe.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -330,7 +329,7 @@ class Carousel extends BaseComponent {
|
|||
|
||||
if (!activeElement || !nextElement) {
|
||||
// Some weirdness is happening, so we bail
|
||||
// todo: change tests that use empty divs to avoid this check
|
||||
// TODO: change tests that use empty divs to avoid this check
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -431,7 +430,7 @@ class Carousel extends BaseComponent {
|
|||
*/
|
||||
|
||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {
|
||||
const target = getElementFromSelector(this)
|
||||
const target = SelectorEngine.getElementFromSelector(this)
|
||||
|
||||
if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
|
||||
return
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): collapse.js
|
||||
* Bootstrap collapse.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import {
|
||||
defineJQueryPlugin,
|
||||
getElement,
|
||||
getElementFromSelector,
|
||||
getSelectorFromElement,
|
||||
reflow
|
||||
} from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import BaseComponent from './base-component'
|
||||
} from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -68,7 +66,7 @@ class Collapse extends BaseComponent {
|
|||
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
|
||||
|
||||
for (const elem of toggleList) {
|
||||
const selector = getSelectorFromElement(elem)
|
||||
const selector = SelectorEngine.getSelectorFromElement(elem)
|
||||
const filterElement = SelectorEngine.find(selector)
|
||||
.filter(foundElement => foundElement === this._element)
|
||||
|
||||
|
@ -185,7 +183,7 @@ class Collapse extends BaseComponent {
|
|||
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
|
||||
|
||||
for (const trigger of this._triggerArray) {
|
||||
const element = getElementFromSelector(trigger)
|
||||
const element = SelectorEngine.getElementFromSelector(trigger)
|
||||
|
||||
if (element && !this._isShown(element)) {
|
||||
this._addAriaAndCollapsedClass([trigger], false)
|
||||
|
@ -229,7 +227,7 @@ class Collapse extends BaseComponent {
|
|||
const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE)
|
||||
|
||||
for (const element of children) {
|
||||
const selected = getElementFromSelector(element)
|
||||
const selected = SelectorEngine.getElementFromSelector(element)
|
||||
|
||||
if (selected) {
|
||||
this._addAriaAndCollapsedClass([element], this._isShown(selected))
|
||||
|
@ -285,10 +283,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
|
|||
event.preventDefault()
|
||||
}
|
||||
|
||||
const selector = getSelectorFromElement(this)
|
||||
const selectorElements = SelectorEngine.find(selector)
|
||||
|
||||
for (const element of selectorElements) {
|
||||
for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {
|
||||
Collapse.getOrCreateInstance(element, { toggle: false }).toggle()
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): dom/data.js
|
||||
* Bootstrap dom/data.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): dom/event-handler.js
|
||||
* Bootstrap dom/event-handler.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { getjQuery } from '../util/index'
|
||||
import { getjQuery } from '../util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -128,7 +128,7 @@ function findHandler(events, callable, delegationSelector = null) {
|
|||
|
||||
function normalizeParameters(originalTypeEvent, handler, delegationFunction) {
|
||||
const isDelegated = typeof handler === 'string'
|
||||
// todo: tooltip passes `false` instead of selector, so we need to check
|
||||
// TODO: tooltip passes `false` instead of selector, so we need to check
|
||||
const callable = isDelegated ? delegationFunction : (handler || delegationFunction)
|
||||
let typeEvent = getTypeEvent(originalTypeEvent)
|
||||
|
||||
|
@ -198,9 +198,8 @@ function removeHandler(element, events, typeEvent, handler, delegationSelector)
|
|||
function removeNamespacedHandlers(element, events, typeEvent, namespace) {
|
||||
const storeElementEvent = events[typeEvent] || {}
|
||||
|
||||
for (const handlerKey of Object.keys(storeElementEvent)) {
|
||||
for (const [handlerKey, event] of Object.entries(storeElementEvent)) {
|
||||
if (handlerKey.includes(namespace)) {
|
||||
const event = storeElementEvent[handlerKey]
|
||||
removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)
|
||||
}
|
||||
}
|
||||
|
@ -248,11 +247,10 @@ const EventHandler = {
|
|||
}
|
||||
}
|
||||
|
||||
for (const keyHandlers of Object.keys(storeElementEvent)) {
|
||||
for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {
|
||||
const handlerKey = keyHandlers.replace(stripUidRegex, '')
|
||||
|
||||
if (!inNamespace || originalTypeEvent.includes(handlerKey)) {
|
||||
const event = storeElementEvent[keyHandlers]
|
||||
removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)
|
||||
}
|
||||
}
|
||||
|
@ -281,8 +279,7 @@ const EventHandler = {
|
|||
defaultPrevented = jQueryEvent.isDefaultPrevented()
|
||||
}
|
||||
|
||||
let evt = new Event(event, { bubbles, cancelable: true })
|
||||
evt = hydrateObj(evt, args)
|
||||
const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
|
||||
|
||||
if (defaultPrevented) {
|
||||
evt.preventDefault()
|
||||
|
@ -300,8 +297,8 @@ const EventHandler = {
|
|||
}
|
||||
}
|
||||
|
||||
function hydrateObj(obj, meta) {
|
||||
for (const [key, value] of Object.entries(meta || {})) {
|
||||
function hydrateObj(obj, meta = {}) {
|
||||
for (const [key, value] of Object.entries(meta)) {
|
||||
try {
|
||||
obj[key] = value
|
||||
} catch {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): dom/manipulator.js
|
||||
* Bootstrap dom/manipulator.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
@ -1,15 +1,36 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): dom/selector-engine.js
|
||||
* Bootstrap dom/selector-engine.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { isDisabled, isVisible } from '../util/index'
|
||||
import { isDisabled, isVisible, parseSelector } from '../util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
const getSelector = element => {
|
||||
let selector = element.getAttribute('data-bs-target')
|
||||
|
||||
if (!selector || selector === '#') {
|
||||
let hrefAttribute = element.getAttribute('href')
|
||||
|
||||
// The only valid content that could double as a selector are IDs or classes,
|
||||
// so everything starting with `#` or `.`. If a "real" URL is used as the selector,
|
||||
// `document.querySelector` will rightfully complain it is invalid.
|
||||
// See https://github.com/twbs/bootstrap/issues/32273
|
||||
if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Just in case some CMS puts out a full URL with the anchor appended
|
||||
if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
|
||||
hrefAttribute = `#${hrefAttribute.split('#')[1]}`
|
||||
}
|
||||
|
||||
selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
|
||||
}
|
||||
|
||||
return parseSelector(selector)
|
||||
}
|
||||
|
||||
const SelectorEngine = {
|
||||
find(selector, element = document.documentElement) {
|
||||
|
@ -77,6 +98,28 @@ const SelectorEngine = {
|
|||
].map(selector => `${selector}:not([tabindex^="-"])`).join(',')
|
||||
|
||||
return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))
|
||||
},
|
||||
|
||||
getSelectorFromElement(element) {
|
||||
const selector = getSelector(element)
|
||||
|
||||
if (selector) {
|
||||
return SelectorEngine.findOne(selector) ? selector : null
|
||||
}
|
||||
|
||||
return null
|
||||
},
|
||||
|
||||
getElementFromSelector(element) {
|
||||
const selector = getSelector(element)
|
||||
|
||||
return selector ? SelectorEngine.findOne(selector) : null
|
||||
},
|
||||
|
||||
getMultipleElementsFromSelector(element) {
|
||||
const selector = getSelector(element)
|
||||
|
||||
return selector ? SelectorEngine.find(selector) : []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): dropdown.js
|
||||
* Bootstrap dropdown.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import * as Popper from '@popperjs/core'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import Manipulator from './dom/manipulator.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import {
|
||||
defineJQueryPlugin,
|
||||
execute,
|
||||
getElement,
|
||||
getNextActiveElement,
|
||||
isDisabled,
|
||||
|
@ -15,11 +20,7 @@ import {
|
|||
isRTL,
|
||||
isVisible,
|
||||
noop
|
||||
} from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Manipulator from './dom/manipulator'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import BaseComponent from './base-component'
|
||||
} from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -95,7 +96,7 @@ class Dropdown extends BaseComponent {
|
|||
|
||||
this._popper = null
|
||||
this._parent = this._element.parentNode // dropdown wrapper
|
||||
// todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
|
||||
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
|
||||
this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
|
||||
SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||
|
||||
SelectorEngine.findOne(SELECTOR_MENU, this._parent)
|
||||
|
@ -310,7 +311,7 @@ class Dropdown extends BaseComponent {
|
|||
|
||||
// Disable Popper if we have a static display or Dropdown is in Navbar
|
||||
if (this._inNavbar || this._config.display === 'static') {
|
||||
Manipulator.setDataAttribute(this._menu, 'popper', 'static') // todo:v6 remove
|
||||
Manipulator.setDataAttribute(this._menu, 'popper', 'static') // TODO: v6 remove
|
||||
defaultBsPopperConfig.modifiers = [{
|
||||
name: 'applyStyles',
|
||||
enabled: false
|
||||
|
@ -319,7 +320,7 @@ class Dropdown extends BaseComponent {
|
|||
|
||||
return {
|
||||
...defaultBsPopperConfig,
|
||||
...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
|
||||
...execute(this._config.popperConfig, [defaultBsPopperConfig])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +409,7 @@ class Dropdown extends BaseComponent {
|
|||
|
||||
event.preventDefault()
|
||||
|
||||
// todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
|
||||
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
|
||||
const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?
|
||||
this :
|
||||
(SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] ||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): modal.js
|
||||
* Bootstrap modal.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin, getElementFromSelector, isRTL, isVisible, reflow } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import ScrollBarHelper from './util/scrollbar'
|
||||
import BaseComponent from './base-component'
|
||||
import Backdrop from './util/backdrop'
|
||||
import FocusTrap from './util/focustrap'
|
||||
import { enableDismissTrigger } from './util/component-functions'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import Backdrop from './util/backdrop.js'
|
||||
import { enableDismissTrigger } from './util/component-functions.js'
|
||||
import FocusTrap from './util/focustrap.js'
|
||||
import { defineJQueryPlugin, isRTL, isVisible, reflow } from './util/index.js'
|
||||
import ScrollBarHelper from './util/scrollbar.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -139,12 +139,12 @@ class Modal extends BaseComponent {
|
|||
}
|
||||
|
||||
dispose() {
|
||||
for (const htmlElement of [window, this._dialog]) {
|
||||
EventHandler.off(htmlElement, EVENT_KEY)
|
||||
}
|
||||
EventHandler.off(window, EVENT_KEY)
|
||||
EventHandler.off(this._dialog, EVENT_KEY)
|
||||
|
||||
this._backdrop.dispose()
|
||||
this._focustrap.deactivate()
|
||||
|
||||
super.dispose()
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,6 @@ class Modal extends BaseComponent {
|
|||
}
|
||||
|
||||
if (this._config.keyboard) {
|
||||
event.preventDefault()
|
||||
this.hide()
|
||||
return
|
||||
}
|
||||
|
@ -336,7 +335,7 @@ class Modal extends BaseComponent {
|
|||
*/
|
||||
|
||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||
const target = getElementFromSelector(this)
|
||||
const target = SelectorEngine.getElementFromSelector(this)
|
||||
|
||||
if (['A', 'AREA'].includes(this.tagName)) {
|
||||
event.preventDefault()
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): offcanvas.js
|
||||
* Bootstrap offcanvas.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import Backdrop from './util/backdrop.js'
|
||||
import { enableDismissTrigger } from './util/component-functions.js'
|
||||
import FocusTrap from './util/focustrap.js'
|
||||
import {
|
||||
defineJQueryPlugin,
|
||||
getElementFromSelector,
|
||||
isDisabled,
|
||||
isVisible
|
||||
} from './util/index'
|
||||
import ScrollBarHelper from './util/scrollbar'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import BaseComponent from './base-component'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import Backdrop from './util/backdrop'
|
||||
import FocusTrap from './util/focustrap'
|
||||
import { enableDismissTrigger } from './util/component-functions'
|
||||
} from './util/index.js'
|
||||
import ScrollBarHelper from './util/scrollbar.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -199,12 +198,12 @@ class Offcanvas extends BaseComponent {
|
|||
return
|
||||
}
|
||||
|
||||
if (!this._config.keyboard) {
|
||||
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)
|
||||
if (this._config.keyboard) {
|
||||
this.hide()
|
||||
return
|
||||
}
|
||||
|
||||
this.hide()
|
||||
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -231,7 +230,7 @@ class Offcanvas extends BaseComponent {
|
|||
*/
|
||||
|
||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||
const target = getElementFromSelector(this)
|
||||
const target = SelectorEngine.getElementFromSelector(this)
|
||||
|
||||
if (['A', 'AREA'].includes(this.tagName)) {
|
||||
event.preventDefault()
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): popover.js
|
||||
* Bootstrap popover.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin } from './util/index'
|
||||
import Tooltip from './tooltip'
|
||||
import Tooltip from './tooltip.js'
|
||||
import { defineJQueryPlugin } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): scrollspy.js
|
||||
* Bootstrap scrollspy.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin, getElement, isDisabled, isVisible } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import BaseComponent from './base-component'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import { defineJQueryPlugin, getElement, isDisabled, isVisible } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -208,11 +208,11 @@ class ScrollSpy extends BaseComponent {
|
|||
continue
|
||||
}
|
||||
|
||||
const observableSection = SelectorEngine.findOne(anchor.hash, this._element)
|
||||
const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element)
|
||||
|
||||
// ensure that the observableSection exists & is visible
|
||||
if (isVisible(observableSection)) {
|
||||
this._targetLinks.set(anchor.hash, anchor)
|
||||
this._targetLinks.set(decodeURI(anchor.hash), anchor)
|
||||
this._observableSections.set(anchor.hash, observableSection)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): tab.js
|
||||
* Bootstrap tab.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin, getElementFromSelector, getNextActiveElement, isDisabled } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import BaseComponent from './base-component'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import SelectorEngine from './dom/selector-engine.js'
|
||||
import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -43,7 +43,7 @@ const NOT_SELECTOR_DROPDOWN_TOGGLE = ':not(.dropdown-toggle)'
|
|||
const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]'
|
||||
const SELECTOR_OUTER = '.nav-item, .list-group-item'
|
||||
const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`
|
||||
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' // todo:v6: could be only `tab`
|
||||
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' // TODO: could only be `tab` in v6
|
||||
const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`
|
||||
|
||||
const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`
|
||||
|
@ -59,7 +59,7 @@ class Tab extends BaseComponent {
|
|||
|
||||
if (!this._parent) {
|
||||
return
|
||||
// todo: should Throw exception on v6
|
||||
// TODO: should throw exception in v6
|
||||
// throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ class Tab extends BaseComponent {
|
|||
|
||||
element.classList.add(CLASS_NAME_ACTIVE)
|
||||
|
||||
this._activate(getElementFromSelector(element)) // Search and activate/show the proper section
|
||||
this._activate(SelectorEngine.getElementFromSelector(element)) // Search and activate/show the proper section
|
||||
|
||||
const complete = () => {
|
||||
if (element.getAttribute('role') !== 'tab') {
|
||||
|
@ -133,7 +133,7 @@ class Tab extends BaseComponent {
|
|||
element.classList.remove(CLASS_NAME_ACTIVE)
|
||||
element.blur()
|
||||
|
||||
this._deactivate(getElementFromSelector(element)) // Search and deactivate the shown section too
|
||||
this._deactivate(SelectorEngine.getElementFromSelector(element)) // Search and deactivate the shown section too
|
||||
|
||||
const complete = () => {
|
||||
if (element.getAttribute('role') !== 'tab') {
|
||||
|
@ -203,7 +203,7 @@ class Tab extends BaseComponent {
|
|||
}
|
||||
|
||||
_setInitialAttributesOnTargetPanel(child) {
|
||||
const target = getElementFromSelector(child)
|
||||
const target = SelectorEngine.getElementFromSelector(child)
|
||||
|
||||
if (!target) {
|
||||
return
|
||||
|
@ -212,7 +212,7 @@ class Tab extends BaseComponent {
|
|||
this._setAttributeIfNotExists(target, 'role', 'tabpanel')
|
||||
|
||||
if (child.id) {
|
||||
this._setAttributeIfNotExists(target, 'aria-labelledby', `#${child.id}`)
|
||||
this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): toast.js
|
||||
* Bootstrap toast.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { defineJQueryPlugin, reflow } from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import BaseComponent from './base-component'
|
||||
import { enableDismissTrigger } from './util/component-functions'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import { enableDismissTrigger } from './util/component-functions.js'
|
||||
import { defineJQueryPlugin, reflow } from './util/index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): tooltip.js
|
||||
* Bootstrap tooltip.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import * as Popper from '@popperjs/core'
|
||||
import { defineJQueryPlugin, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index'
|
||||
import { DefaultAllowlist } from './util/sanitizer'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Manipulator from './dom/manipulator'
|
||||
import BaseComponent from './base-component'
|
||||
import TemplateFactory from './util/template-factory'
|
||||
import BaseComponent from './base-component.js'
|
||||
import EventHandler from './dom/event-handler.js'
|
||||
import Manipulator from './dom/manipulator.js'
|
||||
import { defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index.js'
|
||||
import { DefaultAllowlist } from './util/sanitizer.js'
|
||||
import TemplateFactory from './util/template-factory.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -62,7 +62,7 @@ const Default = {
|
|||
delay: 0,
|
||||
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
|
||||
html: false,
|
||||
offset: [0, 0],
|
||||
offset: [0, 6],
|
||||
placement: 'top',
|
||||
popperConfig: null,
|
||||
sanitize: true,
|
||||
|
@ -197,7 +197,7 @@ class Tooltip extends BaseComponent {
|
|||
return
|
||||
}
|
||||
|
||||
// todo v6 remove this OR make it optional
|
||||
// TODO: v6 remove this or make it optional
|
||||
this._disposePopper()
|
||||
|
||||
const tip = this._getTipElement()
|
||||
|
@ -302,13 +302,13 @@ class Tooltip extends BaseComponent {
|
|||
_createTipElement(content) {
|
||||
const tip = this._getTemplateFactory(content).toHtml()
|
||||
|
||||
// todo: remove this check on v6
|
||||
// TODO: remove this check in v6
|
||||
if (!tip) {
|
||||
return null
|
||||
}
|
||||
|
||||
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)
|
||||
// todo: on v6 the following can be achieved with CSS only
|
||||
// TODO: v6 the following can be achieved with CSS only
|
||||
tip.classList.add(`bs-${this.constructor.NAME}-auto`)
|
||||
|
||||
const tipId = getUID(this.constructor.NAME).toString()
|
||||
|
@ -370,9 +370,7 @@ class Tooltip extends BaseComponent {
|
|||
}
|
||||
|
||||
_createPopper(tip) {
|
||||
const placement = typeof this._config.placement === 'function' ?
|
||||
this._config.placement.call(this, tip, this._element) :
|
||||
this._config.placement
|
||||
const placement = execute(this._config.placement, [this, tip, this._element])
|
||||
const attachment = AttachmentMap[placement.toUpperCase()]
|
||||
return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
|
||||
}
|
||||
|
@ -392,7 +390,7 @@ class Tooltip extends BaseComponent {
|
|||
}
|
||||
|
||||
_resolvePossibleFunction(arg) {
|
||||
return typeof arg === 'function' ? arg.call(this._element) : arg
|
||||
return execute(arg, [this._element])
|
||||
}
|
||||
|
||||
_getPopperConfig(attachment) {
|
||||
|
@ -438,7 +436,7 @@ class Tooltip extends BaseComponent {
|
|||
|
||||
return {
|
||||
...defaultBsPopperConfig,
|
||||
...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
|
||||
...execute(this._config.popperConfig, [defaultBsPopperConfig])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,9 +577,9 @@ class Tooltip extends BaseComponent {
|
|||
_getDelegateConfig() {
|
||||
const config = {}
|
||||
|
||||
for (const key in this._config) {
|
||||
if (this.constructor.Default[key] !== this._config[key]) {
|
||||
config[key] = this._config[key]
|
||||
for (const [key, value] of Object.entries(this._config)) {
|
||||
if (this.constructor.Default[key] !== value) {
|
||||
config[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/backdrop.js
|
||||
* Bootstrap util/backdrop.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import EventHandler from '../dom/event-handler'
|
||||
import { execute, executeAfterTransition, getElement, reflow } from './index'
|
||||
import Config from './config'
|
||||
import EventHandler from '../dom/event-handler.js'
|
||||
import Config from './config.js'
|
||||
import { execute, executeAfterTransition, getElement, reflow } from './index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/component-functions.js
|
||||
* Bootstrap util/component-functions.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import EventHandler from '../dom/event-handler'
|
||||
import { getElementFromSelector, isDisabled } from './index'
|
||||
import EventHandler from '../dom/event-handler.js'
|
||||
import SelectorEngine from '../dom/selector-engine.js'
|
||||
import { isDisabled } from './index.js'
|
||||
|
||||
const enableDismissTrigger = (component, method = 'hide') => {
|
||||
const clickEvent = `click.dismiss${component.EVENT_KEY}`
|
||||
|
@ -21,7 +22,7 @@ const enableDismissTrigger = (component, method = 'hide') => {
|
|||
return
|
||||
}
|
||||
|
||||
const target = getElementFromSelector(this) || this.closest(`.${name}`)
|
||||
const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)
|
||||
const instance = component.getOrCreateInstance(target)
|
||||
|
||||
// Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/config.js
|
||||
* Bootstrap util/config.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { isElement, toType } from './index'
|
||||
import Manipulator from '../dom/manipulator'
|
||||
import Manipulator from '../dom/manipulator.js'
|
||||
import { isElement, toType } from './index.js'
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
|
@ -49,8 +49,7 @@ class Config {
|
|||
}
|
||||
|
||||
_typeCheckConfig(config, configTypes = this.constructor.DefaultType) {
|
||||
for (const property of Object.keys(configTypes)) {
|
||||
const expectedTypes = configTypes[property]
|
||||
for (const [property, expectedTypes] of Object.entries(configTypes)) {
|
||||
const value = config[property]
|
||||
const valueType = isElement(value) ? 'element' : toType(value)
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/focustrap.js
|
||||
* Bootstrap util/focustrap.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import EventHandler from '../dom/event-handler'
|
||||
import SelectorEngine from '../dom/selector-engine'
|
||||
import Config from './config'
|
||||
import EventHandler from '../dom/event-handler.js'
|
||||
import SelectorEngine from '../dom/selector-engine.js'
|
||||
import Config from './config.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/index.js
|
||||
* Bootstrap util/index.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -9,6 +9,20 @@ const MAX_UID = 1_000_000
|
|||
const MILLISECONDS_MULTIPLIER = 1000
|
||||
const TRANSITION_END = 'transitionend'
|
||||
|
||||
/**
|
||||
* Properly escape IDs selectors to handle weird IDs
|
||||
* @param {string} selector
|
||||
* @returns {string}
|
||||
*/
|
||||
const parseSelector = selector => {
|
||||
if (selector && window.CSS && window.CSS.escape) {
|
||||
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
|
||||
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`)
|
||||
}
|
||||
|
||||
return selector
|
||||
}
|
||||
|
||||
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
|
||||
const toType = object => {
|
||||
if (object === null || object === undefined) {
|
||||
|
@ -30,47 +44,6 @@ const getUID = prefix => {
|
|||
return prefix
|
||||
}
|
||||
|
||||
const getSelector = element => {
|
||||
let selector = element.getAttribute('data-bs-target')
|
||||
|
||||
if (!selector || selector === '#') {
|
||||
let hrefAttribute = element.getAttribute('href')
|
||||
|
||||
// The only valid content that could double as a selector are IDs or classes,
|
||||
// so everything starting with `#` or `.`. If a "real" URL is used as the selector,
|
||||
// `document.querySelector` will rightfully complain it is invalid.
|
||||
// See https://github.com/twbs/bootstrap/issues/32273
|
||||
if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Just in case some CMS puts out a full URL with the anchor appended
|
||||
if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
|
||||
hrefAttribute = `#${hrefAttribute.split('#')[1]}`
|
||||
}
|
||||
|
||||
selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
|
||||
}
|
||||
|
||||
return selector
|
||||
}
|
||||
|
||||
const getSelectorFromElement = element => {
|
||||
const selector = getSelector(element)
|
||||
|
||||
if (selector) {
|
||||
return document.querySelector(selector) ? selector : null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const getElementFromSelector = element => {
|
||||
const selector = getSelector(element)
|
||||
|
||||
return selector ? document.querySelector(selector) : null
|
||||
}
|
||||
|
||||
const getTransitionDurationFromElement = element => {
|
||||
if (!element) {
|
||||
return 0
|
||||
|
@ -117,7 +90,7 @@ const getElement = object => {
|
|||
}
|
||||
|
||||
if (typeof object === 'string' && object.length > 0) {
|
||||
return document.querySelector(object)
|
||||
return document.querySelector(parseSelector(object))
|
||||
}
|
||||
|
||||
return null
|
||||
|
@ -249,10 +222,8 @@ const defineJQueryPlugin = plugin => {
|
|||
})
|
||||
}
|
||||
|
||||
const execute = callback => {
|
||||
if (typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
|
||||
return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue
|
||||
}
|
||||
|
||||
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
|
||||
|
@ -318,10 +289,8 @@ export {
|
|||
executeAfterTransition,
|
||||
findShadowRoot,
|
||||
getElement,
|
||||
getElementFromSelector,
|
||||
getjQuery,
|
||||
getNextActiveElement,
|
||||
getSelectorFromElement,
|
||||
getTransitionDurationFromElement,
|
||||
getUID,
|
||||
isDisabled,
|
||||
|
@ -330,6 +299,7 @@ export {
|
|||
isVisible,
|
||||
noop,
|
||||
onDOMContentLoaded,
|
||||
parseSelector,
|
||||
reflow,
|
||||
triggerTransitionEnd,
|
||||
toType
|
||||
|
|
|
@ -1,53 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/sanitizer.js
|
||||
* Bootstrap util/sanitizer.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
const uriAttributes = new Set([
|
||||
'background',
|
||||
'cite',
|
||||
'href',
|
||||
'itemtype',
|
||||
'longdesc',
|
||||
'poster',
|
||||
'src',
|
||||
'xlink:href'
|
||||
])
|
||||
|
||||
// js-docs-start allow-list
|
||||
const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
|
||||
|
||||
/**
|
||||
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
||||
*
|
||||
* Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
||||
*/
|
||||
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i
|
||||
|
||||
/**
|
||||
* A pattern that matches safe data URLs. Only matches image, video and audio types.
|
||||
*
|
||||
* Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
||||
*/
|
||||
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i
|
||||
|
||||
const allowedAttribute = (attribute, allowedAttributeList) => {
|
||||
const attributeName = attribute.nodeName.toLowerCase()
|
||||
|
||||
if (allowedAttributeList.includes(attributeName)) {
|
||||
if (uriAttributes.has(attributeName)) {
|
||||
return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if a regular expression validates the attribute.
|
||||
return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)
|
||||
.some(regex => regex.test(attributeName))
|
||||
}
|
||||
|
||||
export const DefaultAllowlist = {
|
||||
// Global attributes allowed on any supplied element below.
|
||||
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
|
||||
|
@ -81,6 +41,43 @@ export const DefaultAllowlist = {
|
|||
u: [],
|
||||
ul: []
|
||||
}
|
||||
// js-docs-end allow-list
|
||||
|
||||
const uriAttributes = new Set([
|
||||
'background',
|
||||
'cite',
|
||||
'href',
|
||||
'itemtype',
|
||||
'longdesc',
|
||||
'poster',
|
||||
'src',
|
||||
'xlink:href'
|
||||
])
|
||||
|
||||
/**
|
||||
* A pattern that recognizes URLs that are safe wrt. XSS in URL navigation
|
||||
* contexts.
|
||||
*
|
||||
* Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38
|
||||
*/
|
||||
// eslint-disable-next-line unicorn/better-regex
|
||||
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i
|
||||
|
||||
const allowedAttribute = (attribute, allowedAttributeList) => {
|
||||
const attributeName = attribute.nodeName.toLowerCase()
|
||||
|
||||
if (allowedAttributeList.includes(attributeName)) {
|
||||
if (uriAttributes.has(attributeName)) {
|
||||
return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if a regular expression validates the attribute.
|
||||
return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)
|
||||
.some(regex => regex.test(attributeName))
|
||||
}
|
||||
|
||||
export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
|
||||
if (!unsafeHtml.length) {
|
||||
|
@ -100,7 +97,6 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
|
|||
|
||||
if (!Object.keys(allowList).includes(elementName)) {
|
||||
element.remove()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/scrollBar.js
|
||||
* Bootstrap util/scrollBar.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import SelectorEngine from '../dom/selector-engine'
|
||||
import Manipulator from '../dom/manipulator'
|
||||
import { isElement } from './index'
|
||||
import Manipulator from '../dom/manipulator.js'
|
||||
import SelectorEngine from '../dom/selector-engine.js'
|
||||
import { isElement } from './index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/swipe.js
|
||||
* Bootstrap util/swipe.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Config from './config'
|
||||
import EventHandler from '../dom/event-handler'
|
||||
import { execute } from './index'
|
||||
import EventHandler from '../dom/event-handler.js'
|
||||
import Config from './config.js'
|
||||
import { execute } from './index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v5.2.3): util/template-factory.js
|
||||
* Bootstrap util/template-factory.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { DefaultAllowlist, sanitizeHtml } from './sanitizer'
|
||||
import { getElement, isElement } from '../util/index'
|
||||
import SelectorEngine from '../dom/selector-engine'
|
||||
import Config from './config'
|
||||
import SelectorEngine from '../dom/selector-engine.js'
|
||||
import Config from './config.js'
|
||||
import { DefaultAllowlist, sanitizeHtml } from './sanitizer.js'
|
||||
import { execute, getElement, isElement } from './index.js'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -143,7 +143,7 @@ class TemplateFactory extends Config {
|
|||
}
|
||||
|
||||
_resolvePossibleFunction(arg) {
|
||||
return typeof arg === 'function' ? arg(this) : arg
|
||||
return execute(arg, [this])
|
||||
}
|
||||
|
||||
_putElementInTemplate(element, templateElement) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-env node */
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
'use strict'
|
||||
|
||||
const browsers = {
|
||||
safariMac: {
|
||||
base: 'BrowserStack',
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-disable import/extensions, import/no-unassigned-import */
|
||||
|
||||
import Tooltip from '../../dist/tooltip'
|
||||
import '../../dist/carousel'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-env node */
|
||||
'use strict'
|
||||
|
||||
const commonjs = require('@rollup/plugin-commonjs')
|
||||
const configRollup = require('./rollup.bundle')
|
||||
const configRollup = require('./rollup.bundle.js')
|
||||
|
||||
const config = {
|
||||
...configRollup,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint-env node */
|
||||
'use strict'
|
||||
|
||||
const { babel } = require('@rollup/plugin-babel')
|
||||
const { nodeResolve } = require('@rollup/plugin-node-resolve')
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* eslint-env node */
|
||||
|
||||
'use strict'
|
||||
|
||||
const path = require('node:path')
|
||||
|
@ -8,7 +6,7 @@ const { babel } = require('@rollup/plugin-babel')
|
|||
const istanbul = require('rollup-plugin-istanbul')
|
||||
const { nodeResolve } = require('@rollup/plugin-node-resolve')
|
||||
const replace = require('@rollup/plugin-replace')
|
||||
const { browsers } = require('./browsers')
|
||||
const { browsers } = require('./browsers.js')
|
||||
|
||||
const ENV = process.env
|
||||
const BROWSERSTACK = Boolean(ENV.BROWSERSTACK)
|
||||
|
@ -105,7 +103,7 @@ if (BROWSERSTACK) {
|
|||
config.browserStack = {
|
||||
username: ENV.BROWSER_STACK_USERNAME,
|
||||
accessKey: ENV.BROWSER_STACK_ACCESS_KEY,
|
||||
build: `bootstrap-${ENV.GITHUB_SHA ? ENV.GITHUB_SHA.slice(0, 7) + '-' : ''}${new Date().toISOString()}`,
|
||||
build: `bootstrap-${ENV.GITHUB_SHA ? `${ENV.GITHUB_SHA.slice(0, 7)}-` : ''}${new Date().toISOString()}`,
|
||||
project: 'Bootstrap',
|
||||
retryLimit: 2
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"extends": [
|
||||
"../../../.eslintrc.json"
|
||||
],
|
||||
"env": {
|
||||
"jasmine": true
|
||||
},
|
||||
"rules": {
|
||||
"unicorn/consistent-function-scoping": "off",
|
||||
"unicorn/no-useless-undefined": "off",
|
||||
"unicorn/prefer-add-event-listener": "off"
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import Alert from '../../src/alert'
|
||||
import { getTransitionDurationFromElement } from '../../src/util/index'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import Alert from '../../src/alert.js'
|
||||
import { getTransitionDurationFromElement } from '../../src/util/index.js'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Alert', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import BaseComponent from '../../src/base-component'
|
||||
import { clearFixture, getFixture } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { noop } from '../../src/util'
|
||||
import BaseComponent from '../../src/base-component.js'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import { noop } from '../../src/util/index.js'
|
||||
import { clearFixture, getFixture } from '../helpers/fixture.js'
|
||||
|
||||
class DummyClass extends BaseComponent {
|
||||
constructor(element) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Button from '../../src/button'
|
||||
import { getFixture, clearFixture, jQueryMock } from '../helpers/fixture'
|
||||
import Button from '../../src/button.js'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Button', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Carousel from '../../src/carousel'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import { isRTL, noop } from '../../src/util/index'
|
||||
import Swipe from '../../src/util/swipe'
|
||||
import Carousel from '../../src/carousel.js'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import { isRTL, noop } from '../../src/util/index.js'
|
||||
import Swipe from '../../src/util/swipe.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Carousel', () => {
|
||||
const { Simulator, PointerEvent } = window
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Collapse from '../../src/collapse'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import Collapse from '../../src/collapse.js'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Collapse', () => {
|
||||
let fixtureEl
|
||||
|
@ -277,25 +277,25 @@ describe('Collapse', () => {
|
|||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="parentGroup" class="accordion">',
|
||||
' <div id="parentHeader" class="accordion-header">',
|
||||
' <button data-bs-target="#parentContent" data-bs-toggle="collapse" role="button" class="accordion-toggle">Parent</button>',
|
||||
' <div class="accordion-header">',
|
||||
' <button data-bs-target="#parentContent" data-bs-toggle="collapse" class="accordion-toggle">Parent</button>',
|
||||
' </div>',
|
||||
' <div id="parentContent" class="accordion-collapse collapse" aria-labelledby="parentHeader" data-bs-parent="#parentGroup">',
|
||||
' <div id="parentContent" class="accordion-collapse collapse" data-bs-parent="#parentGroup">',
|
||||
' <div class="accordion-body">',
|
||||
' <div id="childGroup" class="accordion">',
|
||||
' <div class="accordion-item">',
|
||||
' <div id="childHeader1" class="accordion-header">',
|
||||
' <button data-bs-target="#childContent1" data-bs-toggle="collapse" role="button" class="accordion-toggle">Child 1</button>',
|
||||
' <div class="accordion-header">',
|
||||
' <button data-bs-target="#childContent1" data-bs-toggle="collapse" class="accordion-toggle">Child 1</button>',
|
||||
' </div>',
|
||||
' <div id="childContent1" class="accordion-collapse collapse" aria-labelledby="childHeader1" data-bs-parent="#childGroup">',
|
||||
' <div id="childContent1" class="accordion-collapse collapse" data-bs-parent="#childGroup">',
|
||||
' <div>content</div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="accordion-item">',
|
||||
' <div id="childHeader2" class="accordion-header">',
|
||||
' <button data-bs-target="#childContent2" data-bs-toggle="collapse" role="button" class="accordion-toggle">Child 2</button>',
|
||||
' <div class="accordion-header">',
|
||||
' <button data-bs-target="#childContent2" data-bs-toggle="collapse" class="accordion-toggle">Child 2</button>',
|
||||
' </div>',
|
||||
' <div id="childContent2" class="accordion-collapse collapse" aria-labelledby="childHeader2" data-bs-parent="#childGroup">',
|
||||
' <div id="childContent2" class="accordion-collapse collapse" data-bs-parent="#childGroup">',
|
||||
' <div>content</div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
|
@ -338,12 +338,12 @@ describe('Collapse', () => {
|
|||
fixtureEl.innerHTML = [
|
||||
'<div class="accordion" id="accordionExample">',
|
||||
' <div class="accordion-item">',
|
||||
' <h2 class="accordion-header" id="headingOne">',
|
||||
' <h2 class="accordion-header">',
|
||||
' <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">',
|
||||
' Accordion Item #1',
|
||||
' </button>',
|
||||
' </h2>',
|
||||
' <div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">',
|
||||
' <div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionExample">',
|
||||
' <div class="accordion-body">',
|
||||
' <nav>',
|
||||
' <div class="nav nav-tabs" id="nav-tab" role="tablist">',
|
||||
|
@ -640,11 +640,11 @@ describe('Collapse', () => {
|
|||
'<div id="accordion">',
|
||||
' <div class="item">',
|
||||
' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
|
||||
' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-bs-parent="#accordion"></div>',
|
||||
' <div id="collapseOne" class="collapse" role="tabpanel" data-bs-parent="#accordion"></div>',
|
||||
' </div>',
|
||||
' <div class="item">',
|
||||
' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
|
||||
' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-bs-parent="#accordion"></div>',
|
||||
' <div id="collapseTwo" class="collapse show" role="tabpanel" data-bs-parent="#accordion"></div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
@ -699,13 +699,13 @@ describe('Collapse', () => {
|
|||
' <div class="col-lg-6">',
|
||||
' <div class="item">',
|
||||
' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
|
||||
' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-bs-parent="#accordion"></div>',
|
||||
' <div id="collapseOne" class="collapse" role="tabpanel" data-bs-parent="#accordion"></div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="col-lg-6">',
|
||||
' <div class="item">',
|
||||
' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
|
||||
' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-bs-parent="#accordion"></div>',
|
||||
' <div id="collapseTwo" class="collapse show" role="tabpanel" data-bs-parent="#accordion"></div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
|
@ -829,18 +829,18 @@ describe('Collapse', () => {
|
|||
'<div id="accordion">',
|
||||
' <div class="item">',
|
||||
' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
|
||||
' <div id="collapseOne" data-bs-parent="#accordion" class="collapse" role="tabpanel" aria-labelledby="headingThree">',
|
||||
' <div id="collapseOne" data-bs-parent="#accordion" class="collapse" role="tabpanel">',
|
||||
' <div id="nestedAccordion">',
|
||||
' <div class="item">',
|
||||
' <a id="nestedLinkTrigger" data-bs-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>',
|
||||
' <div id="nestedCollapseOne" data-bs-parent="#nestedAccordion" class="collapse" role="tabpanel" aria-labelledby="headingThree"></div>',
|
||||
' <div id="nestedCollapseOne" data-bs-parent="#nestedAccordion" class="collapse" role="tabpanel"></div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="item">',
|
||||
' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
|
||||
' <div id="collapseTwo" data-bs-parent="#accordion" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>',
|
||||
' <div id="collapseTwo" data-bs-parent="#accordion" class="collapse show" role="tabpanel"></div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
@ -887,17 +887,17 @@ describe('Collapse', () => {
|
|||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="trigger1" role="button" data-bs-toggle="collapse" href="#test1"></a>',
|
||||
'<a id="trigger2" role="button" data-bs-toggle="collapse" href="#test2"></a>',
|
||||
'<a id="trigger2" role="button" data-bs-toggle="collapse" href="#0/my/id"></a>',
|
||||
'<a id="trigger3" role="button" data-bs-toggle="collapse" href=".multi"></a>',
|
||||
'<div id="test1" class="multi"></div>',
|
||||
'<div id="test2" class="multi"></div>'
|
||||
'<div id="0/my/id" class="multi"></div>'
|
||||
].join('')
|
||||
|
||||
const trigger1 = fixtureEl.querySelector('#trigger1')
|
||||
const trigger2 = fixtureEl.querySelector('#trigger2')
|
||||
const trigger3 = fixtureEl.querySelector('#trigger3')
|
||||
const target1 = fixtureEl.querySelector('#test1')
|
||||
const target2 = fixtureEl.querySelector('#test2')
|
||||
const target2 = fixtureEl.querySelector(`#${CSS.escape('0/my/id')}`)
|
||||
|
||||
const target2Shown = () => {
|
||||
expect(trigger1).not.toHaveClass('collapsed')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Data from '../../../src/dom/data'
|
||||
import { getFixture, clearFixture } from '../../helpers/fixture'
|
||||
import Data from '../../../src/dom/data.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('Data', () => {
|
||||
const TEST_KEY = 'bs.test'
|
||||
|
@ -89,7 +89,6 @@ describe('Data', () => {
|
|||
expect(Data.get(div, TEST_KEY)).toBeNull()
|
||||
})
|
||||
|
||||
/* eslint-disable no-console */
|
||||
it('should console.error a message if called with multiple keys', () => {
|
||||
console.error = jasmine.createSpy('console.error')
|
||||
|
||||
|
@ -102,5 +101,4 @@ describe('Data', () => {
|
|||
expect(console.error).toHaveBeenCalled()
|
||||
expect(Data.get(div, UNKNOWN_KEY)).toBeNull()
|
||||
})
|
||||
/* eslint-enable no-console */
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import EventHandler from '../../../src/dom/event-handler'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import { noop } from '../../../src/util'
|
||||
import EventHandler from '../../../src/dom/event-handler.js'
|
||||
import { noop } from '../../../src/util/index.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('EventHandler', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Manipulator from '../../../src/dom/manipulator'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import Manipulator from '../../../src/dom/manipulator.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('Manipulator', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import SelectorEngine from '../../../src/dom/selector-engine'
|
||||
import { getFixture, clearFixture } from '../../helpers/fixture'
|
||||
import SelectorEngine from '../../../src/dom/selector-engine.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('SelectorEngine', () => {
|
||||
let fixtureEl
|
||||
|
@ -232,5 +232,159 @@ describe('SelectorEngine', () => {
|
|||
expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSelectorFromElement', () => {
|
||||
it('should get selector from data-bs-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-bs-target=".target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if no data-bs-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if data-bs-target equal to #', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should return null if a selector from a href is a url without an anchor', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href="foo/bar.html"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return the anchor if a selector from a href is a url', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href="foo/bar.html#target"></a>',
|
||||
'<div id="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('#target')
|
||||
})
|
||||
|
||||
it('should return null if selector not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null if no selector', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('div')
|
||||
|
||||
expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getElementFromSelector', () => {
|
||||
it('should get element from data-bs-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-bs-target=".target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
|
||||
})
|
||||
|
||||
it('should get element from href if no data-bs-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
|
||||
})
|
||||
|
||||
it('should return null if element not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getElementFromSelector(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null if no selector', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('div')
|
||||
|
||||
expect(SelectorEngine.getElementFromSelector(testEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getMultipleElementsFromSelector', () => {
|
||||
it('should get elements from data-bs-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-bs-target=".target"></div>',
|
||||
'<div class="target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
|
||||
})
|
||||
|
||||
it('should get elements in array, from href if no data-bs-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
|
||||
})
|
||||
|
||||
it('should return empty array if elements not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toHaveSize(0)
|
||||
})
|
||||
|
||||
it('should return empty array if no selector', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('div')
|
||||
|
||||
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toHaveSize(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Dropdown from '../../src/dropdown'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { noop } from '../../src/util/index'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import Dropdown from '../../src/dropdown.js'
|
||||
import { noop } from '../../src/util/index.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Dropdown', () => {
|
||||
let fixtureEl
|
||||
|
@ -75,6 +75,7 @@ describe('Dropdown', () => {
|
|||
resolve()
|
||||
})
|
||||
|
||||
expect().nothing()
|
||||
dropdown.show()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/* eslint-env jquery */
|
||||
|
||||
import Alert from '../../src/alert'
|
||||
import Button from '../../src/button'
|
||||
import Carousel from '../../src/carousel'
|
||||
import Collapse from '../../src/collapse'
|
||||
import Dropdown from '../../src/dropdown'
|
||||
import Modal from '../../src/modal'
|
||||
import Offcanvas from '../../src/offcanvas'
|
||||
import Popover from '../../src/popover'
|
||||
import ScrollSpy from '../../src/scrollspy'
|
||||
import Tab from '../../src/tab'
|
||||
import Toast from '../../src/toast'
|
||||
import Tooltip from '../../src/tooltip'
|
||||
import { clearFixture, getFixture } from '../helpers/fixture'
|
||||
import Alert from '../../src/alert.js'
|
||||
import Button from '../../src/button.js'
|
||||
import Carousel from '../../src/carousel.js'
|
||||
import Collapse from '../../src/collapse.js'
|
||||
import Dropdown from '../../src/dropdown.js'
|
||||
import Modal from '../../src/modal.js'
|
||||
import Offcanvas from '../../src/offcanvas.js'
|
||||
import Popover from '../../src/popover.js'
|
||||
import ScrollSpy from '../../src/scrollspy.js'
|
||||
import Tab from '../../src/tab.js'
|
||||
import Toast from '../../src/toast.js'
|
||||
import Tooltip from '../../src/tooltip.js'
|
||||
import { clearFixture, getFixture } from '../helpers/fixture.js'
|
||||
|
||||
describe('jQuery', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Modal from '../../src/modal'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import ScrollBarHelper from '../../src/util/scrollbar'
|
||||
import { clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import Modal from '../../src/modal.js'
|
||||
import ScrollBarHelper from '../../src/util/scrollbar.js'
|
||||
import { clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Modal', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Offcanvas from '../../src/offcanvas'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import { isVisible } from '../../src/util/index'
|
||||
import ScrollBarHelper from '../../src/util/scrollbar'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import Offcanvas from '../../src/offcanvas.js'
|
||||
import { isVisible } from '../../src/util/index.js'
|
||||
import ScrollBarHelper from '../../src/util/scrollbar.js'
|
||||
import { clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Offcanvas', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Popover from '../../src/popover'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import Popover from '../../src/popover.js'
|
||||
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Popover', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import ScrollSpy from '../../src/scrollspy'
|
||||
|
||||
/** Test helpers */
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import ScrollSpy from '../../src/scrollspy.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('ScrollSpy', () => {
|
||||
let fixtureEl
|
||||
|
@ -942,5 +940,39 @@ describe('ScrollSpy', () => {
|
|||
}, 100)
|
||||
link.click()
|
||||
})
|
||||
|
||||
it('should smoothscroll to observable with anchor link that contains a french word as id', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav id="navBar" class="navbar">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a id="li-jsm-1" class="nav-link" href="#présentation">div 1</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div class="content" data-bs-target="#navBar" style="overflow-y: auto">',
|
||||
' <div id="présentation">div 1</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const div = fixtureEl.querySelector('.content')
|
||||
const link = fixtureEl.querySelector('[href="#présentation"]')
|
||||
const observable = fixtureEl.querySelector('#présentation')
|
||||
const clickSpy = getElementScrollSpy(div)
|
||||
// eslint-disable-next-line no-new
|
||||
new ScrollSpy(div, {
|
||||
offset: 1,
|
||||
smoothScroll: true
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
if (div.scrollTo) {
|
||||
expect(clickSpy).toHaveBeenCalledWith({ top: observable.offsetTop - div.offsetTop, behavior: 'smooth' })
|
||||
} else {
|
||||
expect(clickSpy).toHaveBeenCalledWith(observable.offsetTop - div.offsetTop)
|
||||
}
|
||||
|
||||
done()
|
||||
}, 100)
|
||||
link.click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Tab from '../../src/tab'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import Tab from '../../src/tab.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Tab', () => {
|
||||
let fixtureEl
|
||||
|
@ -177,6 +177,43 @@ describe('Tab', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('should work with tab id being an int', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div class="card-header d-block d-inline-block">',
|
||||
' <ul class="nav nav-tabs card-header-tabs" id="page_tabs">',
|
||||
' <li class="nav-item">',
|
||||
' <a class="nav-link" draggable="false" data-toggle="tab" href="#tab1">',
|
||||
' Working Tab 1 (#tab1)',
|
||||
' </a>',
|
||||
' </li>',
|
||||
' <li class="nav-item">',
|
||||
' <a id="trigger2" class="nav-link" draggable="false" data-toggle="tab" href="#2">',
|
||||
' Tab with numeric ID should work (#2)',
|
||||
' </a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
'</div>',
|
||||
'<div class="card-body">',
|
||||
' <div class="tab-content" id="page_content">',
|
||||
' <div class="tab-pane fade" id="tab1">',
|
||||
' Working Tab 1 (#tab1) Content Here',
|
||||
' </div>',
|
||||
' <div class="tab-pane fade" id="2">',
|
||||
' Working Tab 2 (#2) with numeric ID',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
const profileTriggerEl = fixtureEl.querySelector('#trigger2')
|
||||
const tab = new Tab(profileTriggerEl)
|
||||
|
||||
profileTriggerEl.addEventListener('shown.bs.tab', () => {
|
||||
expect(fixtureEl.querySelector(`#${CSS.escape('2')}`)).toHaveClass('active')
|
||||
done()
|
||||
})
|
||||
|
||||
tab.show()
|
||||
})
|
||||
|
||||
it('should not fire shown when show is prevented', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
|
||||
|
@ -477,7 +514,7 @@ describe('Tab', () => {
|
|||
expect(tabPanel.hasAttribute('tabindex')).toBeFalse()
|
||||
expect(tabPanel.hasAttribute('tabindex2')).toBeFalse()
|
||||
|
||||
expect(tabPanel.getAttribute('aria-labelledby')).toEqual('#foo')
|
||||
expect(tabPanel.getAttribute('aria-labelledby')).toEqual('foo')
|
||||
expect(tabPanel2.hasAttribute('aria-labelledby')).toBeFalse()
|
||||
})
|
||||
})
|
||||
|
@ -603,19 +640,19 @@ describe('Tab', () => {
|
|||
'</div>'
|
||||
].join('')
|
||||
|
||||
const tabEl = fixtureEl.querySelector('#tab1')
|
||||
const tabEl1 = fixtureEl.querySelector('#tab1')
|
||||
const tabEl2 = fixtureEl.querySelector('#tab2')
|
||||
const tabEl3 = fixtureEl.querySelector('#tab3')
|
||||
const tabEl4 = fixtureEl.querySelector('#tab4')
|
||||
const tab = new Tab(tabEl)
|
||||
const tab1 = new Tab(tabEl1)
|
||||
const tab2 = new Tab(tabEl2)
|
||||
const tab3 = new Tab(tabEl3)
|
||||
const tab4 = new Tab(tabEl4)
|
||||
const spy1 = spyOn(tab, 'show').and.callThrough()
|
||||
const spy1 = spyOn(tab1, 'show').and.callThrough()
|
||||
const spy2 = spyOn(tab2, 'show').and.callThrough()
|
||||
const spy3 = spyOn(tab3, 'show').and.callThrough()
|
||||
const spy4 = spyOn(tab4, 'show').and.callThrough()
|
||||
const spyFocus1 = spyOn(tabEl, 'focus').and.callThrough()
|
||||
const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough()
|
||||
const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough()
|
||||
const spyFocus3 = spyOn(tabEl3, 'focus').and.callThrough()
|
||||
const spyFocus4 = spyOn(tabEl4, 'focus').and.callThrough()
|
||||
|
@ -623,7 +660,7 @@ describe('Tab', () => {
|
|||
const keydown = createEvent('keydown')
|
||||
keydown.key = 'ArrowRight'
|
||||
|
||||
tabEl.dispatchEvent(keydown)
|
||||
tabEl1.dispatchEvent(keydown)
|
||||
expect(spy1).not.toHaveBeenCalled()
|
||||
expect(spy2).not.toHaveBeenCalled()
|
||||
expect(spy3).not.toHaveBeenCalled()
|
||||
|
@ -644,19 +681,19 @@ describe('Tab', () => {
|
|||
'</div>'
|
||||
].join('')
|
||||
|
||||
const tabEl = fixtureEl.querySelector('#tab1')
|
||||
const tabEl1 = fixtureEl.querySelector('#tab1')
|
||||
const tabEl2 = fixtureEl.querySelector('#tab2')
|
||||
const tabEl3 = fixtureEl.querySelector('#tab3')
|
||||
const tabEl4 = fixtureEl.querySelector('#tab4')
|
||||
const tab = new Tab(tabEl)
|
||||
const tab1 = new Tab(tabEl1)
|
||||
const tab2 = new Tab(tabEl2)
|
||||
const tab3 = new Tab(tabEl3)
|
||||
const tab4 = new Tab(tabEl4)
|
||||
const spy1 = spyOn(tab, 'show').and.callThrough()
|
||||
const spy1 = spyOn(tab1, 'show').and.callThrough()
|
||||
const spy2 = spyOn(tab2, 'show').and.callThrough()
|
||||
const spy3 = spyOn(tab3, 'show').and.callThrough()
|
||||
const spy4 = spyOn(tab4, 'show').and.callThrough()
|
||||
const spyFocus1 = spyOn(tabEl, 'focus').and.callThrough()
|
||||
const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough()
|
||||
const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough()
|
||||
const spyFocus3 = spyOn(tabEl3, 'focus').and.callThrough()
|
||||
const spyFocus4 = spyOn(tabEl4, 'focus').and.callThrough()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Toast from '../../src/toast'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import Toast from '../../src/toast.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Toast', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Tooltip from '../../src/tooltip'
|
||||
import EventHandler from '../../src/dom/event-handler'
|
||||
import { noop } from '../../src/util/index'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
import EventHandler from '../../src/dom/event-handler.js'
|
||||
import Tooltip from '../../src/tooltip.js'
|
||||
import { noop } from '../../src/util/index.js'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture.js'
|
||||
|
||||
describe('Tooltip', () => {
|
||||
let fixtureEl
|
||||
|
@ -56,7 +56,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('constructor', () => {
|
||||
it('should take care of element either passed as a CSS selector or DOM element', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" id="tooltipEl" rel="tooltip" title="Nice and short title">'
|
||||
fixtureEl.innerHTML = '<a href="#" id="tooltipEl" rel="tooltip" title="Nice and short title"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('#tooltipEl')
|
||||
const tooltipBySelector = new Tooltip('#tooltipEl')
|
||||
|
@ -67,7 +67,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should not take care of disallowed data attributes', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-sanitize="false" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-sanitize="false" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -76,7 +76,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should convert title and content to string if numbers', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -98,7 +98,7 @@ describe('Tooltip', () => {
|
|||
trigger: 'click'
|
||||
})
|
||||
|
||||
containerEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
containerEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipInContainerEl = containerEl.querySelector('a')
|
||||
|
||||
|
@ -114,7 +114,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should create offset modifier when offset is passed as a function', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Offset from function">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Offset from function"></a>'
|
||||
|
||||
const getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20])
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
|
@ -141,7 +141,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should create offset modifier when offset option is passed in data attribute', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-offset="10,20" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-offset="10,20" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -150,7 +150,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should allow to pass config to Popper with `popperConfig`', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -165,7 +165,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should allow to pass config to Popper with `popperConfig` as a function', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const getPopperConfig = jasmine.createSpy('getPopperConfig').and.returnValue({ placement: 'left' })
|
||||
|
@ -192,7 +192,7 @@ describe('Tooltip', () => {
|
|||
describe('enable', () => {
|
||||
it('should enable a tooltip', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -212,7 +212,7 @@ describe('Tooltip', () => {
|
|||
describe('disable', () => {
|
||||
it('should disable tooltip', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -235,7 +235,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('toggleEnabled', () => {
|
||||
it('should toggle enabled', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -251,7 +251,7 @@ describe('Tooltip', () => {
|
|||
describe('toggle', () => {
|
||||
it('should do nothing if disabled', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -273,7 +273,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -289,7 +289,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should call toggle and show the tooltip when trigger is "click"', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -309,7 +309,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should hide a tooltip', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -329,7 +329,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should call toggle and hide the tooltip when trigger is "click"', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -354,7 +354,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('dispose', () => {
|
||||
it('should destroy a tooltip', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const addEventSpy = spyOn(tooltipEl, 'addEventListener').and.callThrough()
|
||||
|
@ -381,7 +381,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should destroy a tooltip after it is shown and hidden', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -402,7 +402,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should destroy a tooltip and remove it from the dom', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -443,7 +443,7 @@ describe('Tooltip', () => {
|
|||
describe('show', () => {
|
||||
it('should show a tooltip', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -488,7 +488,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip on mobile', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -509,7 +509,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip relative to placement option', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -532,7 +532,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should not error when trying to show a tooltip that has been removed from the dom', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -561,7 +561,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with a dom element container', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -579,7 +579,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with a jquery element container', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -600,7 +600,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with a selector in container', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -618,7 +618,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with placement as a function', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const spy = jasmine.createSpy('placement').and.returnValue('top')
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
|
@ -638,7 +638,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip without the animation', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -658,7 +658,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should throw an error the element is not visible', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" style="display: none" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" style="display: none" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -672,7 +672,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should not show a tooltip if show.bs.tooltip is prevented', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -699,7 +699,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show tooltip if leave event hasn\'t occurred before delay expires', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -723,7 +723,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should not show tooltip if leave event occurs before delay expires', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -845,7 +845,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should only trigger inserted event if a new tooltip element was created', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -878,7 +878,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with custom class provided in data attributes', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip" data-bs-custom-class="custom-class">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip" data-bs-custom-class="custom-class"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -896,7 +896,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with custom class provided as a string in config', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -917,7 +917,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should show a tooltip with custom class provided as a function in config', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const spy = jasmine.createSpy('customClass').and.returnValue('custom-class')
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
|
@ -956,7 +956,7 @@ describe('Tooltip', () => {
|
|||
describe('hide', () => {
|
||||
it('should hide a tooltip', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -974,7 +974,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should hide a tooltip on mobile', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -998,7 +998,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should hide a tooltip without animation', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
|
@ -1018,7 +1018,7 @@ describe('Tooltip', () => {
|
|||
|
||||
it('should not hide a tooltip if hide event is prevented', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const assertDone = () => {
|
||||
setTimeout(() => {
|
||||
|
@ -1063,7 +1063,7 @@ describe('Tooltip', () => {
|
|||
describe('update', () => {
|
||||
it('should call popper update', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1082,7 +1082,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should do nothing if the tooltip is not shown', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1094,7 +1094,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('_isWithContent', () => {
|
||||
it('should return true if there is content', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1103,7 +1103,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should return false if there is no content', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title=""></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1114,7 +1114,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('_getTipElement', () => {
|
||||
it('should create the tip element and return it', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1126,7 +1126,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should return the created tip element', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1145,7 +1145,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('setContent', () => {
|
||||
it('should set tip content', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, { animation: false })
|
||||
|
@ -1160,7 +1160,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should re-show tip if it was already shown', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1175,7 +1175,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('should keep tip hidden, if it was already hidden before', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1190,7 +1190,7 @@ describe('Tooltip', () => {
|
|||
})
|
||||
|
||||
it('"setContent" should keep the initial template', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
@ -1207,7 +1207,7 @@ describe('Tooltip', () => {
|
|||
|
||||
describe('setContent', () => {
|
||||
it('should do nothing if the element is null', () => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
|
||||
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Backdrop from '../../../src/util/backdrop'
|
||||
import { getTransitionDurationFromElement } from '../../../src/util/index'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import Backdrop from '../../../src/util/backdrop.js'
|
||||
import { getTransitionDurationFromElement } from '../../../src/util/index.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
const CLASS_BACKDROP = '.modal-backdrop'
|
||||
const CLASS_NAME_FADE = 'fade'
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* Test helpers */
|
||||
|
||||
import { clearFixture, createEvent, getFixture } from '../../helpers/fixture'
|
||||
import { enableDismissTrigger } from '../../../src/util/component-functions'
|
||||
import BaseComponent from '../../../src/base-component'
|
||||
import BaseComponent from '../../../src/base-component.js'
|
||||
import { enableDismissTrigger } from '../../../src/util/component-functions.js'
|
||||
import { clearFixture, createEvent, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
class DummyClass2 extends BaseComponent {
|
||||
static get NAME() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Config from '../../../src/util/config'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import Config from '../../../src/util/config.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
class DummyConfigClass extends Config {
|
||||
static get NAME() {
|
||||
|
@ -128,7 +128,7 @@ describe('Config', () => {
|
|||
const obj = new DummyConfigClass()
|
||||
expect(() => {
|
||||
obj._typeCheckConfig(config)
|
||||
}).toThrowError(TypeError, obj.constructor.NAME.toUpperCase() + ': Option "parent" provided type "number" but expected type "(string|element)".')
|
||||
}).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', () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import FocusTrap from '../../../src/util/focustrap'
|
||||
import EventHandler from '../../../src/dom/event-handler'
|
||||
import SelectorEngine from '../../../src/dom/selector-engine'
|
||||
import { clearFixture, createEvent, getFixture } from '../../helpers/fixture'
|
||||
import EventHandler from '../../../src/dom/event-handler.js'
|
||||
import SelectorEngine from '../../../src/dom/selector-engine.js'
|
||||
import FocusTrap from '../../../src/util/focustrap.js'
|
||||
import { clearFixture, createEvent, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('FocusTrap', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as Util from '../../../src/util/index'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import { noop } from '../../../src/util/index'
|
||||
import * as Util from '../../../src/util/index.js'
|
||||
import { noop } from '../../../src/util/index.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('Util', () => {
|
||||
let fixtureEl
|
||||
|
@ -22,119 +22,6 @@ describe('Util', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('getSelectorFromElement', () => {
|
||||
it('should get selector from data-bs-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-bs-target=".target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if no data-bs-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if data-bs-target equal to #', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should return null if a selector from a href is a url without an anchor', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href="foo/bar.html"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return the anchor if a selector from a href is a url', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-bs-target="#" href="foo/bar.html#target"></a>',
|
||||
'<div id="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('#target')
|
||||
})
|
||||
|
||||
it('should return null if selector not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null if no selector', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getElementFromSelector', () => {
|
||||
it('should get element from data-bs-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-bs-target=".target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
|
||||
})
|
||||
|
||||
it('should get element from href if no data-bs-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
|
||||
})
|
||||
|
||||
it('should return null if element not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getElementFromSelector(testEl)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null if no selector', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.getElementFromSelector(testEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getTransitionDurationFromElement', () => {
|
||||
it('should get transition from element', () => {
|
||||
fixtureEl.innerHTML = '<div style="transition: all 300ms ease-out;"></div>'
|
||||
|
@ -631,6 +518,25 @@ describe('Util', () => {
|
|||
Util.execute(spy)
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should execute if arg is function & return the result', () => {
|
||||
const functionFoo = (num1, num2 = 10) => num1 + num2
|
||||
const resultFoo = Util.execute(functionFoo, [4, 5])
|
||||
expect(resultFoo).toBe(9)
|
||||
|
||||
const resultFoo1 = Util.execute(functionFoo, [4])
|
||||
expect(resultFoo1).toBe(14)
|
||||
|
||||
const functionBar = () => 'foo'
|
||||
const resultBar = Util.execute(functionBar)
|
||||
expect(resultBar).toBe('foo')
|
||||
})
|
||||
|
||||
it('should not execute if arg is not function & return default argument', () => {
|
||||
const foo = 'bar'
|
||||
expect(Util.execute(foo)).toBe('bar')
|
||||
expect(Util.execute(foo, [], 4)).toBe(4)
|
||||
})
|
||||
})
|
||||
|
||||
describe('executeAfterTransition', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DefaultAllowlist, sanitizeHtml } from '../../../src/util/sanitizer'
|
||||
import { DefaultAllowlist, sanitizeHtml } from '../../../src/util/sanitizer.js'
|
||||
|
||||
describe('Sanitizer', () => {
|
||||
describe('sanitizeHtml', () => {
|
||||
|
@ -10,17 +10,75 @@ describe('Sanitizer', () => {
|
|||
expect(result).toEqual(empty)
|
||||
})
|
||||
|
||||
it('should retain tags with valid URLs', () => {
|
||||
const validUrls = [
|
||||
'',
|
||||
'http://abc',
|
||||
'HTTP://abc',
|
||||
'https://abc',
|
||||
'HTTPS://abc',
|
||||
'ftp://abc',
|
||||
'FTP://abc',
|
||||
'mailto:me@example.com',
|
||||
'MAILTO:me@example.com',
|
||||
'tel:123-123-1234',
|
||||
'TEL:123-123-1234',
|
||||
'sip:me@example.com',
|
||||
'SIP:me@example.com',
|
||||
'#anchor',
|
||||
'/page1.md',
|
||||
'http://JavaScript/my.js',
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
|
||||
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
||||
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
||||
'unknown-scheme:abc'
|
||||
]
|
||||
|
||||
for (const url of validUrls) {
|
||||
const template = [
|
||||
'<div>',
|
||||
` <a href="${url}">Click me</a>`,
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const result = sanitizeHtml(template, DefaultAllowlist, null)
|
||||
|
||||
expect(result).toContain(`href="${url}"`)
|
||||
}
|
||||
})
|
||||
|
||||
it('should sanitize template by removing tags with XSS', () => {
|
||||
const template = [
|
||||
'<div>',
|
||||
' <a href="javascript:alert(7)">Click me</a>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
const invalidUrls = [
|
||||
// eslint-disable-next-line no-script-url
|
||||
'javascript:alert(7)',
|
||||
// eslint-disable-next-line no-script-url
|
||||
'javascript:evil()',
|
||||
// eslint-disable-next-line no-script-url
|
||||
'JavaScript:abc',
|
||||
' javascript:abc',
|
||||
' \n Java\n Script:abc',
|
||||
'javascript:',
|
||||
'javascript:',
|
||||
'j avascript:',
|
||||
'javascript:',
|
||||
'javascript:',
|
||||
'jav	ascript:alert();',
|
||||
'jav\u0000ascript:alert();'
|
||||
]
|
||||
|
||||
const result = sanitizeHtml(template, DefaultAllowlist, null)
|
||||
for (const url of invalidUrls) {
|
||||
const template = [
|
||||
'<div>',
|
||||
` <a href="${url}">Click me</a>`,
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
expect(result).not.toContain('href="javascript:alert(7)')
|
||||
const result = sanitizeHtml(template, DefaultAllowlist, null)
|
||||
|
||||
expect(result).not.toContain(`href="${url}"`)
|
||||
}
|
||||
})
|
||||
|
||||
it('should sanitize template and work with multiple regex', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { clearBodyAndDocument, clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import Manipulator from '../../../src/dom/manipulator'
|
||||
import ScrollBarHelper from '../../../src/util/scrollbar'
|
||||
import Manipulator from '../../../src/dom/manipulator.js'
|
||||
import ScrollBarHelper from '../../../src/util/scrollbar.js'
|
||||
import { clearBodyAndDocument, clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('ScrollBar', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import EventHandler from '../../../src/dom/event-handler'
|
||||
import Swipe from '../../../src/util/swipe'
|
||||
import { noop } from '../../../src/util'
|
||||
import EventHandler from '../../../src/dom/event-handler.js'
|
||||
import { noop } from '../../../src/util/index.js'
|
||||
import Swipe from '../../../src/util/swipe.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('Swipe', () => {
|
||||
const { Simulator, PointerEvent } = window
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import TemplateFactory from '../../../src/util/template-factory'
|
||||
import TemplateFactory from '../../../src/util/template-factory.js'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture.js'
|
||||
|
||||
describe('TemplateFactory', () => {
|
||||
let fixtureEl
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
"html"
|
||||
],
|
||||
"extends": "../../../.eslintrc.json",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"html/html-extensions": [
|
||||
".html"
|
||||
]
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "off",
|
||||
"no-new": "off",
|
||||
"unicorn/no-array-for-each": "off"
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
</button>
|
||||
|
||||
<p>For checkboxes and radio buttons, ensure that keyboard behavior is functioning correctly.</p>
|
||||
<p>Navigate to the checkboxes with the keyboard (generally, using <kbd>TAB</kbd> / <kbd>SHIFT + TAB</kbd>), and ensure that <kbd>SPACE</kbd> toggles the currently focused checkbox. Click on one of the checkboxes using the mouse, ensure that focus was correctly set on the actual checkbox, and that <kbd>SPACE</kbd> toggles the checkbox again.</p>
|
||||
<p>Navigate to the checkboxes with the keyboard (generally, using <kbd>Tab</kbd> / <kbd><kbd>Shift</kbd> + <kbd>Tab</kbd></kbd>), and ensure that <kbd>Space</kbd> toggles the currently focused checkbox. Click on one of the checkboxes using the mouse, ensure that focus was correctly set on the actual checkbox, and that <kbd>Space</kbd> toggles the checkbox again.</p>
|
||||
|
||||
<div class="btn-group" data-bs-toggle="buttons">
|
||||
<label class="btn btn-primary active">
|
||||
|
@ -29,7 +29,7 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<p>Navigate to the radio button group with the keyboard (generally, using <kbd>TAB</kbd> / <kbd>SHIFT + TAB</kbd>). If no radio button was initially set to be selected, the first/last radio button should receive focus (depending on whether you navigated "forward" to the group with <kbd>TAB</kbd> or "backwards" using <kbd>SHIFT + TAB</kbd>). If a radio button was already selected, navigating with the keyboard should set focus to that particular radio button. Only one radio button in a group should receive focus at any given time. Ensure that the selected radio button can be changed by using the <kbd>←</kbd> and <kbd>→</kbd> arrow keys. Click on one of the radio buttons with the mouse, ensure that focus was correctly set on the actual radio button, and that <kbd>←</kbd> and <kbd>→</kbd> change the selected radio button again.</p>
|
||||
<p>Navigate to the radio button group with the keyboard (generally, using <kbd>Tab</kbd> / <kbd><kbd>Shift</kbd> + <kbd>Tab</kbd></kbd>). If no radio button was initially set to be selected, the first/last radio button should receive focus (depending on whether you navigated "forward" to the group with <kbd>Tab</kbd> or "backwards" using <kbd><kbd>Shift</kbd> + <kbd>Tab</kbd></kbd>). If a radio button was already selected, navigating with the keyboard should set focus to that particular radio button. Only one radio button in a group should receive focus at any given time. Ensure that the selected radio button can be changed by using the <kbd>←</kbd> and <kbd>→</kbd> arrow keys. Click on one of the radio buttons with the mouse, ensure that focus was correctly set on the actual radio button, and that <kbd>←</kbd> and <kbd>→</kbd> change the selected radio button again.</p>
|
||||
|
||||
<div class="btn-group" data-bs-toggle="buttons">
|
||||
<label class="btn btn-primary active">
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
// Test to show that transition-duration can be changed with css
|
||||
carousel.addEventListener('slid.bs.carousel', event => {
|
||||
t1 = performance.now()
|
||||
console.log('transition-duration took ' + (t1 - t0) + 'ms, slid at ' + event.timeStamp)
|
||||
console.log(`transition-duration took ${t1 - t0}ms, slid at ${event.timeStamp}`)
|
||||
})
|
||||
carousel.addEventListener('slide.bs.carousel', () => {
|
||||
t0 = performance.now()
|
||||
|
|
78
js/tests/visual/input.html
Normal file
78
js/tests/visual/input.html
Normal file
|
@ -0,0 +1,78 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../../dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<title>Form</title>
|
||||
<style></style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Input <small>Bootstrap Visual Test</small></h1>
|
||||
|
||||
<h2>No layout</h2>
|
||||
|
||||
<div class="mb-3">
|
||||
Text
|
||||
<input class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
Email
|
||||
<input type="email" class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
Number
|
||||
<input type="number" class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
Date
|
||||
<input type="date" class="form-control">
|
||||
</div>
|
||||
|
||||
<h2>Flex</h2>
|
||||
|
||||
<div class="d-flex flex-wrap gap-3 mb-3">
|
||||
<div>
|
||||
Text
|
||||
<input class="form-control">
|
||||
</div>
|
||||
<div>
|
||||
Email
|
||||
<input type="email" class="form-control">
|
||||
</div>
|
||||
<div>
|
||||
Number
|
||||
<input type="number" class="form-control">
|
||||
</div>
|
||||
<div>
|
||||
Date
|
||||
<input type="date" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Grid</h2>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
Text
|
||||
<input class="form-control">
|
||||
</div>
|
||||
<div class="col">
|
||||
Email
|
||||
<input type="email" class="form-control">
|
||||
</div>
|
||||
<div class="col">
|
||||
Number
|
||||
<input type="number" class="form-control">
|
||||
</div>
|
||||
<div class="col">
|
||||
Date
|
||||
<input type="date" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../../../dist/js/bootstrap.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -264,7 +264,7 @@
|
|||
|
||||
slowModal.addEventListener('shown.bs.modal', () => {
|
||||
t1 = performance.now()
|
||||
console.log('transition-duration took ' + (t1 - t0) + 'ms.')
|
||||
console.log(`transition-duration took ${t1 - t0}ms.`)
|
||||
})
|
||||
|
||||
slowModal.addEventListener('show.bs.modal', () => {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<li><a class="dropdown-item" href="#one">One</a></li>
|
||||
<li><a class="dropdown-item" href="#two">Two</a></li>
|
||||
<li><a class="dropdown-item" href="#three">Three</a></li>
|
||||
<li><a class="dropdown-item" href="#présentation">Présentation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
|
@ -82,6 +83,14 @@
|
|||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<hr>
|
||||
<h2 id="présentation">Présentation</h2>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
|
||||
<hr>
|
||||
<h2 id="final">Final section</h2>
|
||||
<p>Ad leggings keytar, brunch id art party dolor labore.</p>
|
||||
</div>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<div class="toast-header">
|
||||
<span class="d-block bg-primary rounded me-2" style="width: 20px; height: 20px;"></span>
|
||||
<strong class="me-auto">Bootstrap</strong>
|
||||
<small class="text-muted">2 seconds ago</small>
|
||||
<small class="text-body-secondary">2 seconds ago</small>
|
||||
<button type="button" class="ms-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<div class="container">
|
||||
<h1>Tooltip <small>Bootstrap Visual Test</small></h1>
|
||||
|
||||
<p class="text-muted">Tight pants next level keffiyeh <a href="#" data-bs-toggle="tooltip" title="Default tooltip">you probably</a> haven't heard of them. Photo booth beard raw denim letterpress vegan messenger bag stumptown. Farm-to-table seitan, mcsweeney's fixie sustainable quinoa 8-bit american apparel <a href="#" data-bs-toggle="tooltip" title="Another tooltip">have a</a> terry richardson vinyl chambray. Beard stumptown, cardigans banh mi lomo thundercats. Tofu biodiesel williamsburg marfa, four loko mcsweeney's cleanse vegan chambray. A really ironic artisan <a href="#" data-bs-toggle="tooltip" title="Another one here too">whatever keytar</a>, scenester farm-to-table banksy Austin <a href="#" data-bs-toggle="tooltip" title="The last tip!">twitter handle</a> freegan cred raw denim single-origin coffee viral.</p>
|
||||
<p class="text-body-secondary">Tight pants next level keffiyeh <a href="#" data-bs-toggle="tooltip" title="Default tooltip">you probably</a> haven't heard of them. Photo booth beard raw denim letterpress vegan messenger bag stumptown. Farm-to-table seitan, mcsweeney's fixie sustainable quinoa 8-bit american apparel <a href="#" data-bs-toggle="tooltip" title="Another tooltip">have a</a> terry richardson vinyl chambray. Beard stumptown, cardigans banh mi lomo thundercats. Tofu biodiesel williamsburg marfa, four loko mcsweeney's cleanse vegan chambray. A really ironic artisan <a href="#" data-bs-toggle="tooltip" title="Another one here too">whatever keytar</a>, scenester farm-to-table banksy Austin <a href="#" data-bs-toggle="tooltip" title="The last tip!">twitter handle</a> freegan cred raw denim single-origin coffee viral.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue