@@ -8,12 +8,12 @@ layout: single
8
8
tags : ['Custom Elements', 'Shadow DOM', 'Template']
9
9
---
10
10
11
- HTML is the most important factor for the web platform. It provides a various
12
- low level features to structure sites and apps. But it also is easy to invite a
11
+ HTML is the most important factor for the web platform. It provides various low
12
+ level features to structure sites and apps. But it also is easy to end up with
13
13
div soup once you start implementing a complex component using native HTML tags.
14
- What if the web platform allows you to create your original component? What if
15
- you can give it an arbitrary tag name? What if you can extend features of an
16
- existing HTML tag?
14
+ What if the web platform could allow you to create your original component?
15
+ What if you can give it an arbitrary tag name? What if you can extend features
16
+ of an existing HTML tag?
17
17
Custom Elements allow you to do those things.
18
18
19
19
<!-- Excerpt -->
@@ -27,7 +27,7 @@ Custom Elements allow you to do those things.
27
27
# What are Custom Elements?
28
28
29
29
Custom Elements enable developers to create their own custom HTML tags, let
30
- them use those tags in their sites and apps, enables easier component resuse.
30
+ them use those tags in their sites and apps, and enable easier component resuse.
31
31
32
32
# How to build a custom element
33
33
@@ -38,26 +38,26 @@ its tag name as the first argument.
38
38
var XComponent = document.registerElement('x-component');
39
39
```
40
40
41
- To detect the availability of Custom Elements, check if
42
- ` document.registerElement ` is available. Otherwise, you can simply load
43
- [ ` webcomponents.js ` ] ( https://github.com/webcomponents/webcomponentsjs ) to
44
- polyfill it.
45
-
46
- ```
47
- <script src="libs/webcomponens.js"></script>
48
- ```
49
-
50
41
Now you can use ` <x-component> ` wherever you want in the document.
51
42
52
43
```
53
44
<x-component></x-component>
54
45
```
55
46
56
- Note: ` <x-component> ` can appear in the document before definition of the custom
57
- element execution. See
47
+ Note: ` <x-component> ` can appear in the document before the definition of the
48
+ custom element execution. See
58
49
[ HTML5Rocks article] ( http://www.html5rocks.com/en/tutorials/webcomponents/customelements/ )
59
50
for details.
60
51
52
+ To detect the availability of Custom Elements, check if
53
+ ` document.registerElement ` is available. Otherwise, you can simply load
54
+ [ ` webcomponents.js ` ] ( http://webcomponents.org/polyfills/ ) to
55
+ polyfill it.
56
+
57
+ ```
58
+ <script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
59
+ ```
60
+
61
61
## Naming rules
62
62
63
63
You need to have at least one '` - ` ' inside the name of a custom element. Any tag
76
76
77
77
## Imperative usage
78
78
79
- Defined custom tag can be used declaratively by inserting ` <x-component> ` tag
80
- inside HTML, but you can also do an imperative approach.
79
+ A defined custom tag can be used declaratively by inserting ` <x-component> ` tag
80
+ inside HTML, but you can also take an imperative approach.
81
81
82
82
```
83
83
var XComponent = document.registerElement('x-component');
84
84
var dom = new XComponent();
85
85
document.body.appendChild(dom);
86
86
```
87
87
88
- Above example is using ` new ` to instantiate a custom element.
88
+ The above example is using ` new ` to instantiate a custom element.
89
89
90
90
```
91
91
document.registerElement('x-component');
@@ -102,10 +102,10 @@ Let's add some features to the element.
102
102
103
103
In order to add features to a custom element, you first need to create a basic
104
104
prototype object by calling ` Object.create() ` with ` HTMLElement.prototype ` as an
105
- argument. This way, you can have basic HTML element feature set, so you can add
106
- arbitrary functions. Once your prototype object looks good, set that as a value
107
- of a key ' ` prototype ` ' inside an object and call ` document.registerElement() `
108
- with it as a second argument.
105
+ argument. This gives you an empty prototype object with the basic HTML element
106
+ feature set in its prototype chain. Add any functions and properties you want to
107
+ the prototype object, then pass your prototype to document.registerElement as
108
+ shown below:
109
109
110
110
```
111
111
var proto = Object.create(HTMLElement.prototype);
@@ -120,29 +120,31 @@ document.registerElement('x-component', {
120
120
121
121
## Custom Element Structure
122
122
123
- Let's see what's going on in a custom element using Chrome DevTools. Use
123
+ Let's see what's going on in a custom element using Chrome DevTools. Use the
124
124
"Elements" panel to inspect the ` x-component ` tag we just created. You can see
125
125
the ` x-component ` is an instance of a ` x-component ` prototype which is an
126
- instance of the ` HTMLElement ` .
126
+ instance of the ` HTMLElement ` prototype .
127
127
128
128
![ Custom Element Structure] ( /img/stories/customelements-inherit.png )
129
129
130
130
# Type Extension Custom Element
131
131
132
- You can create a custom element that extends a native HTML element's feature .
133
- This is called the Type Extension Custom Element and is used with its original
134
- tag name with an '` is ` ' attribute.
132
+ You can create a custom element that extends a native HTML element's features .
133
+ This is called a Type Extension Custom Element. To use the element, use the
134
+ original tag and specify the custom tag name using the '` is ` ' attribute.
135
135
136
136
```
137
137
<div is="x-component"></div>
138
138
```
139
139
140
- To define a type extension, add a key of '` extends ` ' inside of the second
141
- argument object with original tag name when calling
142
- ` document.registerElement() ` . Also the base prototype object should be created
143
- using the extending element's prototype instead of ` HTMLElement ` 's.
140
+ To define a type extension:
141
+
142
+ - Create the base prototype object using the prototype of the extended element,
143
+ instead of HTMLElement.
144
+ - Add an ` extends ` key in the second argument to ` document.registerElement() ` ,
145
+ specifying the * tag name* of the extended element.
144
146
145
- Following is an example code when extending an ` input ` element.
147
+ Following is an example code when extending the ` input ` element:
146
148
147
149
```
148
150
var XComponent = document.registerElement('x-component', {
@@ -151,24 +153,24 @@ var XComponent = document.registerElement('x-component', {
151
153
});
152
154
```
153
155
154
- Notice that it ` extends: 'input' ` and prototype is based on ` HTMLInputElement `
155
- instead of ` HTMLElement ` . Now you can use ` <input is="x-component"> ` inside your
156
- document. By doing so, you can have extended APIs on top of basic ` input `
157
- element's features.
156
+ Notice that it ` extends: 'input' ` and its prototype is based on
157
+ ` HTMLInputElement ` instead of ` HTMLElement ` . Now you can use
158
+ ` <input is="x-component"> ` inside your document. By doing so, you can have
159
+ extended APIs on top of basic ` input ` element's features.
158
160
159
161
Note: You may wonder what happens if you set different elements for ` 'extends ` '
160
- and '` prototype ` '. Yes, it is possible and may bring something no ones ever
161
- think of. But as far as I have experimented, you won't get any valuable outcome.
162
+ and '` prototype ` '. Yes, it is possible and may cause unexpected results. But as
163
+ far as I have experimented, you won't get any valuable outcome.
162
164
163
165
## Use case at GitHub
164
166
165
- So what's the point of Type Extension Custom Element? Let's look at the great
166
- existing example at GitHub website.
167
+ So what's the point of Type Extension Custom Element? Let's look at a great
168
+ existing example at the GitHub website.
167
169
168
170
![ relative-time type extension] ( /img/stories/customelements-relativetime.png )
169
171
170
172
GitHub has a many components that displays date and time. Notice they are not
171
- absolute dates/times but relative dates/times against browser's current time.
173
+ absolute dates/times but relative to the browser's current time.
172
174
You should be able to imagine how to calculate that but GitHub is doing that
173
175
using Type Extension Custom Element with [ `time-
174
176
elements`] ( https://github.com/github/time-elements ) .
@@ -189,17 +191,17 @@ This is done by calculating a relative date/time out from an absolute date/time
189
191
190
192
The benefit of using Type Extension Custom Element is that even if JavaScript is
191
193
turned off or the browser doesn't support Custom Elements (including polyfill),
192
- ` time ` element will still show the date/time information as a fallback keeping
193
- its semantics. Try using DevTools and turn off JavaScript, you'll notice it
194
- shows absolute dates/ times.
194
+ the ` time ` element will still show the date/time information as a fallback
195
+ keeping its semantics. Try using DevTools and turning off JavaScript; you'll
196
+ notice it shows absolute dates and times.
195
197
196
198
Read webcomponents.org's
197
199
[ How GitHub is using Web Components in production] ( http://webcomponents.org/articles/interview-with-joshua-peek/ )
198
200
for more details about ` time-elements ` .
199
201
200
202
# Lifecycle callbacks
201
203
202
- I mentioned ` relative-time ` custom element inserts a relative date/time into
204
+ I mentioned the ` relative-time ` custom element inserts a relative date/time into
203
205
` TextContent ` on the fly. But when does that happen? You can define functions to
204
206
be called when certain events happened on Custom Elements, which are called
205
207
"lifecycle callbacks".
@@ -219,13 +221,13 @@ Called when the element is detached from the document.
219
221
Called when one of attributes of the element is changed.
220
222
221
223
In case of ` relative-time ` , ` .createdCallback() ` and
222
- ` .attributeChangedCallback() ` is hooked to insert a relative date/time to
224
+ ` .attributeChangedCallback() ` are hooked up to insert a relative date/time to
223
225
` TextContent ` .
224
226
225
227
## Example
226
228
227
- To use lifecycle callback , just define those functions as a property of a
228
- prototype object when registering a custom element as I mentioned earlier .
229
+ To use lifecycle callbacks , just define the functions as properties of a
230
+ prototype object when registering a custom element.
229
231
230
232
```
231
233
var proto = Object.create(HTMLElement.prototype);
@@ -239,16 +241,16 @@ var XComponent = document.registerElement('x-component', {
239
241
});
240
242
```
241
243
242
- # Combining with Templates and Shadow DOM
244
+ # Combining Custom Elements with Templates and Shadow DOM
243
245
244
- By using Templates and Shadow DOM in the custom element, you can make the
245
- element easier to handle and resusable. With templates, defining content of your
246
+ By using Templates and Shadow DOM in a custom element, you can make the element
247
+ easier to handle and resusable. With templates, defining the content of your
246
248
custom element can be declarative. With Shadow DOM, styles, ids and classes of
247
249
the content can be scoped to itself.
248
250
249
251
You can utilize them when the custom element is created using ` .createdCallback() ` .
250
252
Let's have a look at a sample code. To learn about Templates and Shadow DOM,
251
- read respective articles
253
+ read the respective articles
252
254
([ Template] ( http://webcomponents.org/articles/introduction-to-template-element ) ,
253
255
[ Shadow DOM] ( http://webcomponents.org/articles/introduction-to-shadow-dom ) )
254
256
written previously.
@@ -294,13 +296,13 @@ var XComponent = document.registerElement('x-component', {
294
296
295
297
# Supported browsers
296
298
297
- Custom Elements are supported by Chrome and Opera. Firefox supports it behind a
298
- flag as of November 2014. To check availability, go to
299
+ Custom Elements are supported by Chrome and Opera. Firefox supports them behind
300
+ a flag as of November 2014. To check availability, go to
299
301
[ chromestatus.com] ( https://www.chromestatus.com/features/4642138092470272 ) or
300
302
[ caniuse.com] ( http://caniuse.com/#feat=custom-elements ) . For polyfilling other
301
303
browsers, you can use
302
- [ webcomponents.js] ( https ://github.com/webcomponents/webcomponentsjs ) (renamed from
303
- [ platform.js] ( https://github.com/Polymer/platform ) ).
304
+ [ webcomponents.js] ( http ://webcomponents.org/polyfills/ ) (renamed
305
+ from [ platform.js] ( https://github.com/Polymer/platform ) ).
304
306
305
307
# Resources
306
308
0 commit comments