Javascript framework demos in vanilla JS
This week, I learned that Joe Gregorio has this cool project where he re-implements popular framework sample apps in vanilla JavaScript.
Inspired by his work, I decided to do something similar.
First up this week: Vue.js.
Markdown Editor
The Vue.js Examples page includes a markdown editor powered MarkedJS and Lodash.
Here’s the relevant HTML.
<div id="editor">
<textarea :value="input" @input="update"></textarea>
<div v-html="compiledMarkdown"></div>
</div>
And here’s the JavaScript to make it work.
new Vue({
el: '#editor',
data: {
input: '# hello'
},
computed: {
compiledMarkdown: function () {
return marked(this.input, { sanitize: true })
}
},
methods: {
update: _.debounce(function (e) {
this.input = e.target.value
}, 300)
}
});
I find the Vue syntax a bit weird to read, but this is short and simple, which is a bit part of the appeal of frameworks like this.
So that’s our target. We want to come in at around 15 lines of code (or less).
Vanilla JS Marked Editor
We’re still going to use MarkedJS, because converting markdown to HTML is not a trivial task. But, I think we can write something just as simple without Vue or Lodash.
First, I’m going to tweak the HTML just a touch for simplicity. I’ll give both the text editor and compiled markdown container unique IDs. I’m also going to add autofocus to the textarea
.
<textarea id="editor" autofocus></textarea>
<div id="compiled-markdown"></div>
Since we’re going to convert our text in real time as we type, let’s get the #compiled-markdown
container from the DOM and store it to a variable for faster reuse.
// Get the compiled markdown container
var compiled = document.querySelector('#compiled-markdown');
Next, we want to listen to changes on our #editor
so that we can update our compiled markdown.
Let’s use event delegation to listen to all input
events (which fire when an input
or textarea
changes in value), and filter out events that aren’t triggered by the #editor
.
// Get the compiled markdown container
var compiled = document.querySelector('#compiled-markdown');
// Listen for changes to inputs and textareas
document.addEventListener('input', function (event) {
// Only run if the change happened in the #editor
if (!event.target.matches('#editor')) return;
}, false);
Now, all that’s left to do is used MarkedJS to convert our markdown to HTML and inject it into the DOM.
The event.target
is the textarea
that triggered the event. We’ll pass it’s .value
property into MarkedJS, and use innerHTML
to update the DOM with the result.
// Get the compiled markdown container
var compiled = document.querySelector('#compiled-markdown');
// Listen for changes to inputs and textareas
document.addEventListener('input', function (event) {
// Only run if the change happened in the #editor
if (!event.target.matches('#editor')) return;
compiled.innerHTML = marked(event.target.value, { sanitize: true });
}, false);
And just like that, we have a working markdown editor with two fewer dependencies and four fewer lines of code. And that’s with white space and comments, which the Vue example doesn’t have.
If you strip those out, the vanilla JS version is just five lines of code! Who says vanilla JS has to be more verbose than a framework?
You can download this on GitHub, or play with it in a browser on JSFiddle.
What’s next?
Do you like this project? Want to see more like it?
If you have an example app built with a framework, and you want to see how it might work with vanilla JS, send me an email and let me know about it!