are a set of standards that allow for the creation of reusable widgets or components in web documents and web applications
@CarmenPopoviciu
(>‿◠)✌ Guilherme Rv Coelho <super-presentation>
☜(ˆ▽ˆ) Filipe Araujo <akyral-code>
are a set of standards that allow for the creation of reusable widgets or components in web documents and web applications
Allow authors to extend the HTML vocabulary and define their own, new, fully-featured DOM elements
declarative, readable, meaningful, reusable, self sustainable
HTML Elements
Is the process of adding an element definition to a registry
document.registerElement('ascii-smile', // the type
{
// the prototype. HTMLElement/SVGElement by default
prototype: Object.create(HTMLElement.prototype)
}
); // returns a constructor function
<ascii-smile></ascii-smile>
are Custom Elements that extend other existing elements
var AsciiSmileProto = Object.create(HTMLElement.prototype);
...
document.registerElement('ascii-carmen-smile',
{
prototype: AsciiSmileProto,
extends: 'ascii-smile'
}
);
<ascii-smile is="ascii-smile-carmen"></ascii-smile>
Enable you to store HTML data inside an HTML document. The content of a <template> element is parsed without interpreting it (no loading of images etc.)
<template id="template">
<style>...</style>
<div>
<h1>ASCII Heart</h1>
<div><3</div>
<img src="http://ascii-paradise/heart.jpg">
</div>
</template>
<script>
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
var host = document.querySelector('#host');
host.appendChild(clone);
</script>
<div id="host"></div>
Shadow DOM encapsulates and hides the innards of a custom element inside a nested document.
let me show you something
is a way to include HTML documents in other HTML documents in a simple and declarative way
<html> <!-- import referrer-->
<head>
<!-- URL = import location -->
<!-- ascii-paradise.html = imported document -->
<link rel="import" href="path/to/ascii-paradise.html">
</head>
</html>
Including an import on a page returns a Document not its content
var content = document.querySelector('link[rel="import"]').import;
<template id="heart-template">
<style>
...
</style>
<div id="ascii-heart"><3</div>
</template>
<script>
// thisDoc = ascii-heart.html
var thisDoc = document._currentScript.ownerDocument;
// mainDoc = index.html
var mainDoc = document;
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
var shadowRoot = this.createShadowRoot();
var template = thisDoc.querySelector('#heart-template');
var clone = thisDoc.importNode(template.content, true);
shadowRoot.appendChild(clone);
};
mainDoc.registerElement('ascii-heart', {
prototype: proto
});
</script>
is a library built on top of the web components standards, that helps you build reusable components, faster and easier
To register a custom element, use the Polymer function, and pass in the prototype for the new element
var ASCIIHeart = Polymer({ // element prototype
is: 'ascii-heart', // tag name (mandatory)
properties: {...},
ready: function() {...},
...
});
// imperative
var asciiHeart = document.createElement('ascii-heart');
// or
var asciiHeart = new ASCIIHeart();
To register a custom element, use the Polymer function, and pass in the prototype for the new element
var ASCIIHeart = Polymer({ // element prototype
is: 'ascii-heart', // tag name (mandatory)
properties: {...},
ready: function() {...},
...
});
<!-- declarative -->
<ascii-heart></ascii-heart>
The Polymer function sets up the prototype chain for your custom element, chaining it to the Polymer Base prototype (which provides Polymer value-added features)
Polymer.Base = {
__isPolymerInstance__: true,
_addFeature: function() {
// pluggable features
},
registerCallback: function() {...},
createdCallback: function() {...},
attachedCallback: function() {...},
detachedCallback: function() {..},
attributeChangedCallback: function() {...},
...
};
...
Polymer.Base = Polymer.Base
.chainObject(Polymer.Base, HTMLElement.prototype);
allows creating a Custom Element without immediately registering it
// returns a constructor that can be passed to
// document.registerElement to register your element
var ASCIIHeart = Polymer.Class({
// same prototype argument as the Polymer function
is: 'ascii-heart',
created: function() {
...
}
...
});
document.registerElement('ascii-heart', ASCIIHeart);
allows creating a Custom Element without immediately registering it
// returns a constructor that can be passed to
// document.registerElement to register your element
var ASCIIHeart = Polymer.Class({
// same prototype argument as the Polymer function
is: 'ascii-heart',
created: function() {
...
}
...
});
var asciiHeart = new ASCIIHeart();
// or
var asciiHeart = document.createElement('ascii-heart');
var ASCIICarmenSmileBtn = Polymer({
is: 'ascii-carmen-smile-btn',
extends: 'button'
});
var asciiCarmenSmileBtn = document.createElement('button',
'ascii-carmen-smile-btn');
// or
var asciiCarmenSmileBtn = new ASCIICarmenSmileBtn();
<button is="ascii-carmen-smile"></button>
Polymer({
is: 'ascii-heart',
created: function() {
/* createdCallback */
// Called when the element has been created, but before
// property values are set and local DOM is initialized
},
ready: function() {
// Called after prop values are set & local DOM is initialized
},
attached: function() {
/* attachedCallback */
// Called after the element is attached to the document
},
detached: function() {
/* detachedCallback */
// Called after the element is detached from the document
},
attributeChanged: function(name, type) {
/* attributeChangedCallback*/
// Called when one of the element's attributes is changed
}
});
is the DOM that an element creates
Polymer supports multiple Local DOM implementations
<dom-module>
</dom-module>
<dom-module>
<template>
<div id="heart"><3</div>
</template>
</dom-module>
<dom-module >
<template>
<div id="heart"><3</div>
</template>
<script>
Polymer({
is:
});
</script>
</dom-module>
<dom-module id="ascii-heart">
<template>
<div id="heart"><3</div>
</template>
<script>
Polymer({
is: 'ascii-heart'
});
</script>
</dom-module>
<dom-module id="ascii-heart">
<template>
<div id="heart"><3</div>
</template>
</dom-module>
<script>
Polymer({
is: 'ascii-heart'
});
</script>
<dom-module id="ascii-heart">
<template>
<div id="heart"><3</div>
</template>
<script>
Polymer({
is: 'ascii-heart',
ready: function() {
}
});
</script>
</dom-module>
<dom-module id="ascii-heart">
<template>
<div id="heart"><3</div>
</template>
<script>
Polymer({
is: 'ascii-heart',
ready: function() {
this.$.heart.textContent = '<3 <3';
}
});
</script>
</dom-module>
Polymer provides insertion points via the <content> element. This element supports a select attribute which filters nodes via a simple selector
<ascii-shrug>
<span class="my-face">◔◡◔</span>
<span class="my-other-face">◔.◔</span>
</ascii-shrug>
<dom-module id="ascii-shrug">
<template>
<div class="right-arm">¯\_</div>
<div class="face">
<content ></content>
</div>
<div class="left-arm">_/¯</div>
</template>
<script>
Polymer({
is: 'ascii-shrug'
});
</script>
</dom-module>
<ascii-shrug>
<span class="my-face">◔◡◔</span>
<span class="my-other-face">◔.◔</span>
</ascii-shrug>
<dom-module id="ascii-shrug">
<template>
<div class="right-arm">¯\_</div>
<div class="face">
<content select=".my-face"></content>
</div>
<div class="left-arm">_/¯</div>
</template>
<script>
Polymer({
is: 'ascii-shrug'
});
</script>
</dom-module>
Polymer provides a custom API for manipulating DOM. Almost all of these methods and properties have the same signatures as their standard DOM equivalents
Are the public API of your element. Having declared properties on a custom element, allows a user to configure the property from markup
<ascii-hello face="◉◡◉" waving-hand="left"></ascii-hello>
Polymer({
is: 'ascii-hello',
ready: function() {
}
});
<ascii-hello face="◉◡◉" waving-hand="left"></ascii-hello>
Polymer({
is: 'ascii-hello',
properties: {
face: String,
wavingHand: {
type: String,
value: 'right'
}
},
ready: function() {
// do smth with the properties;
}
});
binds a property or sub-property of a custom element (the host element) to a property or attribute of an element in its local DOM (the child or target element)
<dom-module id="ascii-host">
<template>
<ascii-smiley color="{{discoColor}}"></ascii-smiley>
</template>
<script>
Polymer({
is: 'ascii-host',
properties: {
discoColor: String
}
});
</script>
</dom-module>
<ascii-smiley color="[[discoColor]]"></ascii-smiley>
<script>
Polymer({
is: 'ascii-smiley',
properties: {
color: {
type: String,
notify: true
}
}
});
</script>
<!-- changes to hosts's "discoColor" propagate to child's "color" -->
<!-- changes to child's "color" are ignored by host due to [[]] -->
<ascii-smiley color="{{discoColor}}"></ascii-smiley>
<script>
Polymer({
is: 'ascii-smiley',
properties: {
color: {
type: String,
notify: false
}
}
});
</script>
<!-- changes to hosts's "discoColor" propagate to child's "color" -->
<!-- host won't be notified by changes to child's "color" due to
notify:falsey -->
<ascii-smiley color="{{discoColor}}"></ascii-smiley>
<script>
Polymer({
is: 'ascii-smiley',
properties: {
color: {
type: String,
notify: true,
readOnly: true
}
}
});
</script>
<!-- changes to hosts's "discoColor" are ignored by child due to
readOnly:true -->
<!-- changes to child's "color" propagate to host's "discoColor" -->
<ascii-smiley color="{{discoColor}}"></ascii-smiley>
<script>
Polymer({
is: 'ascii-smiley',
properties: {
color: {
type: String,
notify: true
}
}
});
</script>
<dom-module id="ascii-paradise">
<template>
<!-- Binding to text content -->
{{greeting}} from ASCII Paradise!
<!-- Binding to sub-properties -->
<ascii-smiley face="{{smiley.face}}"
smile-size="{{smiley.smileSize}}"></ascii-smiley>
</template>
<script>
Polymer({
is: 'ascii-paradise',
properties: {
greeting: String,
smiley: Object
}
});
</script>
</dom-module>
Scoped styles should be provided via <style> tags placed inside the element’s local DOM <template>
<dom-module id="ascii-hello">
<template>
<style>
:host {
/* host styles*/
}
.right-arm {
/* element with class "right-arm" styles*/
}
</style>
<div class="right-arm"></div>
<div class="head"></div>
</template>
...
</dom-module>
are used to share style declarations between elements
<!-- ascii-heart-style.html -->
<dom-module id="ascii-heart-style">
<template>
<style>
:host { color: red; }
</style>
</template>
</dom-module>
<!-- ascii-heart.html -->
<link rel="import" href="../ascii-heart-style.html">
<dom-module id="ascii-heart">
<template>
<style is="custom-style" include="ascii-heart-style"></style>
</template>
...
</dom-module>
<template id="heart-template">
<style>
...
</style>
<div id="ascii-heart"><3</div>
</template>
<script>
// thisDoc = ascii-heart.html
var thisDoc = document._currentScript.ownerDocument;
// mainDoc = index.html
var mainDoc = document;
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
var shadowRoot = this.createShadowRoot();
var template = thisDoc.querySelector('#heart-template');
var clone = thisDoc.importNode(template.content, true);
shadowRoot.appendChild(clone);
};
mainDoc.registerElement('ascii-heart', {
prototype: proto
});
</script>
<dom-module id="ascii-heart">
<style>
...
</style>
<template>
<div class="ascii-heart"><3</div>
</template>
</dom-module>
<script>
Polymer({
is: 'ascii-heart'
});
</script>