mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-28 12:55:48 +08:00
fix(jqLite): fix event.stopImmediatePropagation() so it works as expected
jqLite doesn't override the default implementation of event.stopImmediatePropagation() and so it doesn't work as expected, i.e, it doesn't prevent the rest of the event handlers from being executed. Closes #4833
This commit is contained in:
committed by
Michał Gołębiowski
parent
19871d28cf
commit
30354c58fe
@@ -694,7 +694,6 @@ forEach({
|
||||
|
||||
function createEventHandler(element, events) {
|
||||
var eventHandler = function (event, type) {
|
||||
|
||||
// jQuery specific api
|
||||
event.isDefaultPrevented = function() {
|
||||
return event.defaultPrevented;
|
||||
@@ -705,13 +704,34 @@ function createEventHandler(element, events) {
|
||||
|
||||
if (!eventFnsLength) return;
|
||||
|
||||
if (isUndefined(event.immediatePropagationStopped)) {
|
||||
var originalStopImmediatePropagation = event.stopImmediatePropagation;
|
||||
event.stopImmediatePropagation = function() {
|
||||
event.immediatePropagationStopped = true;
|
||||
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (originalStopImmediatePropagation) {
|
||||
originalStopImmediatePropagation.call(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
event.isImmediatePropagationStopped = function() {
|
||||
return event.immediatePropagationStopped === true;
|
||||
};
|
||||
|
||||
// Copy event handlers in case event handlers array is modified during execution.
|
||||
if ((eventFnsLength > 1)) {
|
||||
eventFns = shallowCopy(eventFns);
|
||||
}
|
||||
|
||||
for (var i = 0; i < eventFnsLength; i++) {
|
||||
eventFns[i].call(element, event);
|
||||
if (!event.isImmediatePropagationStopped()) {
|
||||
eventFns[i].call(element, event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -912,11 +932,12 @@ forEach({
|
||||
var eventFns = events && events[eventName];
|
||||
|
||||
if (eventFns) {
|
||||
|
||||
// Create a dummy event to pass to the handlers
|
||||
dummyEvent = {
|
||||
preventDefault: function() { this.defaultPrevented = true; },
|
||||
isDefaultPrevented: function() { return this.defaultPrevented === true; },
|
||||
stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
|
||||
isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
|
||||
stopPropagation: noop,
|
||||
type: eventName,
|
||||
target: element
|
||||
@@ -932,9 +953,10 @@ forEach({
|
||||
handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
|
||||
|
||||
forEach(eventFnsCopy, function(fn) {
|
||||
fn.apply(element, handlerArgs);
|
||||
if (!dummyEvent.isImmediatePropagationStopped()) {
|
||||
fn.apply(element, handlerArgs);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}, function(fn, name){
|
||||
|
||||
@@ -1102,6 +1102,58 @@ describe('jqLite', function() {
|
||||
browserTrigger(a, 'click');
|
||||
});
|
||||
|
||||
it('should stop triggering handlers when stopImmediatePropagation is called', function() {
|
||||
var element = jqLite(a),
|
||||
clickSpy1 = jasmine.createSpy('clickSpy1'),
|
||||
clickSpy2 = jasmine.createSpy('clickSpy2').andCallFake(function(event) { event.stopImmediatePropagation(); }),
|
||||
clickSpy3 = jasmine.createSpy('clickSpy3'),
|
||||
clickSpy4 = jasmine.createSpy('clickSpy4');
|
||||
|
||||
element.on('click', clickSpy1);
|
||||
element.on('click', clickSpy2);
|
||||
element.on('click', clickSpy3);
|
||||
element[0].addEventListener('click', clickSpy4);
|
||||
|
||||
browserTrigger(element, 'click');
|
||||
|
||||
expect(clickSpy1).toHaveBeenCalled();
|
||||
expect(clickSpy2).toHaveBeenCalled();
|
||||
expect(clickSpy3).not.toHaveBeenCalled();
|
||||
expect(clickSpy4).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should execute stopPropagation when stopImmediatePropagation is called', function() {
|
||||
var element = jqLite(a),
|
||||
clickSpy = jasmine.createSpy('clickSpy');
|
||||
|
||||
clickSpy.andCallFake(function(event) {
|
||||
spyOn(event, 'stopPropagation');
|
||||
event.stopImmediatePropagation();
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
element.on('click', clickSpy);
|
||||
|
||||
browserTrigger(element, 'click');
|
||||
expect(clickSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should have event.isImmediatePropagationStopped method', function() {
|
||||
var element = jqLite(a),
|
||||
clickSpy = jasmine.createSpy('clickSpy');
|
||||
|
||||
clickSpy.andCallFake(function(event) {
|
||||
expect(event.isImmediatePropagationStopped()).toBe(false);
|
||||
event.stopImmediatePropagation();
|
||||
expect(event.isImmediatePropagationStopped()).toBe(true);
|
||||
});
|
||||
|
||||
element.on('click', clickSpy);
|
||||
|
||||
browserTrigger(element, 'click');
|
||||
expect(clickSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('mouseenter-mouseleave', function() {
|
||||
var root, parent, sibling, child, log;
|
||||
|
||||
@@ -1784,7 +1836,6 @@ describe('jqLite', function() {
|
||||
expect(event.isDefaultPrevented()).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it('should support handlers that deregister themselves', function() {
|
||||
var element = jqLite('<a>poke</a>'),
|
||||
clickSpy = jasmine.createSpy('click'),
|
||||
@@ -1821,6 +1872,37 @@ describe('jqLite', function() {
|
||||
expect(actualEvent.target).toEqual(element[0]);
|
||||
expect(actualEvent.type).toEqual('click');
|
||||
});
|
||||
|
||||
it('should stop triggering handlers when stopImmediatePropagation is called', function () {
|
||||
var element = jqLite(a),
|
||||
clickSpy1 = jasmine.createSpy('clickSpy1'),
|
||||
clickSpy2 = jasmine.createSpy('clickSpy2').andCallFake(function(event) { event.stopImmediatePropagation(); }),
|
||||
clickSpy3 = jasmine.createSpy('clickSpy3');
|
||||
|
||||
element.on('click', clickSpy1);
|
||||
element.on('click', clickSpy2);
|
||||
element.on('click', clickSpy3);
|
||||
|
||||
element.triggerHandler('click');
|
||||
|
||||
expect(clickSpy1).toHaveBeenCalled();
|
||||
expect(clickSpy2).toHaveBeenCalled();
|
||||
expect(clickSpy3).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should have event.isImmediatePropagationStopped method', function() {
|
||||
var element = jqLite(a),
|
||||
clickSpy = jasmine.createSpy('clickSpy'),
|
||||
event;
|
||||
|
||||
element.on('click', clickSpy);
|
||||
element.triggerHandler('click');
|
||||
event = clickSpy.mostRecentCall.args[0];
|
||||
|
||||
expect(event.isImmediatePropagationStopped()).toBe(false);
|
||||
event.stopImmediatePropagation();
|
||||
expect(event.isImmediatePropagationStopped()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user