Skip to content

Instantly share code, notes, and snippets.

@philcon93
Last active December 15, 2016 06:27
Show Gist options
  • Save philcon93/4aae098af010efe8e0c2329a5aa8d153 to your computer and use it in GitHub Desktop.
Save philcon93/4aae098af010efe8e0c2329a5aa8d153 to your computer and use it in GitHub Desktop.
Web Components

Custom Elements

Element registration

Before you can use a custom element, it needs to be registered. Otherwise, the browser considers it an HTMLElement.

document.registerElement()

To register a new custom element in JavaScript, invoke document.registerElement() somewhere in the page. As before, custom elements built this way work just like standard elements.

var XFooPrototype = Object.create(HTMLElement.prototype);
XFooPrototype.createdCallback = function() {
  this.textContent = "I'm an x-foo!";
};

XFooPrototype.foo = function() {
  console.log('foo() called');
};

var XFoo = document.registerElement('x-foo', {
  prototype: XFooPrototype
});

After registration, you can construct an instance of your element just like standard DOM elements:

<x-foo></x-foo>

Custom Elements

Extending existing elements

If you want to inherit from a specialized form of HTMLElement (e.g. HTMLButtonElement), declare the type using the extends option when calling document.registerElement():

Example extending button:

var XFooButtonPrototype = Object.create(HTMLButtonElement.prototype);
XFooButtonPrototype.createdCallback = function() {
  this.textContent = "I'm an x-foo button!";
};

var XFooButton = document.registerElement('x-foo-button', {
  prototype: XFooButtonPrototype,
  extends: 'button'
});

If you've used extends to create a custom element that derives from an existing DOM element (e.g. something other than HTMLElement), use the is syntax:

<button is="x-foo-button"></button>

@curtiswilkinson
Copy link

ES6 Class syntax lends itself particularly well to writing custom elements like this

https://github.com/GoogleChrome/ui-element-samples/blob/gh-pages/3d-card-flip/card-flip.js

@philcon93
Copy link
Author

philcon93 commented Dec 5, 2016

<neto-search></neto-search>

<template id="netoSearch">
	<style>
		* {
		    -webkit-box-sizing: border-box;
		    -moz-box-sizing: border-box;
		    box-sizing: border-box;
		}	
		.header-search{
			margin-top: 20px;
		}
		.input-group {
		    position: relative;
		    display: table;
		    border-collapse: separate;
		}		
		.form-control {
		    display: block;
		    width: 100%;
		    height: 34px;
		    padding: 6px 12px;
		    font-size: 14px;
		    line-height: 1.42857143;
		    color: #555555;
		    background-color: #fff;
		    background-image: none;
		    border: 1px solid #ccc;
		    border-radius: 4px;
		    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
		    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
		    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
		    -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
		    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
		}		
		.input-group .form-control {
		    position: relative;
		    z-index: 2;
		    float: left;
		    width: 100%;
		    margin-bottom: 0;
		    display: table-cell;
		}
		.input-group-btn {
		    position: relative;
		    font-size: 0;
		    width: 1%;
		    white-space: nowrap;
		    vertical-align: middle;
		    display: table-cell;
		}		
		.input-group-btn > .btn {
    		position: relative;
		}		
		.input-group-btn:last-child > .btn{
			border-bottom-left-radius: 0;
    		border-top-left-radius: 0;			
    		z-index: 2;
    		margin-left: -1px;
		}
		.btn {
		    display: inline-block;
		    margin-bottom: 0;
		    font-weight: normal;
		    text-align: center;
		    vertical-align: middle;
		    touch-action: manipulation;
		    cursor: pointer;
		    background-image: none;
		    border: 1px solid transparent;
		    white-space: nowrap;
		    padding: 6px 12px;
		    font-size: 14px;
		    line-height: 1.42857143;
		    border-radius: 4px;
		    -webkit-user-select: none;
		    -moz-user-select: none;
		    -ms-user-select: none;
		    user-select: none;
		}		
		.btn-default {
    		color: #333333 ;
    		background-color: #ffffff ;
    		border-color: #cccccc;
		}		
		.fa {
		    display: inline-block;
		    font: normal normal normal 14px/1 FontAwesome;
		    font-size: inherit;
		    text-rendering: auto;
		    -webkit-font-smoothing: antialiased;
		    -moz-osx-font-smoothing: grayscale;
		}
		.fa-search:before {
    		content: "\f002";
		}
	</style>
	<div class="header-search">
		<form name="productsearch" method="get" action="/" _lpchecked="1">
			<input type="hidden" name="rf" value="kw">
			<div class="input-group">
				<input class="form-control ajax_search" value="" id="name_search" autocomplete="off" name="kw" type="text" nsearch-init="yes" nsearch-id="0">
				<span class="input-group-btn">
					<button type="submit" value="Search" class="btn btn-default"><i class="fa fa-search"></i></button>
				</span>
			</div>
		</form>
	</div>
</template>

@philcon93
Copy link
Author

var proto = Object.create(HTMLElement.prototype, {
  createdCallback: {
    value: function() {
      var t = document.querySelector('#netoSearch');
      var clone = document.importNode(t.content, true);
      this.createShadowRoot().appendChild(clone);
    }
  }
});

document.registerElement('neto-search', {prototype: proto});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment