UNPKG

2.68 kBMarkdownView Raw
1# Custom Elements with Builtin Extends
2
3[![Build Status](https://travis-ci.com/ungap/custom-elements-builtin.svg?branch=master)](https://travis-ci.com/ungap/custom-elements-builtin) ![WebReflection status](https://offline.report/status/webreflection.svg)
4
5Brings builtin extends to browsers that already have `customElements` (i.e. Safari).
6
7See [document-register-element](https://github.com/WebReflection/document-register-element) to polyfill upfront all other legacy browsers too.
8
9```js
10customElements.define(
11 'my-button',
12 class MyButton extends HTMLButtonElement {
13 static get observedAttributes() { return ['color']; }
14 attributeChangedCallback(name, oldValue, newValue, nsValue) {
15 this.style.color = newValue;
16 }
17 connectedCallback() {
18 this.addEventListener('click', this);
19 }
20 disconnectedCallback() {
21 this.removeEventListener('click', this);
22 }
23 handleEvent(event) {
24 const next = this.nextElementSibling ||
25 this.parentNode.appendChild(
26 document.createElement('div')
27 );
28 next.textContent = `${event.type} @ ${new Date}`;
29 }
30 },
31 {'extends': 'button'}
32);
33```
34
35 * CDN via https://unpkg.com/@ungap/custom-elements-builtin
36 * ESM via `import iterator from '@ungap/custom-elements-builtin'`
37 * CJS via `const iterator = require('@ungap/custom-elements-builtin')`
38
39[Live test](https://ungap.github.io/custom-elements-builtin/test/)
40
41## Constructor Caveat
42
43You cannot use the `constructor` in any meaningful way if you want to ensure API consistency.
44
45Create new elements via `document.createElement('button', {is: 'my-button'})` but do not use `new MyButton` or incompatible browsers will throw right away because they made `HTMLButtonElement` and all others not usable as classes.
46
47If you need a reliable entry point to setup your custom builtins use the `connectedCallback` method instead of the `constructor` so you're also sure all attributes are eventually already known and you'll have full control.
48
49Alternatively, use a `WeakSet` to optionally invoke a setup.
50
51```js
52const initialized = new WeakSet;
53const setup = node => {
54 initialized.add(node);
55 node.live = true;
56};
57class MyButton extends HTMLButtonElement {
58 connectedCallback() {
59 if (!initialized.has(this))
60 setup(this);
61 // anything else
62 }
63}
64```
65
66You can do the same at the beginning of `attributeChangedCallback`.
67
68### Compatible with ...
69
70Any engine that supports genuine ES2015 syntax and the following features:
71
72 * global `MutationObserver`, `customElements`, and `Promise`
73 * `assign`, `create`, `defineProperties`, and `setPrototypeOf` from the `Object`