Слияние кода завершено, страница обновится автоматически
import { action } from 'mobx';
import isObject from 'lodash/isObject';
import noop from 'lodash/noop';
type EventTarget = { addEventListener?: Function; removeEventListener?: Function; attachEvent?: Function; detachEvent?: Function };
type EventListenerOrEventListenerObject = Function | { handleEvent: Function };
export type Handler = [EventListenerOrEventListenerObject, EventListenerOptions | AddEventListenerOptions | boolean, Function];
function on(el: EventTarget, eventName: string, handle: Handler, handles: Handler[]): void {
if (el.addEventListener) {
const [fn, options] = handle;
el.addEventListener(eventName, fn, options);
} else {
const delegates: Function[] = [];
handles.forEach(([, , delegateFn]) => {
if (el.detachEvent) {
el.detachEvent(`on${eventName}`, delegateFn);
delegates.unshift(delegateFn);
}
});
delegates.forEach(delegateFn => {
if (el.attachEvent) {
el.attachEvent(`on${eventName}`, delegateFn);
}
});
}
}
function off(el: EventTarget, eventName: string, handle: Handler): void {
const [fn, options, delegateFn] = handle;
if (el.removeEventListener) {
el.removeEventListener(eventName, fn, options);
} else if (el.detachEvent) {
el.detachEvent(`on${eventName}`, delegateFn);
}
}
function isEventListenerOptions(options?: EventListenerOptions | boolean): options is EventListenerOptions {
return isObject(options);
}
function isAddEventListenerOptions(options?: EventListenerOptions | boolean): options is AddEventListenerOptions {
return isEventListenerOptions(options) && ('once' in options || 'passive' in options);
}
function getCapture(options: EventListenerOptions | boolean): boolean {
return isEventListenerOptions(options) ? options.capture || false : options;
}
function isSameHandler(handle: Handler, other: Handler): boolean {
const [handleFn, handleOption] = handle;
const [otherFn, otherOption] = other;
return handleFn === otherFn && getCapture(handleOption) === getCapture(otherOption);
}
function callHandler(events: Handler[], handle: Handler, ...rest): any {
const [, options, delegateFn] = handle;
if (isAddEventListenerOptions(options) && options.once) {
const index = events.indexOf(handle);
if (index !== -1) {
events.splice(index, 1);
}
}
return delegateFn(...rest);
}
function delegate(fn: EventListenerOrEventListenerObject): Function {
if ('handleEvent' in fn) {
return (...rest) => fn.handleEvent(...rest);
}
return (...rest) => fn(...rest);
}
export default class EventManager {
events: { [eventName: string]: Handler[] } = {};
el?: EventTarget | undefined | null;
constructor(el?: EventTarget | undefined | null) {
this.setTarget(el);
}
setTarget(el?: EventTarget | undefined | null): EventManager {
this.el = el;
return this;
}
addEventListener(eventName: string, fn: EventListenerOrEventListenerObject, options: AddEventListenerOptions | boolean = false): EventManager {
eventName = eventName.toLowerCase();
const events: Handler[] = this.events[eventName] || [];
const index = events.findIndex((handle) => isSameHandler(handle, [fn, options, noop]));
if (index === -1) {
const newHandle: Handler = [fn, options, delegate(fn)];
if (getCapture(options)) {
const captureIndex = events.findIndex(([, handleOptions]) => !getCapture(handleOptions));
if (captureIndex === -1) {
events.push(newHandle);
} else {
events.splice(captureIndex, 0, newHandle);
}
} else {
events.push(newHandle);
}
this.events[eventName] = events;
const { el } = this;
if (el) {
on(el, eventName, newHandle, events);
}
}
return this;
}
removeEventListener(eventName: string, fn?: EventListenerOrEventListenerObject, options: EventListenerOptions | boolean = false): EventManager {
eventName = eventName.toLowerCase();
const events: Handler[] = this.events[eventName];
if (events) {
const { el } = this;
if (fn) {
const index = events.findIndex(handle => isSameHandler(handle, [fn, options, noop]));
if (index !== -1) {
if (el) {
off(el, eventName, events[index]);
}
events.splice(index, 1);
}
} else {
this.events[eventName] = el
? (this.events[eventName] || []).filter((handle) => {
off(el, eventName, handle);
return false;
})
: [];
}
}
return this;
}
@action
fireEventSync(eventName: string, ...rest: any[]): boolean {
const events: Handler[] | undefined = this.events[eventName.toLowerCase()];
return events ? [...events].every(handle => callHandler(events, handle, ...rest) !== false) : true;
}
@action
fireEvent(eventName: string, ...rest: any[]): Promise<boolean> {
const events: Handler[] | undefined = this.events[eventName.toLowerCase()];
return events
? Promise.all([...events].map((handle) => callHandler(events, handle, ...rest))).then(all =>
all.every(result => result !== false),
)
: Promise.resolve(true);
}
clear(): EventManager {
if (this.el) {
Object.keys(this.events).forEach(eventName => this.removeEventListener(eventName));
}
this.events = {};
return this;
}
}
export function preventDefault(e) {
e.preventDefault();
}
export function stopPropagation(e) {
e.stopPropagation();
}
export function stopEvent(e) {
preventDefault(e);
stopPropagation(e);
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )