MiniCodeEditor: jsFiddle in as few bytes as possible

Created: 2014-01-22 — modified: 2014-01-22 — tags: javascript

probably you've already heard about MiniCodeEditor — jsFiddle implementation in 161+ bytes. Below is my addition to that jsgolf

Let's start with "minimal" version presented on their site (168 bytes):
data:text/html,<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>
First thing, let's change oninput event to onchange to prevent things like for(;;) killing the browser (184 bytes):
data:text/html,<body onchange='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>
Now let's add some very basic style. We'll set CSS property of all things to occupy quarter of a screen and let the browser do layout for us. We use 49% instead of 50% to compensate for border sizes which we don't care to reset.
data:text/html,<body onchange='e.firstChild.srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'onload='for(i=3;i--;)e.innerHTML+="<textarea id=t"+i+">"'id=e><iframe></iframe><style>body>*{width:49%;height:48%}
But we want the iframe to be in bottom-right corner, like in original jsFiddle, so in DOM tree it has to be last, so we have to add it after all textareas in body onload event. We will also change body onchange event to use lastChild instead of firstChild:
data:text/html,<body onchange='e.lastChild.srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'onload='for(j=3;j--;)e.innerHTML+="<textarea id=t"+j+">";e.innerHTML+="<iframe></iframe>"'id=e><style>body>*{width:49%;height:48%}
To save some characters while typing e.innerHTML, we'll save 'innerHTML' to a variable on a first use, and use this variable as index for e: (233 bytes):
data:text/html,<body onchange='e.lastChild.srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">";e[i]+="<iframe></iframe>"'id=e><style>body>*{width:49%;height:48%}

now let's add "data" link to share result with friends. Since we can't use lastChild anymore, we'll have to use children[4] to address the iframe.
data:text/html,<body onchange='e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">";e[i]+="<iframe></iframe><br><a id=w>link"'id=e><style>body>*{width:49%;height:48%}
We'll use assignment result to assign same value to several variables (like a=b=1 assigns same value to several variables). (279 bytes):
data:text/html,<body onchange='w.href="data:text/html,"+(e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v])'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">";e[i]+="<iframe></iframe><br><a id=w>link"'id=e><style>body>*{width:49%;height:48%}

now let's also add "fiddle" link to let our friends edit the result. It will be almost like a quine (a program which prints itself): a page which, when edited, will produce a link to an edited version of itself. To do this, first let's add a "load" function which will add some contents to textareas. The most obvious place to do that is when generating them
data:text/html,<body onchange='w.href="data:text/html,"+(e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]);'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">"+["","",""][j];e[i]+="<iframe></iframe><br><a id=w>link"'id=e><style>body>*{width:49%;height:48%}
now let's add a link, which href attribute will be computed as this: get current URL, and replace arguments to "load" function with real data:
data:text/html,<body onchange='w.href="data:text/html,"+(e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]);r.href=(""+location).replace(/\[".*"\]/,JSON.stringify([t0[v],t1[v],t2[v]]))'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">"+["","",""][j];e[i]+="<iframe></iframe><br><a id=w>link</a> <a id=r>fiddle";'id=e><style>body>*{width:49%;height:48%}
to be very nice, let's also rename "link" to "data", and load the generated HTML to iframe by calling onchange event handler from the onload event (403 bytes):
data:text/html,<body onchange='w.href="data:text/html,"+(e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]);r.href=(""+location).replace(/\[".*"\]/,JSON.stringify([t0[v],t1[v],t2[v]]))'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">"+["","",""][j];e[i]+="<iframe></iframe><br><a id=w>data</a> <a id=r>fiddle";e.onchange()'id=e><style>body>*{width:49%;height:48%}
Above code produces wrong links if your text contains hash # or quote ' characters, so let's properly escape input. Final version (531 byte):
data:text/html,<body onchange='w.href=(d="data:text/html")+","+(e.children[4].srcdoc=t2[v="value"]+"<script>"+t0[v]+"</script><style>"+t1[v]).replace("%23","%2523");r.href=d+";base64,"+btoa(x=((l=""+location)[14]==","?unescape(l.slice(15)):atob(l.slice(22))).replace(/\[".*"\]/,JSON.stringify([btoa(t0[v]),btoa(t1[v]),btoa(t2[v])])))'onload='for(j=3;j--;)e[i="innerHTML"]+="<textarea id=t"+j+">"+atob(["","",""][j]);e[i]+="<iframe></iframe><br><a id=w>data</a> <a id=r>fiddle";e.onchange()'id=e><style>body>*{width:49%;height:48%}
Note: to try them out, just copy-paste above data: URLs to your browser's address bar!