# document-register-element
**Repository Path**: mirrors_developit/document-register-element
## Basic Information
- **Project Name**: document-register-element
- **Description**: A stand-alone working lightweight version of the W3C Custom Elements specification
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-08
- **Last Updated**: 2026-07-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
document-register-element
=========================
A stand-alone working lightweight version of the [W3C Custom Elements](http://w3c.github.io/webcomponents/spec/custom/) specification.
[](https://travis-ci.org/WebReflection/document-register-element)
### How
`npm install document-register-element` should bring [build/document-register-element.js](build/document-register-element.js) inside the module folder.
Otherwise simply:
```html
```
on your head element and you should be good to go.
#### via CDN
Many thanks to [cdnjs](http://www.cdnjs.com) for hosting this script. Following an example on how to include it.
```html
```
### TL;DR does it work ?
If you [see the first clock ticking](http://webreflection.github.io/document-register-element/test/examples/x-clock.html), the TL;DR answer is yes.
### Usage Example
A basic HTML example page
```html
testing my-element
some content
```
with the following `my-element.js` content
```javascript
var MyElement = document.registerElement(
'my-element',
{
prototype: Object.create(
HTMLElement.prototype, {
createdCallback: {value: function() {
console.log('here I am ^_^ ');
console.log('with content: ', this.textContent);
}},
attachedCallback: {value: function() {
console.log('live on DOM ;-) ');
}},
detachedCallback: {value: function() {
console.log('leaving the DOM :-( )');
}},
attributeChangedCallback: {value: function(
name, previousValue, value
) {
if (previousValue == null) {
console.log(
'got a new attribute ', name,
' with value ', value
);
} else if (value == null) {
console.log(
'somebody removed ', name,
' its value was ', previousValue
);
} else {
console.log(
name,
' changed from ', previousValue,
' to ', value
);
}
}}
})
}
);
```
### Why
There are a [couple](http://webreflection.blogspot.co.uk/2014/07/a-w3c-custom-elements-alternative.html) of blog [posts](http://webreflection.blogspot.co.uk/2015/03/bringing-custom-elements-to-ie8.html) about this polyfill, and following the quick summary:
[document-register-element.js](build/document-register-element.js) is a stand alone polyfill which aim is to support as many browsers as possible, without requiring extra dependencies at all, and in about **3KB** minified and gzipped.
Add if you want [dom4](https://github.com/WebReflection/dom4#dom4) normalizer and you'll find yourself in a modern DOM environment that works reliably with today browsers with an eye always open on performance.
### Tested On
The [live test page](http://webreflection.github.io/document-register-element/test/) is here, containing all tests as listed in [the test file](test/document-register-element.js).
The following list of **desktop** browsers has been successfully tested:
* Chrome
* Firefox
* IE 8 or greater (please read about IE8 caveats)
* Safari
* Opera
The following list of **mobile** OS has been successfully tested:
* iOS 5.1 or greater
* Android 2.2 or greater
* FirefoxOS 1.1 or greater
* KindleFire 3 or greater
* Windows Phone 7 or greater
* Opera Mobile 12 or greater
* Blackberry OS 7* and OS 10
* webOS 2 or LG TV
* Samsung Bada OS 2 or greater
* NOKIA Asha with Express Browser
The good old [BB OS 7](http://us.blackberry.com/software/smartphones/blackberry-7-os.html) is the only one failing the test with `className` which is not notified as `attributeChanged` when it's changed. This means BB OS 7 will also fail with `id`, however changing `id` at runtime has never been a common or useful pattern.
### Common Issues + Caveat
Here a list of gotchas you might encounter when developing *CustomElement* components.
#### HTML{TABLE|ROW|INPUT|SELECT|others...}Element
As described in [issue 6](https://github.com/WebReflection/document-register-element/issues/6) it's not possible to fully inherit a table, input, select, or other special element behaviors.
```js
// This will NOT work as expected
document.registerElement(
'my-input',
{
prototype: Object.create(
HTMLInputElement.prototype
)
}
);
var mi = document.createElement('my-input');
```
The correct way to properly implement a custom input that will be also backward compatible is the following one:
```js
// This will NOT work as expected
document.registerElement(
'my-input',
{
extends: 'input', // <== IMPORTANT
prototype: Object.create(
HTMLInputElement.prototype
)
}
);
// how to create the input
var mi = document.createElement(
'input', // the extend
'my-input' // the enriched custom definition
);
```
Another approach is to use just a basic `HTMLElement` component and initialize its content at runtime.
```js
document.registerElement(
'my-input',
{
prototype: Object.create(
HTMLElement.prototype,
{
createdCallback: {value: function () {
// here the input
this.el = this.appendChild(
document.createElement('input')
);
}}
}
)
}
);
var mi = document.createElement('my-input');
```
In this case every method that wants to interact with the input will refer `this.el` instead of just `this`.
#### Using `innerHTML`
In order to avoid huge performance impact, native behavior overwrite problems and incompatibilities, there is now a [helper script](https://github.com/WebReflection/document-register-element/blob/master/build/innerHTML.max.js),
which aim is to make **off-line custom elements creation** possible using template strings instead of needing manual `document.createElement` replacements.
The helper is a simple `innerHTML` function that returns the given node, after setting `innerHTML` and, in case the polyfill is used, initialize nodes.
This helper is needed in order to be aligned with native implementations, but please remember that `createdCallback` could be asynchronous, even if triggered ASAP after injecting HTML through this function.
#### Changing the `style` property
If you change the style property via `node.style.cssText` or `node.style.backgroundColor = "red"` this change will most likely reflect through `node.getAttribute("style")`.
In order to prevent footguns inside `attributeChangedCallback` invocations causing potential stack overflows, the `style` property has been filtered starting from version `0.1.1`, also reflecting current native implementation where changing this special property won't invoke the callback.
(yes, even using `node.setAttribute("style", "value")` that you shouldn't ... just use `node.style.cssText = "value"` instead)
#### About IE8
Starting from version `0.2.0` there is an experimental support for IE8.
There is a specific file that needs to be loaded in IE8 only upfront, plus a sequence of polyfills
that will be simply ignored by every browser but downloaded in IE8.
Please check [base.html file](examples/base.html) in order to have a basic model to reuse in case you want to support IE8.
All tests pass and there is a [map component example](http://webreflection.github.io/document-register-element/test/examples/x-map.html) that already works in IE8 too.
Remember there are few things to consider when IE8 is a target but since it didn't cost many bytes
to have it in, I've decided to merge the logic and maintain only one file that will work in IE8 too.
#### IE8 caveats
* it's IE8
* all operations are batched and eventually executed ASAP but asynchronously. This behavior is closer to native Mutation Observers but might have some extra glitch in rendering time
* `className` is right now the only special attribute that reacts. Others might be implemented in the [dre-ie8-upfront-fix.js](src/dre-ie8-upfront-fix.js) file.
* in order to have node reacting to attributes changes, these must be live on the DOM
* if you are using `extends` when create a custom element, remember to minify the production code or wrap such reserved word in quotes