azure-devops-ui
Version:
React components for building web UI in Azure DevOps
138 lines (137 loc) • 5.74 kB
JavaScript
export class EventGroup {
constructor(parent) {
this.id = EventGroup.uniqueId++;
this.isDisposed = false;
this.parent = parent;
this.eventRecords = [];
}
static raise(target, eventName, eventArgs, bubbleEvent) {
let returnValue;
if (EventGroup.isElement(target)) {
const event = document.createEvent("HTMLEvents");
event.initEvent(eventName, bubbleEvent || false, true);
Object.assign(event, eventArgs);
}
else {
while (target && returnValue !== false) {
let events = target.__events__;
let eventRecords = events ? events[eventName] : null;
if (eventRecords) {
for (let id in eventRecords) {
if (eventRecords.hasOwnProperty(id)) {
let eventRecordList = eventRecords[id];
for (let listIndex = 0; returnValue !== false && listIndex < eventRecordList.length; listIndex++) {
let record = eventRecordList[listIndex];
if (record.objectCallback) {
returnValue = record.objectCallback.call(record.parent, eventArgs);
}
}
}
}
}
target = bubbleEvent ? target.parent : null;
}
}
return returnValue;
}
static isElement(target) {
return !!target && (!!target.addEventListener || (typeof HTMLElement !== "undefined" && target instanceof HTMLElement));
}
dispose() {
if (!this.isDisposed) {
this.isDisposed = true;
this.off();
this.parent = null;
}
}
on(target, eventName, callback) {
if (eventName.indexOf(",") > -1) {
let events = eventName.split(/[,]+/);
for (let event in events) {
this.on(target, event, callback);
}
}
else {
let parent = this.parent;
let eventRecord = {
target: target,
eventName: eventName,
parent: parent,
callback: callback
};
if (!target.__events__) {
target.__events__ = {};
}
let events = target.__events__;
if (!events[eventName]) {
events[eventName] = {};
}
if (!events[eventName][this.id]) {
events[eventName][this.id] = [];
}
events[eventName][this.id].push(eventRecord);
if (EventGroup.isElement(target)) {
let processElementEvent = (...args) => {
if (this.isDisposed) {
return;
}
let result = callback.apply(parent, args);
if (result === false && args[0]) {
let e = args[0];
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.cancelBubble = true;
}
return result;
};
eventRecord.elementCallback = processElementEvent;
if (target.addEventListener) {
target.addEventListener(eventName, processElementEvent);
}
}
else {
let processObjectEvent = (...args) => {
if (this.isDisposed) {
return;
}
return callback.apply(parent, args);
};
eventRecord.objectCallback = processObjectEvent;
}
this.eventRecords.push(eventRecord);
}
}
off(target, eventName, callback) {
// For instead of foreach
for (let i = 0; i < this.eventRecords.length; i++) {
let eventRecord = this.eventRecords[i];
if ((!target || target === eventRecord.target) &&
(!eventName || eventName === eventRecord.eventName) &&
(!callback || callback === eventRecord.callback)) {
let events = eventRecord.target.__events__;
let targetArrayLookup = events[eventRecord.eventName];
let targetArray = targetArrayLookup ? targetArrayLookup[this.id] : null;
if (targetArray) {
if (targetArray.length === 1 || !callback) {
delete events[eventRecord.eventName][this.id];
}
else {
targetArray.splice(targetArray.indexOf(eventRecord), 1);
}
// If there's no more event IDs attached, remove the eventName
if (Object.keys(events[eventRecord.eventName]).length === 0) {
delete events[eventRecord.eventName];
}
}
if (eventRecord.elementCallback) {
eventRecord.target.removeEventListener(eventRecord.eventName, eventRecord.elementCallback, eventRecord.options);
}
this.eventRecords.splice(i--, 1);
}
}
}
raise(eventName, eventArgs, bubbleEvent) {
return EventGroup.raise(this.parent, eventName, eventArgs, bubbleEvent);
}
}
EventGroup.uniqueId = 0;