mirror of
https://github.com/twbs/bootstrap.git
synced 2025-08-16 10:34:07 +02:00
Add namespaced events
This commit is contained in:
@@ -57,38 +57,122 @@ if (!window.Event || typeof window.Event !== 'function') {
|
|||||||
window.Event.prototype = origEvent.prototype
|
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 = {
|
const EventHandler = {
|
||||||
on(element, event, handler) {
|
on(element, originalTypeEvent, handler) {
|
||||||
if (typeof event !== 'string' || typeof element === 'undefined') {
|
if (typeof originalTypeEvent !== 'string' ||
|
||||||
|
(typeof element === 'undefined' || element === null)) {
|
||||||
return
|
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) {
|
one(element, event, handler) {
|
||||||
const complete = () => {
|
function complete(e) {
|
||||||
/* eslint func-style: off */
|
const typeEvent = event.replace(stripNameRegex, '')
|
||||||
handler()
|
const events = getEvent(element)
|
||||||
element.removeEventListener(event, complete, false)
|
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)
|
EventHandler.on(element, event, complete)
|
||||||
},
|
},
|
||||||
|
|
||||||
trigger(element, event) {
|
off(element, originalTypeEvent, handler) {
|
||||||
if (typeof event !== 'string' || typeof element === 'undefined') {
|
if (typeof originalTypeEvent !== 'string' ||
|
||||||
return null
|
(typeof element === 'undefined' || element === null)) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const typeEvent = originalTypeEvent.replace(stripNameRegex, '')
|
||||||
|
const events = getEvent(element)
|
||||||
|
if (!events || !events[typeEvent]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const uidEvent = handler.uidEvent
|
||||||
|
const fn = events[typeEvent][uidEvent]
|
||||||
|
element.removeEventListener(typeEvent, fn, false)
|
||||||
|
delete events[typeEvent][uidEvent]
|
||||||
|
},
|
||||||
|
|
||||||
|
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, {
|
const eventToDispatch = new CustomEvent(event, {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
cancelable: true
|
cancelable: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add a function 'isDefaultPrevented'
|
|
||||||
eventToDispatch.isDefaultPrevented = () => eventToDispatch.defaultPrevented
|
|
||||||
element.dispatchEvent(eventToDispatch)
|
element.dispatchEvent(eventToDispatch)
|
||||||
|
returnedEvent = eventToDispatch
|
||||||
return eventToDispatch
|
}
|
||||||
|
return returnedEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user