Last active
April 3, 2017 09:32
-
-
Save frzi/346887b3cf2426628b0f72c354ac8f59 to your computer and use it in GitHub Desktop.
A quick and dirty JSX 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
Show hidden characters
{ | |
"plugins": [ | |
["transform-react-jsx", { | |
"pragma": "document.createCustomElement" | |
}] | |
] | |
} |
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
/** | |
* © 2017 frzi | |
* frzi.com | github.com/frzi | |
*/ | |
/** | |
* The function for JSX! | |
* Make sure the `pragma` for the `transform-react-jsx` plugin is set accordingly! | |
* Borrows the `ref` tag feature from React. | |
*/ | |
document.createCustomElement = document.createCustomElement || function (tag, props, ...children) { | |
if (typeof tag === 'string') { | |
let el = document.createElement(tag) | |
// Properties (and attributes) | |
if (props) { | |
for (const [key, value] of Object.entries(props)) { | |
// Style properties. | |
if (key === 'style' && typeof value === 'object') { | |
for (const property in value) { | |
el.style[property] = value[property] | |
} | |
} | |
// `className` can be either a string or an array. | |
else if (key === 'className') { | |
el.className = Array.isArray(value) ? value.join(' ') : value | |
} | |
// React's `ref` feature. | |
else if (key === 'ref') { | |
value(el) | |
} | |
// DOM attributes. Helps when you need to find the object via `querySelector`. | |
else if (key === 'attr' && typeof value === 'object') { | |
for (const attr in value) { | |
el.setAttribute(attr, value[attr]) | |
} | |
} | |
// Events. | |
else if (/^on[A-Z]/.test(key)) { | |
const eventName = key.substr(2, key.length - 2) | |
el.addEventListener(eventName.toLowerCase(), value) | |
} | |
else if (value !== undefined) { | |
el[key] = value | |
} | |
} | |
} | |
// Children. | |
if (children.length) { | |
for (const child of children) { | |
if (typeof child === 'string') { | |
let text = document.createTextNode(child) | |
el.appendChild(text) | |
} | |
else if (Array.isArray(child)) { | |
for (const node of child) { | |
el.appendChild(node) // Will check `.dom` first. | |
} | |
} | |
else { | |
el.appendChild(child) // Ditto. | |
} | |
} | |
} | |
return el | |
} | |
else { | |
return new tag(props, children) | |
} | |
} | |
/** | |
* Override the `appendChild` function to support elements with a `.dom` property. | |
* Make sure to only replace it once. :-) | |
*/ | |
if (!Node.prototype.originalAppendChild) { | |
Node.prototype.originalAppendChild = Node.prototype.appendChild | |
Node.prototype.appendChild = function appendChild(aChild) { | |
this.originalAppendChild(aChild.dom || aChild) | |
return aChild | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment