Mini HTML/CSS/JS Code Playground (with Editors and Sandbox) in Less than 200 Bytes

Sometime back this thread on HackerNews gained quite some traction. Basically, it’s a small project called MiniCodeEditor which is a tiny and minimal version of an online code playground like CSSDeck.

My purpose here is to simply explain the 168 bytes code:

What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.

<body oninput='e.firstChild.srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'onload='for(i=3;i--;)e.innerHTML+="<textarea id=t"+i+" rows=9>"'id=e><iframe>

Note: This piece of code will work on modern browsers only (Chrome, Safari and Firefox).

Creating Code Editors

The code editors (textareas) are created by this piece of code:

onload='for(i=3;i--;)e.innerHTML+="<textarea id=t"+i+" rows=9>"'

The for loop executes thrice to append 3 textareas with IDs t[1-3] to the body. As the conditional expression i-- becomes 0 which is a falsy value, the loop ends.

Rendering the HTML/CSS/JS Code in the Iframe Sandbox

The piece of code that is responsible for concatenating all the html/css/js code from various textareas and chuck it into the iframe is this:

oninput='e.firstChild.srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'

The srcdoc attribute of the iframe referenced by e.firstChild is set to the concatenated value of the html, js and css (in that order) textareas. This happens when the input event is fired, which is raised instantly when the content of an input or textarea element is changed (event propagation).

One super interesting trick used here is this:

t2[v="value"] ... t0[v] ... t1[v]

The string value gets saved to a new variable v which is reused later. This saves exactly 1 character over:

t2.value ... t0.value ... t1.value

Cross Browser Compatibility

You’ll find a cross-browser version on the project’s webpage which looks like this:

<body id=e><script>for(i=4;--i;)e.innerHTML+="<textarea id=t"+i+" placeholder="+[,"JS","CSS","HTML"][i]+" rows=9 onkeydown='if((K=event).keyCode==9){K.preventDefault();s=this.selectionStart;this.value=this.value.substring(0,this.selectionStart)+\"\t\"+this.value.substring(this.selectionEnd);this.selectionEnd=s+1}'>"+(unescape((l=location).hash.slice(1,-1)).split("\x7F")[i-1]||"");onload=onkeyup=function(a){q=[(E=escape)(j=t1[v="value"]),E(c=t2[v]),E(h=t3[v])].join("\x7f")+1;(H=history)&&H.replaceState?H.replaceState(0,0,"#"+q):location.hash=q;I=h||c||j?h+"<script>"+j+"<\/script><style>"+c:"<pre>Result";navigator.userAgent.match(/IE|Tr/)?((D=e.lastChild.contentWindow.document).write(I),D.close()):frames[0].location.replace("data:text/html,"+escape(I))}</script><iframe>

A prettier version of this code is this:

<body id=e>
    <script>
        for (i = 4; --i;) e.innerHTML += "<textarea id=t" + i + " placeholder=" + [, "JS", "CSS", "HTML"][i] + " rows=9 onkeydown='if((K=event).keyCode==9){K.preventDefault();s=this.selectionStart;this.value=this.value.substring(0,this.selectionStart)+\"\t\"+this.value.substring(this.selectionEnd);this.selectionEnd=s+1}'>" + (unescape((l = location).hash.slice(1, -1)).split("\x7F")[i - 1] || "");
        onload = onkeyup = function (a) {
            q = [(E = escape)(j = t1[v = "value"]), E(c = t2[v]), E(h = t3[v])].join("\x7f") + 1;
            (H = history) && H.replaceState ? H.replaceState(0, 0, "#" + q) : location.hash = q;
            I = h || c || j ? h + "<script>" + j + "<\/script><style>" + c : "<pre>Result";
            navigator.userAgent.match(/IE|Tr/) ? ((D = e.lastChild.contentWindow.document).write(I), D.close()) : frames[0].location.replace("data:text/html," + escape(I))
        }
    </script>
    <iframe>

Similar to the previous version, this piece of code also starts by creating 3 textareas with keydown events that checks for the tab key to allow indentations.

This version has an interesting auto-save feature too, as you write the code. When we type in any of the boxes, it concatenates all the code with a separator which is the non-printable DEL (\x7f) character and saves them into the browser hash string. This piece is achieved by the listener attached to the load and keyup events of the window (global) object.

So even after a refresh, the code will simply break the hash string on the separator and set the values for different code boxes. The code that helps with the setting of the values is this (as a value of the textarea tag in the first line of the JS code):

(unescape((l = location).hash.slice(1, -1)).split("\x7F")[i - 1] || "");

Conclusion

This project might not have a practical usage but is really fun as there are a couple of tricks employed in order to make the code really short and yet produce some meaningful result.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

2 thoughts on “Mini HTML/CSS/JS Code Playground (with Editors and Sandbox) in Less than 200 Bytes”

  1. Hi Rishabh,
    I am novice to web development, i developed one small site with the java script, via that i’m displaying some charts on the web page; unfortunately it is not working properly.
    Actually that is mobile app developed for iphone. Now i want to debug that java script code, so would you please tell any freeware tools to debug the java script code.

Leave a Reply

Your email address will not be published. Required fields are marked *

*