mirror of
https://github.com/twbs/bootstrap.git
synced 2024-12-01 13:24:25 +01:00
317 lines
10 KiB
JavaScript
317 lines
10 KiB
JavaScript
/*!
|
|
* Bootstrap event-handler.js v4.3.1 (https://getbootstrap.com/)
|
|
* Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
*/
|
|
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./polyfill.js')) :
|
|
typeof define === 'function' && define.amd ? define(['./polyfill.js'], factory) :
|
|
(global = global || self, global.EventHandler = factory(global.Polyfill));
|
|
}(this, function (polyfill_js) { 'use strict';
|
|
|
|
/**
|
|
* --------------------------------------------------------------------------
|
|
* Bootstrap (v4.3.1): util/index.js
|
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
var _window = window,
|
|
jQuery = _window.jQuery; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
|
|
|
|
/**
|
|
* --------------------------------------------------------------------------
|
|
* Bootstrap (v4.3.1): dom/event-handler.js
|
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
/**
|
|
* ------------------------------------------------------------------------
|
|
* Constants
|
|
* ------------------------------------------------------------------------
|
|
*/
|
|
|
|
var namespaceRegex = /[^.]*(?=\..*)\.|.*/;
|
|
var stripNameRegex = /\..*/;
|
|
var keyEventRegex = /^key/;
|
|
var stripUidRegex = /::\d+$/;
|
|
var eventRegistry = {}; // Events storage
|
|
|
|
var uidEvent = 1;
|
|
var customEvents = {
|
|
mouseenter: 'mouseover',
|
|
mouseleave: 'mouseout'
|
|
};
|
|
var nativeEvents = ['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) {
|
|
var uid = getUidEvent(element);
|
|
element.uidEvent = uid;
|
|
eventRegistry[uid] = eventRegistry[uid] || {};
|
|
return eventRegistry[uid];
|
|
}
|
|
|
|
function fixEvent(event, element) {
|
|
// Add which for key events
|
|
if (event.which === null && keyEventRegex.test(event.type)) {
|
|
event.which = event.charCode === null ? event.keyCode : event.charCode;
|
|
}
|
|
|
|
event.delegateTarget = element;
|
|
}
|
|
|
|
function bootstrapHandler(element, fn) {
|
|
return function handler(event) {
|
|
fixEvent(event, element);
|
|
|
|
if (handler.oneOff) {
|
|
EventHandler.off(element, event.type, fn);
|
|
}
|
|
|
|
return fn.apply(element, [event]);
|
|
};
|
|
}
|
|
|
|
function bootstrapDelegationHandler(element, selector, fn) {
|
|
return function handler(event) {
|
|
var domElements = element.querySelectorAll(selector);
|
|
|
|
for (var target = event.target; target && target !== this; target = target.parentNode) {
|
|
for (var i = domElements.length; i--;) {
|
|
if (domElements[i] === target) {
|
|
fixEvent(event, target);
|
|
|
|
if (handler.oneOff) {
|
|
EventHandler.off(element, event.type, fn);
|
|
}
|
|
|
|
return fn.apply(target, [event]);
|
|
}
|
|
}
|
|
} // To please ESLint
|
|
|
|
|
|
return null;
|
|
};
|
|
}
|
|
|
|
function findHandler(events, handler, delegationSelector) {
|
|
if (delegationSelector === void 0) {
|
|
delegationSelector = null;
|
|
}
|
|
|
|
var uidEventList = Object.keys(events);
|
|
|
|
for (var i = 0, len = uidEventList.length; i < len; i++) {
|
|
var event = events[uidEventList[i]];
|
|
|
|
if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {
|
|
return event;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function normalizeParams(originalTypeEvent, handler, delegationFn) {
|
|
var delegation = typeof handler === 'string';
|
|
var originalHandler = delegation ? delegationFn : handler; // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
|
|
|
|
var typeEvent = originalTypeEvent.replace(stripNameRegex, '');
|
|
var custom = customEvents[typeEvent];
|
|
|
|
if (custom) {
|
|
typeEvent = custom;
|
|
}
|
|
|
|
var isNative = nativeEvents.indexOf(typeEvent) > -1;
|
|
|
|
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;
|
|
}
|
|
|
|
var _normalizeParams = normalizeParams(originalTypeEvent, handler, delegationFn),
|
|
delegation = _normalizeParams[0],
|
|
originalHandler = _normalizeParams[1],
|
|
typeEvent = _normalizeParams[2];
|
|
|
|
var events = getEvent(element);
|
|
var handlers = events[typeEvent] || (events[typeEvent] = {});
|
|
var previousFn = findHandler(handlers, originalHandler, delegation ? handler : null);
|
|
|
|
if (previousFn) {
|
|
previousFn.oneOff = previousFn.oneOff && oneOff;
|
|
return;
|
|
}
|
|
|
|
var uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''));
|
|
var 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) {
|
|
var 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) {
|
|
var storeElementEvent = events[typeEvent] || {};
|
|
Object.keys(storeElementEvent).forEach(function (handlerKey) {
|
|
if (handlerKey.indexOf(namespace) > -1) {
|
|
var event = storeElementEvent[handlerKey];
|
|
removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);
|
|
}
|
|
});
|
|
}
|
|
|
|
var EventHandler = {
|
|
on: function on(element, event, handler, delegationFn) {
|
|
addHandler(element, event, handler, delegationFn, false);
|
|
},
|
|
one: function one(element, event, handler, delegationFn) {
|
|
addHandler(element, event, handler, delegationFn, true);
|
|
},
|
|
off: function off(element, originalTypeEvent, handler, delegationFn) {
|
|
if (typeof originalTypeEvent !== 'string' || !element) {
|
|
return;
|
|
}
|
|
|
|
var _normalizeParams2 = normalizeParams(originalTypeEvent, handler, delegationFn),
|
|
delegation = _normalizeParams2[0],
|
|
originalHandler = _normalizeParams2[1],
|
|
typeEvent = _normalizeParams2[2];
|
|
|
|
var inNamespace = typeEvent !== originalTypeEvent;
|
|
var events = getEvent(element);
|
|
var isNamespace = originalTypeEvent.charAt(0) === '.';
|
|
|
|
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(function (elementEvent) {
|
|
removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1));
|
|
});
|
|
}
|
|
|
|
var storeElementEvent = events[typeEvent] || {};
|
|
Object.keys(storeElementEvent).forEach(function (keyHandlers) {
|
|
var handlerKey = keyHandlers.replace(stripUidRegex, '');
|
|
|
|
if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) {
|
|
var event = storeElementEvent[keyHandlers];
|
|
removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);
|
|
}
|
|
});
|
|
},
|
|
trigger: function trigger(element, event, args) {
|
|
if (typeof event !== 'string' || !element) {
|
|
return null;
|
|
}
|
|
|
|
var typeEvent = event.replace(stripNameRegex, '');
|
|
var inNamespace = event !== typeEvent;
|
|
var isNative = nativeEvents.indexOf(typeEvent) > -1;
|
|
var jQueryEvent;
|
|
var bubbles = true;
|
|
var nativeDispatch = true;
|
|
var defaultPrevented = false;
|
|
var evt = null;
|
|
|
|
if (inNamespace && typeof jQuery !== 'undefined') {
|
|
jQueryEvent = jQuery.Event(event, args);
|
|
jQuery(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 = polyfill_js.createCustomEvent(event, {
|
|
bubbles: bubbles,
|
|
cancelable: true
|
|
});
|
|
} // merge custom informations in our event
|
|
|
|
|
|
if (typeof args !== 'undefined') {
|
|
Object.keys(args).forEach(function (key) {
|
|
Object.defineProperty(evt, key, {
|
|
get: function get() {
|
|
return args[key];
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
if (defaultPrevented) {
|
|
evt.preventDefault();
|
|
|
|
if (!polyfill_js.defaultPreventedPreservedOnDispatch) {
|
|
Object.defineProperty(evt, 'defaultPrevented', {
|
|
get: function get() {
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (nativeDispatch) {
|
|
element.dispatchEvent(evt);
|
|
}
|
|
|
|
if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {
|
|
jQueryEvent.preventDefault();
|
|
}
|
|
|
|
return evt;
|
|
}
|
|
};
|
|
|
|
return EventHandler;
|
|
|
|
}));
|
|
//# sourceMappingURL=event-handler.js.map
|