1
0
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:
Johann-S
2017-08-22 18:47:54 +02:00
committed by XhmikosR
parent 744071040e
commit 00ca781171

View File

@@ -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
} }
} }