Skip to content

Instantly share code, notes, and snippets.

@matfin
Last active January 6, 2016 19:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matfin/a868758a36ba815679a5 to your computer and use it in GitHub Desktop.
Save matfin/a868758a36ba815679a5 to your computer and use it in GitHub Desktop.
HTML5 Web Components - Snippets from learning
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<!-- Option One -->
<!--pluralsight-comment></pluralsight-comment-->
<script type="text/javascript">
var PluralSightCommentProto = Object.create(HTMLElement.prototype);
PluralSightCommentProto.createdCallback = function() {
console.log('Comment prototype created');
this.innerHTML = '<h2>This is a comment</h2><br /><textarea></textarea><br /><input type="submit">';
};
var PluralSightComment = document.registerElement('pluralsight-comment', {
prototype: PluralSightCommentProto
});
var comment = new PluralSightComment();
// Option Two
//document.body.appendChild(comment);
// Option Three
//var created_comment = document.createElement('pluralsight-comment');
//document.body.appendChild(created_comment);
// Option Four
document.body.innerHTML = '<pluralsight-comment></pluralsight-comment>';
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<comment-form>
<!-- This will be inserted to the template where the content select attribute is set to 'h1' -->
<h1>
This is a comment form using insertion points
</h1>
<!-- This will be inserted to the template where the content select attribute is set to '.instructions' -->
<p class="instructions">
Type anything you want
</p>
<!-- This will be inserted to the template where the content select attribute is set to '.footer' -->
<!-- Note: the class on the footer is needed as it matches the '.footer' select attribute given in the template. -->
<p class="footer">
And is this a footer?
</p>
</comment-form>
<template id="comment-form">
<fieldset>
<legend>
<content select="h1">
</content>
</legend>
<content select="p.instructions">
</content>
<textarea style="width: 400px; height: 200px;"></textarea>
<br />
<input type="submit" value="Add comment" />
<content select="p.footer">
</content>
</fieldset>
</template>
<script type="text/javascript">
// Creating the custom element
var commentProto = Object.create(HTMLElement.prototype);
// Set the content inside the created callback function
commentProto.createdCallback = function() {
// Reference the template and then create a shadow root
var template = document.getElementById('comment-form'),
shadow = this.createShadowRoot();
// Grab the content of the template and append it to the shadow root
shadow.appendChild(document.importNode(template.content, true));
}
// Register the custom element using the comment form prototype
document.registerElement('comment-form', {
prototype: commentProto
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="host">
<ul>
<li>
An item
</li>
<li>
A second item
</li>
<li>
A third item
</li>
<li>
A fourth item
</li>
</ul>
</div>
<template>
<h1>
Item lists
</h1>
<content id="test"></content>
</template>
<script type="text/javascript">
var host = document.querySelector('#host'),
root = host.createShadowRoot(),
template = document.querySelector('template'),
clone = document.importNode(template.content, true);
root.appendChild(clone);
var distributedNodes = root.querySelector('content#test').getDistributedNodes()
console.log(distributedNodes);
var destinationInsertionPoints = document.querySelector('ul').getDestinationInsertionPoints();
console.log(destinationInsertionPoints);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button id="light-dom-button">
Light DOM Button
</button>
<div id="host">
</div>
<template>
<button id="shadow-dom-button">
Shadow DOM Button
</button>
<!-- Demonstrating how the 'change' event is fired for a select dropdown inside a template -->
<select id="event-change-demo">
<option selected value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</template>
<script type="text/javascript">
var host = document.querySelector('#host'),
root = host.createShadowRoot(),
template = document.querySelector('template'),
clone = document.importNode(template.content, true);
root.appendChild(clone);
document.addEventListener('click', function(e) {
// Should log 'host' as the targets id if the button labelled 'Shadow DOM Button' is clicked
console.log('document based event listener got: ', e.target.id);
});
root.addEventListener('click', function(e) {
// Should log 'shadow-dom-button' as the targets id if the button labelled 'Shadow DOM Button' is clicked
console.log('shadow root based event listener got: ', e.target.id);
});
root.addEventListener('change', function(e) {
// Will not log for a change event on the template select element
console.log('document based change listener got:', e.target.id);
});
root.addEventListener('change', function(e) {
// Will log for a change event on the template select element
console.log('shadow root based change listener got:', e.target.id);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button is="pluralsight-button"></button>
<script type="text/javascript">
var ButtonPrototype = Object.create(HTMLButtonElement.prototype);
ButtonPrototype.createdCallback = function() {
console.log('ButtonPrototype: createdCallback has been fired');
this.innerHTML = 'PluralSightButton';
this.value = 'A given value';
this.style.color = 'orange';
};
var PluralSightButton = document.registerElement('pluralsight-button', {
prototype: ButtonPrototype,
extends: 'button'
});
document.body.appendChild(new PluralSightButton());
//document.body.innerHTML = '<button is="pluralsight-button"></button>';
var createdButtonElement = document.createElement('button', 'pluralsight-button');
document.body.appendChild(createdButtonElement);
setTimeout(function() {
createdButtonElement.style.color = 'red';
createdButtonElement.innerHTML = 'I have been changed!';
}, 3000);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<!-- Create a style. Does it apply to the content inside the template created by the shadow dom? -->
<style type="text/css">
h1 {
font-family: verdana;
color: red;
}
</style>
</head>
<body>
<div id="host">
<ul>
<li>
An item
</li>
<li>
Sitting
</li>
<li>
In a
</li>
<li>
List of items
</li>
</ul>
</div>
<template id="template">
<h1>
I am a template
</h1>
<p>
And this is to test Javascript encapsulation inside the shadow dom.
</p>
<content id="test">
</content>
<script type="text/javascript">
// This function will not be encapsulated
function testFunction(message) {
console.log('Called with message', message);
};
// This will help with encapsulation
var module = (function() {
return {
encapsulatedTestFunction: function(message) {
console.log('Encapsulated function says: ', message);
}
}
})();
module.encapsulatedTestFunction('I am being called from within the template.');
</script>
</template>
<script type="text/javascript">
var host = document.getElementById('host'),
root = host.createShadowRoot(),
template = document.getElementById('template'),
clone = document.importNode(template.content, true); // true for 'deep copy' of the content
root.appendChild(clone);
var distributedNodes = root.querySelector('#test').getDistributedNodes();
console.log({
distributed_nodes: distributedNodes
});
var destinationInsertionPoints = document.querySelector('ul').getDestinationInsertionPoints();
console.log({
destination_insertion_points: destinationInsertionPoints
});
// Call the testFunction declared in the template with the id of template
testFunction('I am being called from the script tag at the bottom of this page');
// Call the encapsulated function from the template
module.encapsulatedTestFunction('I am being called from the script at the bottom of the page.');
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<hello-world></hello-world>
<script type="text/javascript">
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
console.log('proto: createdCallback fired');
this.innerHTML = '<h1>Custom element: hello</h1>';
this.style.color = 'red';
};
proto.attachedCallback = function() {
console.log('proto: attachedCallback fired');
};
proto.detachedCallback = function() {
console.log('proto: detachedCallback fired');
};
proto.attributeChangedCallback = function(attrName, oldValue, newValue) {
console.log('proto: attributeChangedCallback fired with', attrName, oldValue, newValue);
};
var helloComponent = document.registerElement('hello-world', {
prototype: proto
});
setTimeout(function() {
document.querySelector('hello-world').setAttribute('custom', 'A test value');
}, 2000);
setTimeout(function() {
document.querySelector('hello-world').setAttribute('custom', 'An edited test value');
}, 4000);
setTimeout(function() {
document.querySelector('hello-world').remove();
}, 6000);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<!-- Create a style. Does it apply to the content inside the template created by the shadow dom? -->
<style type="text/css">
h1 {
font-family: verdana;
color: red;
}
</style>
</head>
<body>
<h1>
I am a regular h1 appended to the light dom with styling applied
</h1>
<!-- The shadow host -->
<div id="host">
</div>
<template id="template">
<!-- Styling should only apply to the markup within this template -->
<style type="text/css">
h1 {
font-family: arial;
color: blue;
}
</style>
<h1>
I am a web component template added via the shadow dom - I have the styling defined within this template.
</h1>
</template>
<script type="text/javascript">
// Reference the host and create a shadow root from it
// Reference the template as well.
var host = document.getElementById('host'),
root = host.createShadowRoot(),
template = document.querySelector('template');
// Appending the template to the shadow dom - no styling should be applied
root.appendChild(document.importNode(template.content, true));
// Using document.querySelectorAll() should only return the h1 in the 'light dom'
var light_dom_headings = document.querySelectorAll('h1');
console.log({
light: light_dom_headings
});
// Using root.querySelectorAll() should only return the h1 in its template
var shadow_dom_headings = root.querySelectorAll('h1');
console.log({
shadow: shadow_dom_headings
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<comment-form>
<!-- This will be inserted to the template where the content select attribute is set to 'h1' -->
<h1>
This is a comment form using insertion points
</h1>
<!-- This will be inserted to the template where the content select attribute is set to '.instructions' -->
<p class="instructions">
Type anything you want
</p>
<!-- The template negation selector should exclude this from being displayed -->
<p class="instructions boring">
A message of no particular interest
</p>
<input type="button" value="Reset" />
<!-- This will be inserted to the template where the content select attribute is set to '.footer' -->
<!-- Note: the class on the footer is needed as it matches the '.footer' select attribute given in the template. -->
<p id="footer">
And is this a footer?
</p>
<span>This should not show at all</span>
</comment-form>
<template id="comment-form">
<fieldset>
<legend>
<content select="h1">
</content>
</legend>
<content select="p.instructions:not(.boring)">
</content>
<textarea style="width: 400px; height: 200px;"></textarea>
<br />
<content select="input[type=button]">
</content>
<input type="submit" value="Add comment" />
<content select="p#footer">
</content>
</fieldset>
</template>
<script type="text/javascript">
// Creating the custom element
var commentProto = Object.create(HTMLElement.prototype);
// Set the content inside the created callback function
commentProto.createdCallback = function() {
// Reference the template and then create a shadow root
var template = document.getElementById('comment-form'),
shadow = this.createShadowRoot();
// Grab the content of the template and append it to the shadow root
shadow.appendChild(document.importNode(template.content, true));
}
// Register the custom element using the comment form prototype
document.registerElement('comment-form', {
prototype: commentProto
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/**
* Styling 'shadow' elements inside the shadow DOM from the 'light' DOM
*/
custom-list::shadow li {
color: red;
}
/**
* We should not need a special selector for the h2 inside the template
*/
h2 {
font-style: italic;
color: blue;
}
</style>
</head>
<body>
<custom-list>
<h2>
A list of things
</h2>
</custom-list>
<template id="custom-list-template">
<content select="h2"></content>
<ul>
<li>
Item One
</li>
<li>
Item Two
</li>
<li>
Item Three
</li>
</ul>
</template>
<script type="text/javascript">
var customList = Object.create(HTMLElement.prototype);
customList.createdCallback = function() {
var template = document.getElementById('custom-list-template'),
clone = document.importNode(template.content, true);
this.createShadowRoot().appendChild(clone);
};
document.registerElement('custom-list', {
prototype: customList
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="host">
<span class="message">
Light dom
</span>
</div>
<script type="text/javascript">
var host = document.querySelector('#host'),
first_root = host.createShadowRoot(),
second_root = host.createShadowRoot(),
third_root = host.createShadowRoot();
first_root.innerHTML = '<div>First root</div>';
second_root.innerHTML = '<content select=".message"></content><shadow></shadow><span>Second root</span>';
third_root.innerHTML = '<span>I am the third root</span><shadow></shadow>';
// Will evaulaute to true because the older shadow host of the second shadow root is the first shadow root added.
console.log(second_root.olderShadowRoot === first_root);
// Will evaluate to true because the show.shadowRoot is always the last shadowRoot added - like the third shadow root
console.log(host.shadowRoot === third_root);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#button {
color: green;
background-color: red;
}
</style>
</head>
<body>
<div id="host">
<button id="button">A Button</button>
</div>
<template>
<style type="text/css">
::content > #button {
font-size: 1rem;
border: none;
border-radius: 0.5rem;
background-color: #0066cc;
color: white;
padding: 0.5rem 1rem;
}
</style>
<content select="button"></content>
</template>
<script type="text/javascript">
var root = document.querySelector('#host').createShadowRoot(),
template = document.querySelector('template');
root.appendChild(template.content.cloneNode(true));
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/* #host {
background-color: pink;
} */
</style>
</head>
<body>
<section class="">
<div id="host" class="warning">
<p>
My host is styled via the :host selector and I will be visible because the select attribute on the content tag inside the template matches me.
</p>
<span>
I may not be visible unless I get a content that has a select attribute that matches what I am - a span element.
</span>
</div>
</section>
<template>
<!-- The styling for this template -->
<style type="text/css">
:host {
font-family: verdana;
font-size: 0.9rem;
box-sizing: border-box;
color: white;
width: 50%;
padding: 0.25rem 1rem;
border-radius: 0.5rem;
transition-property: transform;
transition-duration: 250ms;
}
/**
* Psuedo state styling
*/
:host(:hover) {
transform: scale(1.05);
}
:host(.error) {
background-color: red;
}
:host(.warning) {
background-color: orange;
}
:host(.success) {
background-color: green;
}
/**
* Do any of the parents this template has been cloned into have a class of .theme-dark ?
* If so, we will apply the following styling.
*/
:host-context(.theme-dark) {
background-color: black;
}
/**
* Styling for distributed nodes
*/
::content p {
font-style: italic;
}
::content span {
font-size: 2rem;
color: black;
}
</style>
<!-- And the content placeholder -->
<content select="p, span"></content>
</template>
<script type="text/javascript">
var host = document.querySelector('#host'),
root = host.createShadowRoot(),
template = document.querySelector('template'),
clone = document.importNode(template.content, true);
root.appendChild(clone);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
x-foo:unresolved p {
opacity: 0.25;
}
x-foo p {
opacity: 1;
}
</style>
</head>
<body>
<x-foo>
<p>
I have an opacity of 0.25 because I am :unresolved
</p>
</x-foo>
<template>
<p>
I have an opacity of 1 because I am now resolved
</p>
</template>
<script type="text/javascript">
var xProto = Object.create(HTMLElement.prototype);
xProto.createdCallback = function() {
console.log('xProto: createdCallback function fired');
var template = document.querySelector('template'),
clone = document.importNode(template.content, true);
this.createShadowRoot().appendChild(clone);
};
setTimeout(function() {
document.registerElement('x-foo', {
prototype: xProto
});
}, 3000);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/**
* Styling 'shadow' elements inside the shadow DOM from the 'light' DOM
*/
custom-list /deep/ li {
color: red;
}
/**
* We should not need a special selector for the h2 inside the template
*/
h2 {
font-style: italic;
color: blue;
}
</style>
</head>
<body>
<video controls></video>
<custom-list>
<magic-list>
</magic-list>
</custom-list>
<!-- Template: custom list -->
<template id="custom-list-template">
<ul>
<li>
Item One
</li>
<li>
Item Two
</li>
<li>
Item Three
</li>
</ul>
<shadow>
</shadow>
</template>
<!-- Template: magic list -->
<template id="magic-list-template">
<ul>
<li>
Magic List Item One
</li>
<li>
And the second item
</li>
<li>
And finally the third
</li>
</ul>
</template>
<script type="text/javascript">
/**
* A custom list, its created callback and then registration
*/
var customList = Object.create(HTMLElement.prototype);
customList.createdCallback = function() {
var template = document.getElementById('custom-list-template'),
clone = document.importNode(template.content, true);
this.createShadowRoot().appendChild(clone);
};
document.registerElement('custom-list', {
prototype: customList
});
/**
* Another custom list, its created callback and then registration
*/
var magicList = Object.create(HTMLElement.prototype);
magicList.createdCallback = function() {
var template = document.getElementById('magic-list-template'),
clone = document.importNode(template.content, true);
this.createShadowRoot().appendChild(clone);
};
document.registerElement('magic-list', {
prototype: magicList
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment