fix(core): should support event.stopImmediatePropagation (#20469)

PR Close #20469
This commit is contained in:
JiaLi.Passion
2017-11-16 11:43:53 +09:00
committed by Miško Hevery
parent 1861e416a1
commit 997336b790
2 changed files with 72 additions and 1 deletions

View File

@ -35,6 +35,10 @@ const ANGULAR = 'ANGULAR';
const NATIVE_ADD_LISTENER = 'addEventListener';
const NATIVE_REMOVE_LISTENER = 'removeEventListener';
// use the same symbol string which is used in zone.js
const stopSymbol = '__zone_symbol__propagationStopped';
const stopMethodSymbol = '__zone_symbol__stopImmediatePropagation';
const blackListedEvents: string[] =
(typeof Zone !== 'undefined') && (Zone as any)[__symbol__('BLACK_LISTED_EVENTS')];
let blackListedMap: {[eventName: string]: string};
@ -81,6 +85,11 @@ const globalListener = function(event: Event) {
// itself or others
const copiedTasks = taskDatas.slice();
for (let i = 0; i < copiedTasks.length; i++) {
// if other listener call event.stopImmediatePropagation
// just break
if ((event as any)[stopSymbol] === true) {
break;
}
const taskData = copiedTasks[i];
if (taskData.zone !== Zone.current) {
// only use Zone.run when Zone.current not equals to stored zone
@ -94,7 +103,33 @@ const globalListener = function(event: Event) {
@Injectable()
export class DomEventsPlugin extends EventManagerPlugin {
constructor(@Inject(DOCUMENT) doc: any, private ngZone: NgZone) { super(doc); }
constructor(@Inject(DOCUMENT) doc: any, private ngZone: NgZone) {
super(doc);
this.patchEvent();
}
private patchEvent() {
if (!Event || !Event.prototype) {
return;
}
if ((Event.prototype as any)[stopMethodSymbol]) {
// already patched by zone.js
return;
}
const delegate = (Event.prototype as any)[stopMethodSymbol] =
Event.prototype.stopImmediatePropagation;
Event.prototype.stopImmediatePropagation = function() {
if (this) {
this[stopSymbol] = true;
}
// should call native delegate in case
// in some enviroment part of the application
// will not use the patched Event
delegate && delegate.apply(this, arguments);
};
}
// This plugin should come last in the list of plugins, because it accepts all
// events.