From d459dfac74e90c29950d49a82edc19fd913d435e Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 29 Jul 2021 08:25:05 +0000 Subject: update to bootstrap 5.0.2 --- vendor/twbs/bootstrap/js/src/dom/event-handler.js | 349 ++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 vendor/twbs/bootstrap/js/src/dom/event-handler.js (limited to 'vendor/twbs/bootstrap/js/src/dom/event-handler.js') diff --git a/vendor/twbs/bootstrap/js/src/dom/event-handler.js b/vendor/twbs/bootstrap/js/src/dom/event-handler.js new file mode 100644 index 000000000..c8303f7f2 --- /dev/null +++ b/vendor/twbs/bootstrap/js/src/dom/event-handler.js @@ -0,0 +1,349 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.0.2): dom/event-handler.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + +import { getjQuery } from '../util/index' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const namespaceRegex = /[^.]*(?=\..*)\.|.*/ +const stripNameRegex = /\..*/ +const stripUidRegex = /::\d+$/ +const eventRegistry = {} // Events storage +let uidEvent = 1 +const customEvents = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' +} +const customEventsRegex = /^(mouseenter|mouseleave)/i +const nativeEvents = new Set([ + 'click', + 'dblclick', + 'mouseup', + 'mousedown', + 'contextmenu', + 'mousewheel', + 'DOMMouseScroll', + 'mouseover', + 'mouseout', + 'mousemove', + 'selectstart', + 'selectend', + 'keydown', + 'keypress', + 'keyup', + 'orientationchange', + 'touchstart', + 'touchmove', + 'touchend', + 'touchcancel', + 'pointerdown', + 'pointermove', + 'pointerup', + 'pointerleave', + 'pointercancel', + 'gesturestart', + 'gesturechange', + 'gestureend', + 'focus', + 'blur', + 'change', + 'reset', + 'select', + 'submit', + 'focusin', + 'focusout', + 'load', + 'unload', + 'beforeunload', + 'resize', + 'move', + 'DOMContentLoaded', + 'readystatechange', + 'error', + 'abort', + 'scroll' +]) + +/** + * ------------------------------------------------------------------------ + * Private methods + * ------------------------------------------------------------------------ + */ + +function getUidEvent(element, uid) { + return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++ +} + +function getEvent(element) { + const uid = getUidEvent(element) + + element.uidEvent = uid + eventRegistry[uid] = eventRegistry[uid] || {} + + return eventRegistry[uid] +} + +function bootstrapHandler(element, fn) { + return function handler(event) { + event.delegateTarget = element + + if (handler.oneOff) { + EventHandler.off(element, event.type, fn) + } + + return fn.apply(element, [event]) + } +} + +function bootstrapDelegationHandler(element, selector, fn) { + return function handler(event) { + 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 + + if (handler.oneOff) { + // eslint-disable-next-line unicorn/consistent-destructuring + 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 normalizeParams(originalTypeEvent, handler, delegationFn) { + const delegation = typeof handler === 'string' + const originalHandler = delegation ? delegationFn : handler + + let typeEvent = getTypeEvent(originalTypeEvent) + const isNative = nativeEvents.has(typeEvent) + + if (!isNative) { + typeEvent = originalTypeEvent + } + + return [delegation, originalHandler, typeEvent] +} + +function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { + if (typeof originalTypeEvent !== 'string' || !element) { + return + } + + if (!handler) { + handler = delegationFn + delegationFn = null + } + + // 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 => { + return function (event) { + if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) { + return fn.call(this, event) + } + } + } + + if (delegationFn) { + delegationFn = wrapFn(delegationFn) + } else { + handler = wrapFn(handler) + } + } + + const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) + const events = getEvent(element) + const handlers = events[typeEvent] || (events[typeEvent] = {}) + const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null) + + if (previousFn) { + previousFn.oneOff = previousFn.oneOff && oneOff + + return + } + + const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, '')) + const fn = delegation ? + bootstrapDelegationHandler(element, handler, delegationFn) : + bootstrapHandler(element, handler) + + fn.delegationSelector = delegation ? handler : null + fn.originalHandler = originalHandler + fn.oneOff = oneOff + fn.uidEvent = uid + handlers[uid] = fn + + element.addEventListener(typeEvent, fn, delegation) +} + +function removeHandler(element, events, typeEvent, handler, delegationSelector) { + const fn = findHandler(events[typeEvent], handler, delegationSelector) + + if (!fn) { + return + } + + element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)) + delete events[typeEvent][fn.uidEvent] +} + +function removeNamespacedHandlers(element, events, typeEvent, namespace) { + const storeElementEvent = events[typeEvent] || {} + + Object.keys(storeElementEvent).forEach(handlerKey => { + if (handlerKey.includes(namespace)) { + const event = storeElementEvent[handlerKey] + + removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) + } + }) +} + +function getTypeEvent(event) { + // allow to get the native events from namespaced events ('click.bs.button' --> 'click') + event = event.replace(stripNameRegex, '') + return customEvents[event] || event +} + +const EventHandler = { + on(element, event, handler, delegationFn) { + addHandler(element, event, handler, delegationFn, false) + }, + + one(element, event, handler, delegationFn) { + addHandler(element, event, handler, delegationFn, true) + }, + + off(element, originalTypeEvent, handler, delegationFn) { + if (typeof originalTypeEvent !== 'string' || !element) { + return + } + + const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) + const inNamespace = typeEvent !== originalTypeEvent + const events = getEvent(element) + const isNamespace = originalTypeEvent.startsWith('.') + + if (typeof originalHandler !== 'undefined') { + // Simplest case: handler is passed, remove that listener ONLY. + if (!events || !events[typeEvent]) { + return + } + + removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null) + return + } + + if (isNamespace) { + Object.keys(events).forEach(elementEvent => { + removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)) + }) + } + + const storeElementEvent = events[typeEvent] || {} + Object.keys(storeElementEvent).forEach(keyHandlers => { + const handlerKey = keyHandlers.replace(stripUidRegex, '') + + if (!inNamespace || originalTypeEvent.includes(handlerKey)) { + const event = storeElementEvent[keyHandlers] + + removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) + } + }) + }, + + trigger(element, event, args) { + if (typeof event !== 'string' || !element) { + return null + } + + const $ = getjQuery() + const typeEvent = getTypeEvent(event) + const inNamespace = event !== typeEvent + const isNative = nativeEvents.has(typeEvent) + + let jQueryEvent + let bubbles = true + let nativeDispatch = true + let defaultPrevented = false + let evt = null + + if (inNamespace && $) { + jQueryEvent = $.Event(event, args) + + $(element).trigger(jQueryEvent) + bubbles = !jQueryEvent.isPropagationStopped() + nativeDispatch = !jQueryEvent.isImmediatePropagationStopped() + 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] + } + }) + }) + } + + if (defaultPrevented) { + evt.preventDefault() + } + + if (nativeDispatch) { + element.dispatchEvent(evt) + } + + if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') { + jQueryEvent.preventDefault() + } + + return evt + } +} + +export default EventHandler -- cgit v1.2.3