diff --git a/CHANGELOG.md b/CHANGELOG.md index 5526817f..cb42ed23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,14 +12,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased -### Changed - -### Added -* A `disconnectedCallback()` function was added (https://github.com/Polymer/lit-element/pull/213). - ### Changed * LitElement changed to a non-abstract class to be more compatible with the JavaScript mixin pattern -(https://github.com/Polymer/lit-element/issues/227). +([#227](https://github.com/Polymer/lit-element/issues/227)). +* Update lit-html dependency to ^0.12.0 ([#244](https://github.com/Polymer/lit-element/pull/244)), +* Passes the components `this` reference to lit-html as the `eventContext`, allowing unbound event listener methods. ([#244](https://github.com/Polymer/lit-element/pull/244)). +### Added +* A `disconnectedCallback()` method was added to UpdatingElement([#213](https://github.com/Polymer/lit-element/pull/213)). +* Added `@eventOptions()` decorator for setting event listener options on methods ([#244](https://github.com/Polymer/lit-element/pull/244)). + + ## [0.6.1] - 2018-09-17 diff --git a/README.md b/README.md index b2a8b644..b07e7668 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ and renders declaratively using `lit-html`. * expression: ``` html`
${this.disabled ? 'Off' : 'On'}
` ``` * property: ``` html`` ``` * attribute: ``` html`
` ``` - * event handler: ``` html`` ``` + * event handler: ``` html`` ``` ## Getting started diff --git a/package-lock.json b/package-lock.json index 4d4f8563..32d0aca1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1411,7 +1411,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } @@ -1720,7 +1720,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -1798,7 +1798,7 @@ }, "babel-helper-is-nodes-equiv": { "version": "0.0.1", - "resolved": "http://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", "dev": true }, @@ -2004,7 +2004,7 @@ }, "babel-preset-minify": { "version": "0.4.0-alpha.caaefb4c", - "resolved": "http://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.4.0-alpha.caaefb4c.tgz", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.4.0-alpha.caaefb4c.tgz", "integrity": "sha1-pQUsWVXdl9JGmbKB/amjAuqMGHE=", "dev": true, "requires": { @@ -2444,7 +2444,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -2527,7 +2527,7 @@ }, "cancel-token": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/cancel-token/-/cancel-token-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/cancel-token/-/cancel-token-0.1.1.tgz", "integrity": "sha1-wYGXZ0uxyEwdaTPr8V2NWlznm08=", "dev": true, "requires": { @@ -2648,7 +2648,7 @@ }, "cleankill": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/cleankill/-/cleankill-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/cleankill/-/cleankill-2.0.0.tgz", "integrity": "sha1-WYMN/ItBHVPccq0J1Fp46jMWGpE=", "dev": true }, @@ -2770,7 +2770,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -3217,7 +3217,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -3281,7 +3281,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -3585,7 +3585,7 @@ }, "express": { "version": "4.16.3", - "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { @@ -4382,7 +4382,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -4451,7 +4451,7 @@ }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { @@ -4783,7 +4783,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -5176,7 +5176,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -5456,9 +5456,9 @@ } }, "lit-html": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-0.11.4.tgz", - "integrity": "sha512-yfJUxQrRjhYo4cdz3Db9YlkHs9v+rTZA4fvE/dqCOrA1Q2Bmx52X2OtEgGQ+JhyCb6ddDTndLijZjsSoQ44G7Q==" + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-0.12.0.tgz", + "integrity": "sha512-NyFgq8yTlGEjUFQOmNnK/kj+ZdDVJzTwsLunNSewGiOns7SjuJi6ymCCqzZZ81uW2VwEmliMbOlFZc9QmOJPLA==" }, "load-json-file": { "version": "1.1.0", @@ -5616,7 +5616,7 @@ }, "lolex": { "version": "1.3.2", - "resolved": "http://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, @@ -5772,7 +5772,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -5881,7 +5881,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -5908,7 +5908,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -6073,7 +6073,7 @@ }, "chalk": { "version": "0.4.0", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { @@ -6605,7 +6605,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -6936,7 +6936,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -7087,7 +7087,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -7116,7 +7116,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -7562,7 +7562,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -7604,7 +7604,7 @@ "dependencies": { "debug": { "version": "2.1.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.1.3.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", "dev": true, "requires": { @@ -7833,7 +7833,7 @@ }, "sinon": { "version": "1.17.7", - "resolved": "http://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", "dev": true, "requires": { @@ -8200,7 +8200,7 @@ }, "stacky": { "version": "1.3.1", - "resolved": "http://registry.npmjs.org/stacky/-/stacky-1.3.1.tgz", + "resolved": "https://registry.npmjs.org/stacky/-/stacky-1.3.1.tgz", "integrity": "sha1-PxF+UYe5pz0j+HbWnwXIWxGAShI=", "dev": true, "requires": { @@ -8222,7 +8222,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -8235,7 +8235,7 @@ }, "lodash": { "version": "3.10.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, @@ -8494,7 +8494,7 @@ "dependencies": { "rimraf": { "version": "2.2.8", - "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", "dev": true, "optional": true @@ -9248,7 +9248,7 @@ }, "commander": { "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { @@ -9315,7 +9315,7 @@ }, "lodash": { "version": "3.10.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, @@ -9455,7 +9455,7 @@ }, "request": { "version": "2.85.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.85.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "dev": true, "requires": { @@ -9532,7 +9532,7 @@ "dependencies": { "@polymer/test-fixture": { "version": "0.0.3", - "resolved": "http://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-0.0.3.tgz", + "resolved": "https://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-0.0.3.tgz", "integrity": "sha1-REN1JpfU2Sk7vEEuoLXk00HxSdk=", "dev": true }, @@ -9573,7 +9573,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -9601,7 +9601,7 @@ }, "lodash": { "version": "3.10.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, diff --git a/package.json b/package.json index f3b4741a..98c60d25 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "typings": "lit-element.d.ts", "dependencies": { - "lit-html": "^0.11.4" + "lit-html": "^0.12.0" }, "publishConfig": { "access": "public" diff --git a/src/lib/decorators.ts b/src/lib/decorators.ts index 80c06bca..38e47a51 100644 --- a/src/lib/decorators.ts +++ b/src/lib/decorators.ts @@ -18,7 +18,7 @@ import {LitElement} from '../lit-element.js'; import {PropertyDeclaration, UpdatingElement} from './updating-element.js'; export type Constructor = { - new (...args: unknown[]): T + new (...args: any[]): T }; /** @@ -89,3 +89,35 @@ function _query(queryFn: (target: NodeSelector, selector: string) => T) { }); }; } + +/** + * Adds event listener options to a method used as an event listener in a + * lit-html template. + * + * @param options An object that specifis event listener options as accepted by + * `EventTarget#addEventListener` and `EventTarget#removeEventListener`. + * + * Current browsers support the `capture`, `passive`, and `once` options. See: + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters + * + * @example + * + * class MyElement { + * + * clicked = false; + * + * render() { + * return html`
`; + * } + * + * @eventOptions({capture: true}) + * _onClick(e) { + * this.clicked = true; + * } + * } + */ +export const eventOptions = (options: EventListenerOptions) => + (proto: any, name: string) => { + // This comment is here to fix a disagreement between formatter and linter + Object.assign(proto[name], options); + }; diff --git a/src/lit-element.ts b/src/lit-element.ts index 3c21b85c..b8ea547f 100644 --- a/src/lit-element.ts +++ b/src/lit-element.ts @@ -42,16 +42,16 @@ export class LitElement extends UpdatingElement { const templateResult = this.render() as any; if (templateResult instanceof TemplateResult) { (this.constructor as typeof LitElement) - .render(templateResult, this.renderRoot!, this.localName!); + .render(templateResult, this.renderRoot!, + {scopeName : this.localName!, eventContext : this}); } } /** - Invoked on each update to perform rendering tasks. This method must return a - lit-html TemplateResult. Setting properties inside this method will *not* - trigger the element to update. + * Invoked on each update to perform rendering tasks. This method must return + * a lit-html TemplateResult. Setting properties inside this method will *not* + * trigger the element to update. * @returns {TemplateResult} Must return a lit-html TemplateResult. */ protected render() {} - } diff --git a/src/test/lib/decorators_test.ts b/src/test/lib/decorators_test.ts index 30c265b8..50b789f4 100644 --- a/src/test/lib/decorators_test.ts +++ b/src/test/lib/decorators_test.ts @@ -12,6 +12,7 @@ * http://polymer.github.io/PATENTS.txt */ +import {eventOptions} from '../../lib/decorators.js'; import { customElement, html, @@ -120,4 +121,31 @@ suite('decorators', () => { assert.lengthOf(spans, 0); }); }); + + suite('@eventOptions', () => { + test('allows capturing listeners', async () => { + @customElement(generateElementName() as keyof HTMLElementTagNameMap) + class C extends LitElement { + eventPhase?: number; + + render() { + return html` +
+ `; + } + + @eventOptions({capture : true}) + onClick(e: Event) { + this.eventPhase = e.eventPhase; + } + } + + const c = new C(); + container.appendChild(c); + await c.updateComplete; + const button = c.shadowRoot!.querySelector('button')!; + button.click(); + assert.equal(c.eventPhase, Event.CAPTURING_PHASE); + }); + }); }); diff --git a/src/test/lit-element_test.ts b/src/test/lit-element_test.ts index 4da476ee..b96c6884 100644 --- a/src/test/lit-element_test.ts +++ b/src/test/lit-element_test.ts @@ -978,7 +978,7 @@ suite('LitElement', () => { render() { const attr = 'attr'; const prop = 'prop'; - const event = (e: Event) => { this._event = e; }; + const event = function(this: E, e: Event) { this._event = e; }; return html `
`; } @@ -995,6 +995,24 @@ suite('LitElement', () => { assert.equal(el._event, e); }); + test('event listeners are invoked with the right `this` value', async () => { + class E extends LitElement { + event?: Event; + + render() { return html`
`; } + + onTest(e: Event) { this.event = e; } + } + customElements.define(generateElementName(), E); + const el = new E(); + container.appendChild(el); + await el.updateComplete; + const div = el.shadowRoot!.querySelector('div')!; + const event = new Event('test'); + div.dispatchEvent(event); + assert.equal(el.event, event); + }); + test('`firstUpdated` called when element first updates', async () => { class E extends LitElement {