Skip to content

Instantly share code, notes, and snippets.

@frzi
Last active April 3, 2017 09:32
Show Gist options
  • Save frzi/346887b3cf2426628b0f72c354ac8f59 to your computer and use it in GitHub Desktop.
Save frzi/346887b3cf2426628b0f72c354ac8f59 to your computer and use it in GitHub Desktop.
A quick and dirty JSX function.
{
"plugins": [
["transform-react-jsx", {
"pragma": "document.createCustomElement"
}]
]
}
/**
* © 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