Abra.js

Elliot Plant
2 min readMay 11, 2020

--

Static page example for Abra.js

I love making simple tools, and my favorite tools for making simple tools is HTML + JS. Something I run into every time in these small projects is creating and appending DOM nodes, a problem for which there are 5 trillion solutions. In a big project, one might use React to solve this problem. In a medium project, one might use jQuery to solve this problem. But what about small projects? Like really small projects with no dependencies?

My favorite solution has been to use template strings:

someParentElement.innerHTML = `<p>Lorem to the Ipsum</p>`

Nice. Awesome. Template strings are cool. My text editor even knows how to highlight the stuff in the template string. It even works with nested template strings:

const favoriteBerries = [
{
name: 'blueberry',
color: 'blue'
},
{
name: 'strawberry',
color: 'red'
}
];
someParentElement.innerHTML = `
<ul>
${
favoriteBerries
.map(berry => `
<li style="color: ${berry.color}">
${berry.name}
</li>
`)
.join('\n')
}
</ul>
`;

Still pretty cool. It looks a bit like JSX, and we’re still using vanilla. But I don’t love double (or triple…) nesting template strings. Also, we lose a lot of the power of our editors (like linters) inside of template strings. But what about binding functions?

window.clickityClick = function(event) {
console.log('Click click!')
}
someParentElement.innerHTML = `
<button onclick="clickityClick(event)">
Click Here
</button>
<button id="the-second-button">
Or Click Here
</button>
`
const secondButton = document.querySelector('#the-second-button')
secondButton.onclick = window.clicktyClick;

That’s rough. We have to either use the name of the function on the window to call it from our template string or query for it after we create it. Both ways suck.

Wouldn’t it be nice if we could create elements with JavaScript objects? This is how React started (sort of) and it’s what Abra does:

const listItems = favoriteBerries.map(berry => abra.li({
style: {
color: berry.color
}
}, berry.name)
)
const list = abra.ul({ id: 'berry-list' }, ...listItems)
someParentElement.appendChild(list)

Does it look better? In some ways. It loses the JSX feel of HTML-in-your-JS, but it makes the DOM-nodes-are-just-JS-objects thing way more clear.

I made Abra because I was tired of querying for elements I had just created, and I would be pleasantly shocked if other people found it useful.

Use it if you want, but please don’t use it if you are already using jQuery or React. Those are bigger, more powerful tools that solve this problem more completely. Use Abra if you just want to copy a few lines of JS into your project to make creating elements easier.

--

--