Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(event-manager): shadow dom event bubbling #758

Merged
5 changes: 4 additions & 1 deletion dist/amd/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3397,7 +3397,10 @@ define(['exports', 'aurelia-logging', 'aurelia-pal', 'aurelia-task-queue', 'aure
}
}

target = target.parentNode;
var parent = target.parentNode;
var parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion dist/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3302,7 +3302,10 @@ function handleDelegatedEvent(event) {
}
}

target = target.parentNode;
const parent = target.parentNode;
const parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion dist/commonjs/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3350,7 +3350,10 @@ function handleDelegatedEvent(event) {
}
}

target = target.parentNode;
var parent = target.parentNode;
var parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion dist/es2015/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3100,7 +3100,10 @@ function handleDelegatedEvent(event) {
}
}

target = target.parentNode;
const parent = target.parentNode;
const parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion dist/native-modules/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3310,7 +3310,10 @@ function handleDelegatedEvent(event) {
}
}

target = target.parentNode;
var parent = target.parentNode;
var parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion dist/system/aurelia-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,10 @@ System.register(['aurelia-logging', 'aurelia-pal', 'aurelia-task-queue', 'aureli
}
}

target = target.parentNode;
var parent = target.parentNode;
var parentIsShadowRoot = parent && parent.toString() === '[object ShadowRoot]';

target = parentIsShadowRoot ? parent.host : parent;
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ function handleDelegatedEvent(event) {
}
}

target = target.parentNode;
const parent = target.parentNode;
const parentIsShadowRoot = parent && parent instanceof ShadowRoot;
michaelw85 marked this conversation as resolved.
Show resolved Hide resolved

target = parentIsShadowRoot ? parent.host : parent;
michaelw85 marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
54 changes: 45 additions & 9 deletions test/event-manager.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,28 @@ describe('EventManager', () => {
});

describe('addEventListener', () => {
const em = new EventManager();
const one = document.createElement('div');
const two = document.createElement('div');
const three = document.createElement('div');

const oneClick = jasmine.createSpy('one-click');
const threeClick = jasmine.createSpy('three-click');
const oneDelegate = jasmine.createSpy('one-delegate');
const threeDelegate = jasmine.createSpy('three-delegate');
let em, one, two, three, shadowHost, shadowRoot, shadowButton, oneClick, threeClick, oneDelegate, threeDelegate;

beforeEach(() => {
em = new EventManager();
one = document.createElement('div');
two = document.createElement('div');
three = document.createElement('div');
shadowHost = document.createElement('div');
shadowButton = document.createElement('button');

oneClick = jasmine.createSpy('one-click');
threeClick = jasmine.createSpy('three-click');
oneDelegate = jasmine.createSpy('one-delegate');
threeDelegate = jasmine.createSpy('three-delegate');

document.body.appendChild(one);
one.appendChild(two);
two.appendChild(three);
one.appendChild(shadowHost);

shadowRoot = shadowHost.attachShadow({ mode: 'open' });
shadowRoot.appendChild(shadowButton);

em.addEventListener(one, 'click', oneClick, delegationStrategy.none);
em.addEventListener(three, 'click', threeClick, delegationStrategy.none);
Expand Down Expand Up @@ -120,6 +128,20 @@ describe('EventManager', () => {
threeClick.calls.reset();
});

it('bubbles properly out of shadow dom when not delegated with composed flag', () => {
michaelw85 marked this conversation as resolved.
Show resolved Hide resolved
const shadowButtonClickEvent = DOM.createCustomEvent('click', { bubbles: true, composed: true });
shadowButton.dispatchEvent(shadowButtonClickEvent);
expect(oneClick).toHaveBeenCalledWith(shadowButtonClickEvent);
oneClick.calls.reset();
});

it('should not bubble out of shadow dom when not delegated without composed flag', () => {
const shadowButtonClickEvent = DOM.createCustomEvent('click', { bubbles: true });
shadowButton.dispatchEvent(shadowButtonClickEvent);
expect(oneClick).not.toHaveBeenCalledWith(shadowButtonClickEvent);
oneClick.calls.reset();
});

it('bubbles properly when delegated', () => {
const threeDelegateEvent = DOM.createCustomEvent('delegate', { bubbles: true });
three.dispatchEvent(threeDelegateEvent);
Expand All @@ -143,6 +165,20 @@ describe('EventManager', () => {
threeDelegate.calls.reset();
});

it('bubbles properly out of shadow dom when delegated with composed flag', () => {
const shadowButtonDelegateEvent = DOM.createCustomEvent('delegate', { bubbles: true, composed: true });
shadowButton.dispatchEvent(shadowButtonDelegateEvent);
expect(oneDelegate).toHaveBeenCalledWith(shadowButtonDelegateEvent);
oneDelegate.calls.reset();
});

it('should not bubble out of shadow dom when delegated without composed flag', () => {
const shadowButtonDelegateEvent = DOM.createCustomEvent('delegate', { bubbles: true });
shadowButton.dispatchEvent(shadowButtonDelegateEvent);
expect(oneDelegate).not.toHaveBeenCalledWith(shadowButtonDelegateEvent);
oneDelegate.calls.reset();
});

it('stops bubbling when asked', () => {
let wasCalled = false;
let stopDelegate = (event) => {
Expand Down