Skip to content

Commit

Permalink
Adds passive/once to EventListenerOptions type
Browse files Browse the repository at this point in the history
Fixes #325.

Despite this supposedly being in TypeScirpt (microsoft/TypeScript#9548), it's not, so we augment the type here.

Also adds tests for `once` and `passive` options.
  • Loading branch information
Steven Orvell committed Dec 12, 2018
1 parent 01d51c8 commit 4339387
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 9 deletions.
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/lib/decorators.ts
Expand Up @@ -90,6 +90,15 @@ function _query<T>(queryFn: (target: NodeSelector, selector: string) => T) {
};
}

// TODO(sorvell): augment TypeScript's EventListenerOptions which does
// not include these options despite https://github.com/Microsoft/TypeScript/issues/9548
declare global {
interface EventListenerOptions {
passive?: boolean;
once?: boolean;
}
}

/**
* Adds event listener options to a method used as an event listener in a
* lit-html template.
Expand Down
107 changes: 106 additions & 1 deletion src/test/lib/decorators_test.ts
Expand Up @@ -22,6 +22,44 @@ import {
} from '../../lit-element.js';
import {generateElementName} from '../test-helpers.js';

let hasOptions;
const supportsOptions = (function() {
if (hasOptions !== undefined) {
return hasOptions;
}
const fn = () => {};
const event = 'foo';
hasOptions = false;
const options = {
get capture() {
hasOptions = true;
return true;
}
};
document.body.addEventListener(event, fn, options);
document.body.removeEventListener(event, fn, options);
return hasOptions;
})();

let hasPassive;
const supportsPassive = (function() {
if (hasPassive !== undefined) {
return hasPassive;
}
const fn = () => {};
const event = 'foo';
hasPassive = false;
const options = {
get passive() {
hasPassive = true;
return true;
}
};
document.body.addEventListener(event, fn, options);
document.body.removeEventListener(event, fn, options);
return hasPassive;
})();

const assert = chai.assert;

suite('decorators', () => {
Expand Down Expand Up @@ -123,7 +161,10 @@ suite('decorators', () => {
});

suite('@eventOptions', () => {
test('allows capturing listeners', async () => {
test('allows capturing listeners', async function() {
if (!supportsOptions) {
this.skip();
}
@customElement(generateElementName() as keyof HTMLElementTagNameMap)
class C extends LitElement {
eventPhase?: number;
Expand All @@ -147,5 +188,69 @@ suite('decorators', () => {
button.click();
assert.equal(c.eventPhase, Event.CAPTURING_PHASE);
});

test('allows once listeners', async function() {
if (!supportsOptions) {
this.skip();
}
@customElement(generateElementName() as keyof HTMLElementTagNameMap)
class C extends LitElement {

clicked = 0;

render() {
return html`
<div @click=${this.onClick}><button></button></div>
`;
}

@eventOptions({once : true})
onClick() {
this.clicked++;
}
}

const c = new C();
container.appendChild(c);
await c.updateComplete;
const button = c.shadowRoot!.querySelector('button')!;
button.click();
button.click();
assert.equal(c.clicked, 1);
});

test('allows passive listeners', async function() {
if (!supportsPassive) {
this.skip();
}
@customElement(generateElementName() as keyof HTMLElementTagNameMap)
class C extends LitElement {

defaultPrevented?: boolean;

render() {
return html`
<div @click=${this.onClick}><button></button></div>
`;
}

@eventOptions({passive : true})
onClick(e: Event) {
try {
e.preventDefault();
} catch (error) {
// no need to do anything
}
this.defaultPrevented = e.defaultPrevented;
}
}

const c = new C();
container.appendChild(c);
await c.updateComplete;
const button = c.shadowRoot!.querySelector('button')!;
button.click();
assert.isFalse(c.defaultPrevented);
});
});
});

0 comments on commit 4339387

Please sign in to comment.