Understanding UTF-8
Live demo of how exactly a Unicode character encodes into UTF-8, bit by bit.
HTML
<input type="button" value="do" onclick="foo()"> source:<a href="https://en.wikipedia.org/wiki/UTF-8#Examples">UTF-8#Examples</a>
• escapes: <a href="http://xem.github.io/escape/">EscApe</a> <br>
<textarea id="inn" onkeyup="foo()">$¢€𐍈�􏿽</textarea>
<table><tbody id="data"></tbody></table>
CSS
textarea {width:95%;height:6em;}
table {background-color:#f9f9f9;border:1px solid #aaa;border-collapse:collapse;color:#000;margin:1em 0;font-size:8pt;}
th, td {border:1px solid #aaa;padding:.3em .4em;}
th {background-color:#f2f2f2;text-align:center;font-weight:700;}
code {color:black;background-color:#f9f9f9;border:1px solid #ddd;border-radius:2px;padding:1px 4px;font-family:monospace,Courier;white-space:nowrap;}
.r {color:#f00;}
.g {color:#0f0;}
.b {color:#00f;}
.m {color:#f0f;}
JavaScript
function foo() {
var txt = '';
var inn = utfarray(document.getElementById('inn').value);
var data = document.getElementById('data');
var th = '<tr><th colspan="2">Character</th><th>Binary code point</th><th>Binary UTF-8</th><th>Hexadecimal UTF-8</th></tr>';
for(var i=0;i<inn.length;i++) {
if(inn[i] > 0x1FFFFF) continue
txt += '<tr><td>' + character(inn[i]) + '</td><td><code>U+' + hex(inn[i]) + '</code></td>';
txt += '<td align="right"><code>' + chunk4(inn[i]) + '</code></td><td><code>' + binutf8(byte(inn[i])) + '</code></td><td><code>' + byte(inn[i],true).join(' ') + '</code></td></tr>\n';
}
data.innerHTML = th + txt;
}
function byte(num,color) { //array of hex strings
var arr = percent(num).replace(/^\%/,'').split('%');
for(var i=0;i<arr.length;i++) {
//arr[i] = padleft(arr[i],2,'0');
arr[i] = (color) ? '<span class="' + 'rgbm'[arr.length-i-1] + '">' + padleft(arr[i],2,'0') + '</span>' : padleft(arr[i],2,'0');
}
return arr;
}
function binutf8(byte) { //binary octets
var txt = '';
for(var i=0;i<byte.length;i++) {
var cls = 'rgbm'[byte.length-i-1];
var part = padleft(parseInt(byte[i],16).toString(2),8,'0');
if(byte.length == 1) {
txt += part.substring(0,1) + '<span class="r">' + part.substring(1,8) + '</span> ';
} else if(i > 0) {
txt += part.substring(0,2) + '<span class="' + cls + '">' + part.substring(2,8) + '</span> ';
} else {
txt += part.substring(0,byte.length+i+1) + '<span class="' + cls + '">' + part.substring(byte.length+i+1,8) + '</span> ';
}
}
return txt.replace(/ $/,'');
}
function chunk4(num) { //padded right-based 4 couplets in 7/11/16/21 bit chunks
var bin = num.toString(2);
if(bin.length < 7) bin = padleft(bin,7,'0');
if(bin.length > 7 && bin.length < 11) bin = padleft(bin,11,'0');
if(bin.length > 11 && bin.length < 16) bin = padleft(bin,16,'0');
if(bin.length > 16 && bin.length < 21) bin = padleft(bin,21,'0');
var rev = '';
for(var...