diff options
Diffstat (limited to 'vendor/twbs/bootstrap/js/src/dom/event-handler.js')
-rw-r--r-- | vendor/twbs/bootstrap/js/src/dom/event-handler.js | 188 |
1 files changed, 80 insertions, 108 deletions
diff --git a/vendor/twbs/bootstrap/js/src/dom/event-handler.js b/vendor/twbs/bootstrap/js/src/dom/event-handler.js index e085ea138..d141258bd 100644 --- a/vendor/twbs/bootstrap/js/src/dom/event-handler.js +++ b/vendor/twbs/bootstrap/js/src/dom/event-handler.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.1.3): dom/event-handler.js + * Bootstrap (v5.2.0): dom/event-handler.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -8,9 +8,7 @@ import { getjQuery } from '../util/index' /** - * ------------------------------------------------------------------------ * Constants - * ------------------------------------------------------------------------ */ const namespaceRegex = /[^.]*(?=\..*)\.|.*/ @@ -22,7 +20,7 @@ const customEvents = { mouseenter: 'mouseover', mouseleave: 'mouseout' } -const customEventsRegex = /^(mouseenter|mouseleave)/i + const nativeEvents = new Set([ 'click', 'dblclick', @@ -73,17 +71,15 @@ const nativeEvents = new Set([ ]) /** - * ------------------------------------------------------------------------ * Private methods - * ------------------------------------------------------------------------ */ -function getUidEvent(element, uid) { +function makeEventUid(element, uid) { return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++ } -function getEvent(element) { - const uid = getUidEvent(element) +function getElementEvents(element) { + const uid = makeEventUid(element) element.uidEvent = uid eventRegistry[uid] = eventRegistry[uid] || {} @@ -93,7 +89,7 @@ function getEvent(element) { function bootstrapHandler(element, fn) { return function handler(event) { - event.delegateTarget = element + hydrateObj(event, { delegateTarget: element }) if (handler.oneOff) { EventHandler.off(element, event.type, fn) @@ -108,66 +104,52 @@ function bootstrapDelegationHandler(element, selector, fn) { const domElements = element.querySelectorAll(selector) for (let { target } = event; target && target !== this; target = target.parentNode) { - for (let i = domElements.length; i--;) { - if (domElements[i] === target) { - event.delegateTarget = target + for (const domElement of domElements) { + if (domElement !== target) { + continue + } - if (handler.oneOff) { - EventHandler.off(element, event.type, selector, fn) - } + hydrateObj(event, { delegateTarget: target }) - return fn.apply(target, [event]) + if (handler.oneOff) { + EventHandler.off(element, event.type, selector, fn) } + + return fn.apply(target, [event]) } } - - // To please ESLint - return null } } -function findHandler(events, handler, delegationSelector = null) { - const uidEventList = Object.keys(events) - - for (let i = 0, len = uidEventList.length; i < len; i++) { - const event = events[uidEventList[i]] - - if (event.originalHandler === handler && event.delegationSelector === delegationSelector) { - return event - } - } - - return null +function findHandler(events, callable, delegationSelector = null) { + return Object.values(events) + .find(event => event.callable === callable && event.delegationSelector === delegationSelector) } -function normalizeParams(originalTypeEvent, handler, delegationFn) { - const delegation = typeof handler === 'string' - const originalHandler = delegation ? delegationFn : handler - +function normalizeParameters(originalTypeEvent, handler, delegationFunction) { + const isDelegated = typeof handler === 'string' + // todo: tooltip passes `false` instead of selector, so we need to check + const callable = isDelegated ? delegationFunction : (handler || delegationFunction) let typeEvent = getTypeEvent(originalTypeEvent) - const isNative = nativeEvents.has(typeEvent) - if (!isNative) { + if (!nativeEvents.has(typeEvent)) { typeEvent = originalTypeEvent } - return [delegation, originalHandler, typeEvent] + return [isDelegated, callable, typeEvent] } -function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { +function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { if (typeof originalTypeEvent !== 'string' || !element) { return } - if (!handler) { - handler = delegationFn - delegationFn = null - } + let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction) // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position // this prevents the handler from being dispatched the same way as mouseover or mouseout does - if (customEventsRegex.test(originalTypeEvent)) { - const wrapFn = fn => { + if (originalTypeEvent in customEvents) { + const wrapFunction = fn => { return function (event) { if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) { return fn.call(this, event) @@ -175,36 +157,31 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { } } - if (delegationFn) { - delegationFn = wrapFn(delegationFn) - } else { - handler = wrapFn(handler) - } + callable = wrapFunction(callable) } - const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) - const events = getEvent(element) + const events = getElementEvents(element) const handlers = events[typeEvent] || (events[typeEvent] = {}) - const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null) + const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null) - if (previousFn) { - previousFn.oneOff = previousFn.oneOff && oneOff + if (previousFunction) { + previousFunction.oneOff = previousFunction.oneOff && oneOff return } - const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, '')) - const fn = delegation ? - bootstrapDelegationHandler(element, handler, delegationFn) : - bootstrapHandler(element, handler) + const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')) + const fn = isDelegated ? + bootstrapDelegationHandler(element, handler, callable) : + bootstrapHandler(element, callable) - fn.delegationSelector = delegation ? handler : null - fn.originalHandler = originalHandler + fn.delegationSelector = isDelegated ? handler : null + fn.callable = callable fn.oneOff = oneOff fn.uidEvent = uid handlers[uid] = fn - element.addEventListener(typeEvent, fn, delegation) + element.addEventListener(typeEvent, fn, isDelegated) } function removeHandler(element, events, typeEvent, handler, delegationSelector) { @@ -221,13 +198,12 @@ function removeHandler(element, events, typeEvent, handler, delegationSelector) function removeNamespacedHandlers(element, events, typeEvent, namespace) { const storeElementEvent = events[typeEvent] || {} - Object.keys(storeElementEvent).forEach(handlerKey => { + for (const handlerKey of Object.keys(storeElementEvent)) { if (handlerKey.includes(namespace)) { const event = storeElementEvent[handlerKey] - - removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) + removeHandler(element, events, typeEvent, event.callable, event.delegationSelector) } - }) + } } function getTypeEvent(event) { @@ -237,50 +213,49 @@ function getTypeEvent(event) { } const EventHandler = { - on(element, event, handler, delegationFn) { - addHandler(element, event, handler, delegationFn, false) + on(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, false) }, - one(element, event, handler, delegationFn) { - addHandler(element, event, handler, delegationFn, true) + one(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, true) }, - off(element, originalTypeEvent, handler, delegationFn) { + off(element, originalTypeEvent, handler, delegationFunction) { if (typeof originalTypeEvent !== 'string' || !element) { return } - const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) + const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction) const inNamespace = typeEvent !== originalTypeEvent - const events = getEvent(element) + const events = getElementEvents(element) + const storeElementEvent = events[typeEvent] || {} const isNamespace = originalTypeEvent.startsWith('.') - if (typeof originalHandler !== 'undefined') { + if (typeof callable !== 'undefined') { // Simplest case: handler is passed, remove that listener ONLY. - if (!events || !events[typeEvent]) { + if (!Object.keys(storeElementEvent).length) { return } - removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null) + removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null) return } if (isNamespace) { - Object.keys(events).forEach(elementEvent => { + for (const elementEvent of Object.keys(events)) { removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)) - }) + } } - const storeElementEvent = events[typeEvent] || {} - Object.keys(storeElementEvent).forEach(keyHandlers => { + for (const keyHandlers of Object.keys(storeElementEvent)) { const handlerKey = keyHandlers.replace(stripUidRegex, '') if (!inNamespace || originalTypeEvent.includes(handlerKey)) { const event = storeElementEvent[keyHandlers] - - removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) + removeHandler(element, events, typeEvent, event.callable, event.delegationSelector) } - }) + } }, trigger(element, event, args) { @@ -291,13 +266,11 @@ const EventHandler = { const $ = getjQuery() const typeEvent = getTypeEvent(event) const inNamespace = event !== typeEvent - const isNative = nativeEvents.has(typeEvent) - let jQueryEvent + let jQueryEvent = null let bubbles = true let nativeDispatch = true let defaultPrevented = false - let evt = null if (inNamespace && $) { jQueryEvent = $.Event(event, args) @@ -308,26 +281,8 @@ const EventHandler = { defaultPrevented = jQueryEvent.isDefaultPrevented() } - if (isNative) { - evt = document.createEvent('HTMLEvents') - evt.initEvent(typeEvent, bubbles, true) - } else { - evt = new CustomEvent(event, { - bubbles, - cancelable: true - }) - } - - // merge custom information in our event - if (typeof args !== 'undefined') { - Object.keys(args).forEach(key => { - Object.defineProperty(evt, key, { - get() { - return args[key] - } - }) - }) - } + let evt = new Event(event, { bubbles, cancelable: true }) + evt = hydrateObj(evt, args) if (defaultPrevented) { evt.preventDefault() @@ -337,7 +292,7 @@ const EventHandler = { element.dispatchEvent(evt) } - if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') { + if (evt.defaultPrevented && jQueryEvent) { jQueryEvent.preventDefault() } @@ -345,4 +300,21 @@ const EventHandler = { } } +function hydrateObj(obj, meta) { + for (const [key, value] of Object.entries(meta || {})) { + try { + obj[key] = value + } catch { + Object.defineProperty(obj, key, { + configurable: true, + get() { + return value + } + }) + } + } + + return obj +} + export default EventHandler |