mirror of
https://github.com/twbs/bootstrap.git
synced 2025-01-28 20:52:21 +01:00
Add namespaced events
This commit is contained in:
parent
744071040e
commit
00ca781171
@ -57,38 +57,122 @@ if (!window.Event || typeof window.Event !== 'function') {
|
||||
window.Event.prototype = origEvent.prototype
|
||||
}
|
||||
|
||||
const namespaceRegex = /[^.]*(?=\..*)\.|.*/
|
||||
const stripNameRegex = /\..*/
|
||||
|
||||
// Events storage
|
||||
const eventRegistry = {}
|
||||
let uidEvent = 1
|
||||
|
||||
function getUidEvent(element, uid) {
|
||||
return element.uidEvent = uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++
|
||||
}
|
||||
|
||||
function getEvent(element) {
|
||||
const uid = getUidEvent(element)
|
||||
return eventRegistry[uid] = eventRegistry[uid] || {}
|
||||
}
|
||||
|
||||
const nativeEvents =
|
||||
`click,dblclick,mouseup,mousedown,contextmenu,
|
||||
'mousewheel,DOMMouseScroll,
|
||||
'mouseover,mouseout,mousemove,selectstart,selectend,
|
||||
'keydown,keypress,keyup,
|
||||
'orientationchange,
|
||||
'touchstart,touchmove,touchend,touchcancel,
|
||||
'gesturestart,gesturechange,gestureend,
|
||||
'focus,blur,change,reset,select,submit,
|
||||
'load,unload,beforeunload,resize,move,DOMContentLoaded,readystatechange,
|
||||
'error,abort,scroll`.split(',')
|
||||
|
||||
function bootstrapHandler(element, fn) {
|
||||
return function (event) {
|
||||
return fn.apply(element, [event])
|
||||
}
|
||||
}
|
||||
|
||||
const EventHandler = {
|
||||
on(element, event, handler) {
|
||||
if (typeof event !== 'string' || typeof element === 'undefined') {
|
||||
on(element, originalTypeEvent, handler) {
|
||||
if (typeof originalTypeEvent !== 'string' ||
|
||||
(typeof element === 'undefined' || element === null)) {
|
||||
return
|
||||
}
|
||||
element.addEventListener(event, handler, false)
|
||||
|
||||
// allow to get the native events from namespaced events ('click.bs.button' --> 'click')
|
||||
let typeEvent = originalTypeEvent.replace(stripNameRegex, '')
|
||||
const isNative = nativeEvents.indexOf(typeEvent) > -1
|
||||
if (!isNative) {
|
||||
typeEvent = originalTypeEvent
|
||||
}
|
||||
const events = getEvent(element)
|
||||
const handlers = events[typeEvent] || (events[typeEvent] = {})
|
||||
const uid = getUidEvent(handler, originalTypeEvent.replace(namespaceRegex, ''))
|
||||
// TODO : Handle multi events on one element
|
||||
if (handlers[uid]) {
|
||||
return
|
||||
}
|
||||
|
||||
const fn = bootstrapHandler(element, handler)
|
||||
handlers[uid] = fn
|
||||
handler.uidEvent = uid
|
||||
element.addEventListener(typeEvent, fn, false)
|
||||
},
|
||||
|
||||
one(element, event, handler) {
|
||||
const complete = () => {
|
||||
/* eslint func-style: off */
|
||||
handler()
|
||||
element.removeEventListener(event, complete, false)
|
||||
function complete(e) {
|
||||
const typeEvent = event.replace(stripNameRegex, '')
|
||||
const events = getEvent(element)
|
||||
if (!events || !events[typeEvent]) {
|
||||
return
|
||||
}
|
||||
const uidEvent = handler.uidEvent
|
||||
const fn = events[typeEvent][uidEvent]
|
||||
fn.apply(element, [e])
|
||||
EventHandler.off(element, event, handler)
|
||||
}
|
||||
EventHandler.on(element, event, complete)
|
||||
},
|
||||
|
||||
trigger(element, event) {
|
||||
if (typeof event !== 'string' || typeof element === 'undefined') {
|
||||
return null
|
||||
off(element, originalTypeEvent, handler) {
|
||||
if (typeof originalTypeEvent !== 'string' ||
|
||||
(typeof element === 'undefined' || element === null)) {
|
||||
return
|
||||
}
|
||||
|
||||
const eventToDispatch = new CustomEvent(event, {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
})
|
||||
const typeEvent = originalTypeEvent.replace(stripNameRegex, '')
|
||||
const events = getEvent(element)
|
||||
if (!events || !events[typeEvent]) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add a function 'isDefaultPrevented'
|
||||
eventToDispatch.isDefaultPrevented = () => eventToDispatch.defaultPrevented
|
||||
element.dispatchEvent(eventToDispatch)
|
||||
const uidEvent = handler.uidEvent
|
||||
const fn = events[typeEvent][uidEvent]
|
||||
element.removeEventListener(typeEvent, fn, false)
|
||||
delete events[typeEvent][uidEvent]
|
||||
},
|
||||
|
||||
return eventToDispatch
|
||||
trigger(element, event) {
|
||||
if (typeof event !== 'string' ||
|
||||
(typeof element === 'undefined' || element === null)) {
|
||||
return null
|
||||
}
|
||||
const typeEvent = event.replace(stripNameRegex, '')
|
||||
const isNative = nativeEvents.indexOf(typeEvent) > -1
|
||||
let returnedEvent = null
|
||||
if (isNative) {
|
||||
const evt = document.createEvent('HTMLEvents')
|
||||
evt.initEvent(typeEvent, true, true)
|
||||
element.dispatchEvent(evt)
|
||||
returnedEvent = evt
|
||||
} else {
|
||||
const eventToDispatch = new CustomEvent(event, {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
})
|
||||
element.dispatchEvent(eventToDispatch)
|
||||
returnedEvent = eventToDispatch
|
||||
}
|
||||
return returnedEvent
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user