@polymer/polymer
Version:
The Polymer library makes it easy to create your own web components. Give your element some markup and properties, and then use it on a site. Polymer provides features like dynamic templates and data binding to reduce the amount of boilerplate you need to
275 lines (254 loc) • 7.61 kB
HTML
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<script>
if (window.customElements) {
customElements.forcePolyfill = true;
}
window.ShadyDOM = {
force: true
};
</script>
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
</head>
<body>
<dom-module id="x-event-scoped">
<template>
<div id="scoped" on-composed="childHandler" on-scoped="childHandler"></div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-event-scoped',
properties: {
hostEvents: {
type: Array,
value: function() {
return [];
}
},
childEvents: {
type: Array,
value: function() {
return [];
}
}
},
listeners: {
'composed': 'hostHandler',
'scoped': 'hostHandler'
},
hostHandler: function(e) {
this.hostEvents.push({
target: e.target,
type: e.type,
path: e.composedPath()
});
},
childHandler: function(e) {
this.childEvents.push({
target: e.target,
type: e.type,
path: e.composedPath()
});
},
fireComposed: function() {
return this.fire('composed', null, {node: this.$.scoped});
},
fireScoped: function(){
return this.fire('scoped', null, {node: this.$.scoped, composed: false});
}
});
});
</script>
</dom-module>
<dom-module id="x-focus">
<template>
<style>
:host {
display: block;
}
</style>
<div id="child" on-focus="focusHandler"></div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-focus',
properties: {
events: {
type: Array,
value: function() {
return [];
}
}
},
listeners: {
focus: 'focusHandler'
},
focusHandler: function(e) {
this.events.push(e.target);
},
fireComposed: function() {
var ev = new Event('focus', {composed: true});
this.$.child.dispatchEvent(ev);
},
fireScoped: function() {
var ev = new Event('focus');
this.$.child.dispatchEvent(ev);
}
});
});
</script>
</dom-module>
<dom-module id="x-a">
<template>
<div id="child" on-foo="childFooHandler"></div>
<div id="child2"></div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-a',
listeners: {
'foo': 'fooHandler'
},
fooHandler: function(e) {
this.event = {target: e.target, relatedTarget: e.relatedTarget};
},
childFooHandler: function(e) {
this.childEvent = {target: e.target, relatedTarget: e.relatedTarget};
}
});
});
</script>
</dom-module>
<test-fixture id="scoped">
<template>
<x-event-scoped></x-event-scoped>
</template>
</test-fixture>
<test-fixture id="globalpatch">
<template>
<div></div>
</template>
</test-fixture>
<test-fixture id="focus">
<template>
<x-focus></x-focus>
</template>
</test-fixture>
<test-fixture id="relatedtarget">
<template>
<x-a id="one"></x-a>
<x-a id="two"></x-a>
</template>
</test-fixture>
<dom-module id="x-slot-inner">
</dom-module>
<test-fixture id="slot">
<template>
<x-slot>
<span class="target"></span>
</x-slot>
</template>
</test-fixture>
<script>
suite('ShadyDOM event patching', function() {
test('events retarget', function() {
var el = fixture('scoped');
el.fireComposed();
assert.equal(el.hostEvents[0].target, el);
assert.equal(el.childEvents[0].target, el.$.scoped);
});
test('event.composedPath is consistent', function() {
var el = fixture('scoped');
el.fireComposed();
assert.equal(el.hostEvents.length, el.childEvents.length);
});
test('event patching works on non Polymer elements', function() {
var el = fixture('globalpatch');
var path;
el.addEventListener('foo', function(e) {
path = e.composedPath();
});
var e = new Event('foo', {composed: true});
el.dispatchEvent(e);
assert.deepEqual([el, el.parentNode, document.body, document.documentElement, document, window], path);
});
test('`composed` flag controls event propagation through roots', function() {
var el = fixture('scoped');
el.fireScoped();
el.fireComposed();
assert.equal(el.hostEvents.length, 1);
assert.equal(el.hostEvents[0].type, 'composed');
assert.equal(el.childEvents.length, 2);
assert.equal(el.childEvents[0].type, 'scoped');
assert.equal(el.childEvents[1].type, 'composed');
});
test('composed focus and blur events retarget up tree', function() {
var el = fixture('focus');
el.fireComposed();
assert.equal(el.events.length, 2);
assert.equal(el.events[0], el.$.child);
assert.equal(el.events[1], el);
});
test('scoped focus and blur events do not retarget', function() {
var el = fixture('focus');
var e = new Event('focus');
if (e.isTrused !== false) {
// skip browser if we cannot distinguish
// native focus events from user created ones
this.skip();
}
el.fireScoped();
assert.equal(el.events.length, 1);
assert.equal(el.events[0], el.$.child);
});
test('composed relatedTarget retargets', function() {
var els = fixture('relatedtarget');
var a = els[0];
var b = els[1];
var ev = new MouseEvent('foo', {bubbles: true, composed: true, relatedTarget: b.$.child});
a.$.child.dispatchEvent(ev);
assert.property(a, 'childEvent');
assert.deepEqual(a.childEvent, {target: a.$.child, relatedTarget: b});
assert.property(a, 'event');
assert.deepEqual(a.event, {target: a, relatedTarget: b});
});
test('events do not fire if relatedtarget and target are the same node after retargeting', function() {
var els = fixture('relatedtarget');
var a = els[0];
var ev = new MouseEvent('foo', {bubbles: true, composed: true, relatedTarget: a.$.child2});
a.$.child.dispatchEvent(ev);
assert.property(a, 'childEvent');
assert.deepEqual(a.childEvent, {target: a.$.child, relatedTarget: a.$.child2});
assert.notProperty(a, 'event');
});
test('capturing event listeners fire correctly for focus and blur', function() {
var el = fixture('focus');
var timeStamp;
el.addEventListener('focus', function(e) {
timeStamp = e.timeStamp;
}, true);
el.fireComposed();
assert.ok(timeStamp);
assert.equal(el.events.length, 2);
assert.equal(el.events[0], el.$.child);
assert.equal(el.events[1], el);
});
});
</script>
</body>
</html>