Hacker News new | ask | show | jobs
by dumindaxsb 2003 days ago
Hello!,

I'm the original owner of this tweet & new to HN. I never expected this to go crazy at this scale. A big thank you to @rukshn for sharing it here.

My apologies for the narrow requirement definition (had to limit it to 280 chars :)

What I intended was to build the UI from scratch & the logic all within JS.

Learnt a lot from all these contributions & keep 'em coming.

Since everybody is into plain JS, here's my version:

279 chars, No HTML injection/document.write(), can add, strike-through & clear the whole list

a=document;x=a.body;b=(d,t)=>{return d.appendChild(a.createElement(t))};c=(e,v)=>{e.innerHTML=v;return e};i=b(x,"input");c(b(x,"a"),"+").onclick=_=>{c(b(o,"li"),i.value).onclick=(e)=>{e.target.style.textDecoration="line-through"}};o=b(x,"ol");c(b(x,"a"),"X").onclick=_=>{c(o,'')}

https://jsbin.com/weyijorila/edit?html,output

2 comments

I like the createElement/appendChild-and-return-child and set-innerHTML-and-return-child combinations, they’re just the right level of repetition for minification.

As it stands, the use of innerHTML is bad, because it allows an injection attack (which amuses me given you said “no HTML injection”—though I know what you meant by that); you should use innerText instead. (You should always think very carefully before setting innerHTML or doing other similar tricks like the insertAdjacentHTML that I used in mine.)

There’s also some low-hanging fruit for golfing here:

• appendChild can be replaced with append (this sheds IE support, which I think is reasonable).

• You have arrow functions containing only a return statement; there’s a form that returns the expression: `a => { return b; }` can be written as just `a => b`. Also often in such golfing exercises if you have a function that has no return value, you can just drop the braces and let it return a value anyway, for two characters of savings.

• I said I liked the b and c functions, but it turns out that merging them ends up saving 7 characters in this case, because all but one of the invocations uses both.

Beyond that, I object strenuously to the use of <a onclick=…>+</a> for what is functionally a button, as it’s completely inaccessible to screen readers and the likes (it’s not focusable, isn’t announced as anything, and it doesn’t respond to the keyboard). Use <button> instead.

Here’s where I am on yours, 253 characters:

  a=document;b=(d,t,v)=>(d.append(d=a.createElement(t)),d.innerText=v,d);i=b(x=a.body,"input");b(x,"button","+").onclick=_=>b(o,"li",i.value).onclick=(e)=>e.target.style.textDecoration="line-through";o=b(x,"ol");b(x,"button","X").onclick=_=>o.innerText=""
Nice finishing touch. I think this is the shortest it could get in this approach with semantic tags.

I just learnt about insertAdjacentHTML & last variable return of arrow functions. (not using widely due to compatibility)

Also, you're absolutely right about XSS & Button. I thought innerText only removing text, keeping the <li></li> :)

So, learnt some new stuff. Thank you!

In your code, the <ol> initially outputs "undefined". So we need to change it to o=b(x,"ol","") there.

Final code: a=document;b=(d,t,v)=>(d.append(d=a.createElement(t)),d.innerText=v,d);i=b(x=a.body,"input");b(x,"button","+").onclick=_=>b(o,"li",i.value).onclick=(e)=>e.target.style.textDecoration="line-through";o=b(x,"ol","");b(x,"button","X").onclick=_=>o.innerText=""

> last variable return of arrow functions. (not using widely due to compatibility)

It’s not last variable return such as you get in expression-oriented languages like Ruby or Rust; rather, it’s that if what follows the fat arrow is not a curly brace, it’s parsed as an expression, which is made to be the value returned. So `a => { a }` is the void function, but `a => { return a }` and `a => a` are identity functions. Expressed as an approximate grammar, it’s

  arrow-function = arrow-function-parameters "=>" ( "{" *statement "}" | expression-minus-object-literals )
All forms of arrow functions were introduced at the same time, in ES6 (roughly meaning “everything since but excluding IE”). `a => { return a; }` has identical browser support to `a => a`, so if you use arrow functions you might as well switch to the expression form.
Welcome to HN community @dumindaxsb :]

Thank you for making my Sunday an awesome one