Last active
August 7, 2018 06:29
-
-
Save AeonFr/2741024955144311631e97f9e178d9b4 to your computer and use it in GitHub Desktop.
Function to create DOM elements filled with attributes and content, in one line of JavaScript. Inspired on React.createElement().
This file contains hidden or 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
/** | |
* el(tag, options[, innerHTML]) | |
* Creates an HTMLElement object | |
* and fills it with various attributes and properties. | |
* Inspired by React's `React.createElement()` function | |
* | |
* @param string tag The element's tagname, such as P, DIV, etc. | |
* @param object options | |
* An object that can contain key-value pairs of attributes such as | |
* "aria-label", "itemtype", "disabled", etc. | |
* Can also contain a "style" key that should | |
* be a DOMElement.style object | |
* (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) | |
* Can also contain "special" properties | |
* that map to setters of the Element JS object, such as | |
* "id", "className", "contentEditable", "tabIndex" etc. | |
* @param string innerHTML The element's innerHTML | |
* (note: you can optionally, omit this argument and declare "innerHTML" inside the option's object) | |
* @return Element An HTML Element (object of type Element, DOMElement, DOMInputElement, etc.) | |
*/ | |
function el(tag, options, innerHTML){ | |
var el = document.createElement(tag); | |
Object.keys(options).forEach(function(key){ | |
if (typeof options[key] == 'object'){ | |
/** We deduce that if the object index is not a string, | |
* then it is the el.style object. | |
* Still, we can call this generic code that can populate | |
* any object with a massive assignation, | |
* and support other possible use-cases besides el.style | |
**/ | |
Object.assign(el[key], options[key]); | |
} else { | |
/* Implement "native" setters whenever available, | |
* (native setters such as el.value, el.innerHTML, etc.) | |
* otherwise fall back to el.setAttribute() | |
*/ | |
if (key in el) | |
el[key] = options[key]; | |
else | |
el.setAttribute(key, options[key]); | |
} | |
}); | |
if (innerHTML) | |
el.innerHTML = innerHTML; | |
return el; | |
} | |
/** | |
* ********************* TESTS | |
* */ | |
var testWrapper = el('div', { classList: 'tests' }); | |
document.body.appendChild(testWrapper); | |
testWrapper.appendChild(el('p',{ 'data-text': 'Calling el() withouth innerHTML' })); | |
testWrapper.appendChild(el('p', | |
{ style: { backgroundColor: 'red' } }, | |
'calling el() with <code>options.style.backgroundColor = red</code>' | |
)); | |
testWrapper.appendChild(el('p', { | |
style: { color: 'red', padding: '1rem' }, | |
'data-order': -1, | |
'aria-label': 'Hello, World' | |
}, 'calling el() with multiple attributes and styles') | |
); | |
testWrapper.appendChild(el('p', {}, 'I was created and inserted in one line of JS!')); | |
testWrapper.appendChild(el('p', { | |
id: 'specialAttributes', | |
draggable: true, | |
contentEditable: true, | |
lang: 'en', | |
tabIndex: -1, | |
className: 'special-attributes special-attributes--test' | |
}, 'testing "special" attributes: "className" and other attributes that should map to DOMElement setters.')); | |
testWrapper.appendChild(el('style', {}, '.special-attributes{ color: blue }')) | |
testWrapper.appendChild(el('small', { style: { display: 'block', maxWidth: '30em' } }, | |
'In the above example, the options properties map directly to DOMElement setters.' | |
+ ' Setting "tabindex: -1" and "class: ..." would also work,' | |
+ ' but the values passed would not be validated by the browser' | |
+ ' since they would be inserted with "getAttribute()",' | |
+ ' instead of using the native DOMElement.tabIndex and DOMElement.className setters.' | |
)); | |
/** ------------------------------ TEST RESULTS | |
<div class="tests"> | |
<p data-text="Calling el() withouth innerHTML"></p> | |
<p style="background-color: red;"> | |
calling el() with <code>options.style.backgroundColor = red</code> | |
</p> | |
<p data-order="-1" aria-label="Hello, World" style="color: red; padding: 1rem;"> | |
calling el() with multiple attributes and styles | |
</p> | |
<p>I was created and inserted in one line of JS!</p> | |
<p id="specialAttributes" draggable="true" contenteditable="true" lang="en" tabindex="-1" class="special-attributes special-attributes--test"> | |
testing "special" attributes: "className" and other attributes that should map to DOMElement setters. | |
</p> | |
<style>.special-attributes{ color: blue }</style> | |
<small style="display: block; max-width: 30em;"> | |
In the above example, the options properties map directly to DOMElement setters. Setting "tabindex: -1" and "class: ..." would also work, but the values passed would not be validated by the browser since they would be inserted with "getAttribute()", instead of using the native DOMElement.tabIndex and DOMElement.className setters. | |
</small> | |
</div> | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment