A TO-DO app that fits in a single tweet

Sunday morning while I was scrolling through my Twitter feed one tweet caught my eye,

The challenge was to make a todo app that fits in a single tweet, just like any other todo app, you should be able to add or remove tasks and clear the task list. I thought how hard this can get, I thought to myself this is doable just by using plain JavaScript.

So since I don’t have a laptop, what resulted was a whole day of torture having to code though my iPad on codepen.

Plain JavaScript

Soon after I started using plain JavaScript it became obvious that I was not able to make it within one tweet, the DOM manipulation was taking too much characters, document.createElements, document.getElements.

It was obvious that was not the right approach.

Using vue

Vue framework won’t require any build tools, so I don’t have to go through setting up Webpack,

Also I can easily create the DOM within the script tag using simple HTML. So that will save some characters for me in DOM manipulation.

The first version I made use the method option in Vue app to handle button clicks, the button click event will call the function in methods to add new tasks and clear the task list.

However, I was unable to reduce it to one tweet. Then I went back to in-line functions, the same methods were added to button click events inline and not within the methods section.

Also I had to change buttons to anchor tags, in order to save some characters, and I had to use emojis instead of button text to save some more characters.

I also had to drop few buttons like a button to add a task, and instead I had to go with pressing enter key to add a task instead.

So I made the final version, the JavaScript code looked like this,

See the Pen qBaXmpE by Rukshan Ranatunge (@rukshn) on CodePen.

Then I ran the code through an online JavaScript minifier and then the whole HTML though an HTML minifier, and ended up with this piece of code,

<body><script src=https://unpkg.com/vue@next></script><script>var x={data:()=>({t:[],k:""}),template:'<input @keyup.enter="t.push(k)" v-model="k"><a @click="t=[]">❎</a><p v-for="(v,i) in t"><a @click="t.splice(i,1)">?️</a>{{v}}</p>'};Vue.createApp(x).mount("body")</script>

With my fingers crossed, I copied the code on to Twitter, and guess what it fits perfectly inside a single Tweet.

https://twitter.com/JustRuky/status/1340862545322762240

And here is the code in action, link

See the Pen qBaXmpE by Rukshan Ranatunge (@rukshn) on CodePen.

What I failed to achieve

The original Tweet says, that the completed tasks should have a strike through.

But because css was costing me too much characters I had to fall back to remove completed tasks instead, but I’m sure someone will figure a solution for that as well.

At the same time, I think you can save even more characters by using mithril, because you have short-codes for DOM elements as well, but I haven’t tried mithril in awhile.

One last thing

No I didn’t waste my whole Sunday on this problem, but I had to spend few hours, thinking and trying different versions.

I would have cut back some more time if I had a laptop. Somerimes I feel like buying an old laptop and refurbishing it and installing Ubuntu on it.

Sunday well spent? Absolutely yes.

Best answer?

One thing I love about HN is the fact that there are lot of bright minds out there. Since I posted this on HN I knew it was just a matter of time since someone figures this out.

I guess this is the best answer and also ticks all the boxes, well done.

 <script>document.write(`<style>:checked+*{text-decoration:line-through}#t{display:none}</style><p id="t"><input type="checkbox"><input><div id="f"></div><p><button onclick="f.appendChild(t.cloneNode(true)).id=''">+</button><button onclick="f.innerHTML=''">×</button>`)</script>

HN link to this answer: https://news.ycombinator.com/item?id=25493533

Original thread on HN: https://news.ycombinator.com/item?id=25492302