Last active
February 23, 2018 11:06
-
-
Save spiralx/773bac30884db9028313758c0621f14a to your computer and use it in GitHub Desktop.
Simple element builder function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A simple HTML element builder function. | |
* @module EL | |
* @license MIT | |
* @author James Skinner <spiralx@gmail> | |
* @see {@link https://github.com/spiralx My GitHub profile} | |
*/ | |
// UMD wrapper to support CommonJS and AMD as well as the browser | |
(function(root, factory) { | |
if (typeof define === 'function' && define.amd) { | |
define(factory) | |
} | |
else if (typeof exports === 'object') { | |
module.exports = factory() | |
} | |
else { | |
root.EL = factory() | |
} | |
})(this, function factory() { | |
'use strict' | |
/** | |
* Function to generate HTML elements. | |
* | |
* @example | |
* // returns "<div id="main"><div class="container"><section class="comment body"></section></div></div>" | |
* EL('#main', [ '.container', [ 'section.comment.body' ] ]).outerHTML | |
* | |
* @example | |
* // returns "<div class="panel"><div class="panel-header"><a href="/"><h1 id="title">TITLE</h1><br>Subtitle</a></div></div>" | |
* EL('.panel', [ '.panel-header', [ 'a', { href: '/' }, [ 'h1#title', 'TITLE' ], [ 'br' ], 'Subtitle' ] ]).outerHTML | |
* | |
* @example | |
* // returns "<a id="home" class="button raised" href="/" style="font-weight: bold;">Link</a>" | |
* EL('a#home.button.raised', { href: '/', style: { 'font-weight': 'bold' } }, 'Link').outerHTML | |
* | |
* @example | |
* // returns "<div class="content"><div class="section">Lorem ipsum</div><hr class="thick width50"><div class="section">dolor est</div></div>" | |
* let hr = document.createElement('hr') | |
* hr.className = 'thick width50' | |
* EL('.content', [ '.section', 'Lorem ipsum' ], hr, [ '.section', 'dolor est' ]).outerHTML | |
* | |
* @example | |
* // returns "<li><form><label id="qt">Loading search... please wait.</label><br><input id="qh" type="hidden"><input id="qh2" type="hidden"><input id="q" disabled="" size="20"><input id="qb" type="button" value="Search" disabled=""></form></li>" | |
* EL('li', [ | |
* 'form', | |
* [ 'label#qt', 'Loading search... please wait.' ], | |
* [ 'br' ], | |
* [ 'input#qh', { type: 'hidden' } ], | |
* [ 'input#qh2', { type: 'hidden' } ], | |
* [ 'input#q', { disabled: true, size: 20 } ], | |
* [ 'input#qb', { type: 'button', value: 'Search', disabled: true } ], | |
* ]).outerHTML | |
* | |
* @param {string} [defn=div] Defines the element and optionally its ID and class(es), format is: | |
* [TAG_NAME=div]?[#ID]?[.CLASS_NAME]*[#ID]? | |
* | |
* @param {Object} [properties] For each name, value pair set the property name of the element to value | |
* to set properties on the `dataset` and `style` properties respectively | |
* @param {Object} [properties.data] Each name and value pair is applied to the element's dataset property | |
* @param {Object} [properties.style] Each name and value pair is applied to the element's style property | |
* | |
* @param {...(string|Array|HTMLElement)} children Each param defines a child of the constructed element, as either a text node or | |
* HTML element for string and HTMLElement parameters respectively, or for an | |
* array parameter, it's items are used as the arguments to EL, and the result | |
* then used as the child. | |
* @returns {HTMLElement} | |
*/ | |
function EL(defn = 'div', properties = {}, ...children) { | |
const m = defn.split(/\b(?=[\.#])/g) | |
const tag = m[0].startsWith('#') || m[0].startsWith('.') | |
? 'div' | |
: m.shift() | |
const element = document.createElement(tag || 'div') | |
m.forEach(v => { | |
if (v[0] === '.') { | |
element.classList.add(v.substr(1)) | |
} | |
else if (v[0] === '#') { | |
element.id = v.substr(1) | |
} | |
}) | |
if (Object.getPrototypeOf(properties) === Object.prototype) { | |
const { data = {}, style = {}, ...props } = properties | |
Object.assign(element.dataset, data) | |
Object.assign(element.style, style) | |
Object.assign(element, props) | |
} else { | |
children.unshift(properties) | |
} | |
for (let child of children) { | |
if (typeof child === 'string') { | |
child = document.createTextNode(child) | |
} else if (Array.isArray(child)) { | |
child = EL(...child) | |
} else if (!(child instanceof HTMLElement)) { | |
throw new TypeError(`Unknown child type`) | |
} | |
element.appendChild(child) | |
} | |
return element | |
} | |
return EL | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment