Skip to content
This repository has been archived by the owner on Feb 25, 2021. It is now read-only.

Commit

Permalink
Support non-bubbling events
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveSandersonMS committed May 1, 2018
1 parent 29908b1 commit 01a2dd9
Showing 1 changed file with 18 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { EventForDotNet, UIEventArgs } from './EventForDotNet';

const nonBubblingEvents = toLookup([
'abort', 'blur', 'change', 'error', 'focus', 'load', 'loadend', 'loadstart', 'mouseenter', 'mouseleave',
'progress', 'reset', 'scroll', 'submit', 'unload', 'DOMNodeInsertedIntoDocument', 'DOMNodeRemovedFromDocument'
]);

export interface OnEventCallback {
(event: Event, componentId: number, eventHandlerId: number, eventArgs: EventForDotNet<UIEventArgs>): void;
}
Expand Down Expand Up @@ -64,6 +69,7 @@ export class EventDelegator {
// Scan up the element hierarchy, looking for any matching registered event handlers
let candidateElement = evt.target as Element | null;
let eventArgs: EventForDotNet<UIEventArgs> | null = null; // Populate lazily
const eventIsNonBubbling = nonBubblingEvents.hasOwnProperty(evt.type);
while (candidateElement) {
if (candidateElement.hasOwnProperty(this.eventsCollectionKey)) {
const handlerInfos = candidateElement[this.eventsCollectionKey];
Expand All @@ -78,7 +84,7 @@ export class EventDelegator {
}
}

candidateElement = candidateElement.parentElement;
candidateElement = eventIsNonBubbling ? null : candidateElement.parentElement;
}
}
}
Expand All @@ -105,7 +111,11 @@ class EventInfoStore {
this.countByEventName[eventName]++;
} else {
this.countByEventName[eventName] = 1;
document.addEventListener(eventName, this.globalListener);

// To make delegation work with non-bubbling events, register a 'capture' listener.
// We preserve the non-bubbling behavior by only dispatching such events to the targeted element.
const useCapture = nonBubblingEvents.hasOwnProperty(eventName);
document.addEventListener(eventName, this.globalListener, useCapture);
}
}

Expand Down Expand Up @@ -154,3 +164,9 @@ interface EventHandlerInfo {
componentId: number;
eventHandlerId: number;
}

function toLookup(items: string[]): { [key: string]: boolean } {
const result = {};
items.forEach(value => { result[value] = true; });
return result;
}

0 comments on commit 01a2dd9

Please sign in to comment.