0
0
mirror of https://github.com/twbs/bootstrap.git synced 2024-12-02 14:24:19 +01:00

improve event handler

This commit is contained in:
Johann-S 2019-02-14 21:19:10 +01:00 committed by XhmikosR
parent 30861cbc6d
commit e58b47cf74

View File

@ -1,6 +1,3 @@
import Polyfill from './polyfill'
import Util from '../util'
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v4.3.1): dom/eventHandler.js * Bootstrap (v4.3.1): dom/eventHandler.js
@ -8,6 +5,9 @@ import Util from '../util'
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import Polyfill from './polyfill'
import Util from '../util'
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* Constants * Constants
@ -78,10 +78,12 @@ function bootstrapHandler(element, fn) {
function bootstrapDelegationHandler(element, selector, fn) { function bootstrapDelegationHandler(element, selector, fn) {
return function handler(event) { return function handler(event) {
const domElements = element.querySelectorAll(selector) const domElements = element.querySelectorAll(selector)
for (let target = event.target; target && target !== this; target = target.parentNode) { for (let target = event.target; target && target !== this; target = target.parentNode) {
for (let i = domElements.length; i--;) { for (let i = domElements.length; i--;) {
if (domElements[i] === target) { if (domElements[i] === target) {
fixEvent(event, target) fixEvent(event, target)
if (handler.oneOff) { if (handler.oneOff) {
EventHandler.off(element, event.type, fn) EventHandler.off(element, event.type, fn)
} }
@ -97,12 +99,12 @@ function bootstrapDelegationHandler(element, selector, fn) {
} }
function findHandler(events, handler, delegationSelector = null) { function findHandler(events, handler, delegationSelector = null) {
for (const uid in events) { const uidList = Object.keys(events)
if (!Object.prototype.hasOwnProperty.call(events, uid)) {
continue
}
for (let i = 0; i < uidList.length; i++) {
const uid = uidList[i]
const event = events[uid] const event = events[uid]
if (event.originalHandler === handler && event.delegationSelector === delegationSelector) { if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {
return events[uid] return events[uid]
} }
@ -117,13 +119,14 @@ function normalizeParams(originalTypeEvent, handler, delegationFn) {
// allow to get the native events from namespaced events ('click.bs.button' --> 'click') // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
let typeEvent = originalTypeEvent.replace(stripNameRegex, '') let typeEvent = originalTypeEvent.replace(stripNameRegex, '')
const custom = customEvents[typeEvent] const custom = customEvents[typeEvent]
if (custom) { if (custom) {
typeEvent = custom typeEvent = custom
} }
const isNative = nativeEvents.indexOf(typeEvent) > -1 const isNative = nativeEvents.indexOf(typeEvent) > -1
if (!isNative) { if (!isNative) {
typeEvent = originalTypeEvent typeEvent = originalTypeEvent
} }
@ -142,13 +145,13 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
} }
const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn)
const events = getEvent(element) const events = getEvent(element)
const handlers = events[typeEvent] || (events[typeEvent] = {}) const handlers = events[typeEvent] || (events[typeEvent] = {})
const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null) const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null)
if (previousFn) { if (previousFn) {
previousFn.oneOff = previousFn.oneOff && oneOff previousFn.oneOff = previousFn.oneOff && oneOff
return return
} }
@ -166,6 +169,7 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
function removeHandler(element, events, typeEvent, handler, delegationSelector) { function removeHandler(element, events, typeEvent, handler, delegationSelector) {
const fn = findHandler(events[typeEvent], handler, delegationSelector) const fn = findHandler(events[typeEvent], handler, delegationSelector)
if (fn === null) { if (fn === null) {
return return
} }
@ -176,16 +180,15 @@ function removeHandler(element, events, typeEvent, handler, delegationSelector)
function removeNamespacedHandlers(element, events, typeEvent, namespace) { function removeNamespacedHandlers(element, events, typeEvent, namespace) {
const storeElementEvent = events[typeEvent] || {} const storeElementEvent = events[typeEvent] || {}
for (const handlerKey in storeElementEvent) {
if (!Object.prototype.hasOwnProperty.call(storeElementEvent, handlerKey)) {
continue
}
Object.keys(storeElementEvent)
.forEach((handlerKey) => {
if (handlerKey.indexOf(namespace) > -1) { if (handlerKey.indexOf(namespace) > -1) {
const event = storeElementEvent[handlerKey] const event = storeElementEvent[handlerKey]
removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)
} }
} })
} }
const EventHandler = { const EventHandler = {
@ -203,9 +206,9 @@ const EventHandler = {
} }
const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn) const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn)
const inNamespace = typeEvent !== originalTypeEvent const inNamespace = typeEvent !== originalTypeEvent
const events = getEvent(element) const events = getEvent(element)
const isNamespace = originalTypeEvent.charAt(0) === '.'
if (typeof originalHandler !== 'undefined') { if (typeof originalHandler !== 'undefined') {
// Simplest case: handler is passed, remove that listener ONLY. // Simplest case: handler is passed, remove that listener ONLY.
@ -217,29 +220,24 @@ const EventHandler = {
return return
} }
const isNamespace = originalTypeEvent.charAt(0) === '.'
if (isNamespace) { if (isNamespace) {
for (const elementEvent in events) { Object.keys(events)
if (!Object.prototype.hasOwnProperty.call(events, elementEvent)) { .forEach((elementEvent) => {
continue
}
removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1)) removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1))
} })
} }
const storeElementEvent = events[typeEvent] || {} const storeElementEvent = events[typeEvent] || {}
for (const keyHandlers in storeElementEvent) { Object.keys(storeElementEvent)
if (!Object.prototype.hasOwnProperty.call(storeElementEvent, keyHandlers)) { .forEach((keyHandlers) => {
continue
}
const handlerKey = keyHandlers.replace(stripUidRegex, '') const handlerKey = keyHandlers.replace(stripUidRegex, '')
if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) { if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) {
const event = storeElementEvent[keyHandlers] const event = storeElementEvent[keyHandlers]
removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector) removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)
} }
} })
}, },
trigger(element, event, args) { trigger(element, event, args) {
@ -250,13 +248,13 @@ const EventHandler = {
const typeEvent = event.replace(stripNameRegex, '') const typeEvent = event.replace(stripNameRegex, '')
const inNamespace = event !== typeEvent const inNamespace = event !== typeEvent
const isNative = nativeEvents.indexOf(typeEvent) > -1 const isNative = nativeEvents.indexOf(typeEvent) > -1
const $ = Util.jQuery const $ = Util.jQuery
let jQueryEvent
let jQueryEvent
let bubbles = true let bubbles = true
let nativeDispatch = true let nativeDispatch = true
let defaultPrevented = false let defaultPrevented = false
let evt = null
if (inNamespace && typeof $ !== 'undefined') { if (inNamespace && typeof $ !== 'undefined') {
jQueryEvent = $.Event(event, args) jQueryEvent = $.Event(event, args)
@ -267,7 +265,6 @@ const EventHandler = {
defaultPrevented = jQueryEvent.isDefaultPrevented() defaultPrevented = jQueryEvent.isDefaultPrevented()
} }
let evt = null
if (isNative) { if (isNative) {
evt = document.createEvent('HTMLEvents') evt = document.createEvent('HTMLEvents')
evt.initEvent(typeEvent, bubbles, true) evt.initEvent(typeEvent, bubbles, true)
@ -312,19 +309,4 @@ const EventHandler = {
} }
} }
/* istanbul ignore next */
// focusin and focusout polyfill
if (Polyfill.focusIn) {
(() => {
function listenerFocus(event) {
EventHandler.trigger(event.target, 'focusin')
}
function listenerBlur(event) {
EventHandler.trigger(event.target, 'focusout')
}
EventHandler.on(document, 'focus', 'input', listenerFocus)
EventHandler.on(document, 'blur', 'input', listenerBlur)
})()
}
export default EventHandler export default EventHandler