Truth table

by BaliBalo

CSS

table
{
    border-collapse: collapse;
}
th, td
{
    border: 1px solid #d8d8d8;
    width: 40px;
    height: 30px;
    text-align: center;
    font-weight: normal;
    background: white;
    outline: none;
}
th
{
    text-transform: lowercase;
    color: #4b4b4b;
    font-style: italic;
}
.first-output
{
    border-left: double 3px #d8d8d8;
}
.true
{
    background: #fdfbec;
}
.false
{
    background: #ffeee6;
}

JavaScript

var columns = {
    inputs: [
        'O1', 'O2', 'O3'
    ],
    outputs: [
        'A','B'
    ]
};
var il = columns.inputs.length, ol = columns.outputs.length, tl = il + ol;
var n = Math.pow(2, il);
var table = document.createElement('table');
var head = document.createElement('tr');
var i, j, row, cell, isTrue;
for(i = 0; i < il; i++)
{
    cell = document.createElement('th');
    cell.textContent = columns.inputs[i];
    head.appendChild(cell);
}
for(i = 0; i < ol; i++)
{
    cell = document.createElement('th');
    if(!i)
        cell.className = 'first-output';
    cell.textContent = columns.outputs[i];
    head.appendChild(cell);
}
table.appendChild(head);
for(i = 0; i < n; i++)
{
    row = document.createElement('tr');
    for(j = il; j-- > 0;)
    {
        cell = document.createElement('td');
        isTrue = ((i >> j) & 1);
        cell.textContent = isTrue ? 'T' : 'F';
        cell.className = isTrue ? 'true' : 'false';
        row.appendChild(cell);
    }
    for(j = 0; j < ol; j++)
    {
        cell = document.createElement('td');
        if(!j)
            cell.className = 'first-output';
        cell.contentEditable = true;
        cell.onkeydown = cellOnKeydown;
        row.appendChild(cell);
    }
    table.appendChild(row);
}
document.body.appendChild(table);

function nextCell(cell)
{
    var nRow = cell.parentNode.nextSibling;
    return cell.nextSibling || (nRow && nRow.children[il]) || cell;
}
function cellOnKeydown(e)
{
    var nRow, nCell;
    switch(e.keyCode)
    {
        case 9:
        case 13:
        case 32:
            nextCell(this).focus();
            break;
        case 37:
            nCell = this.previousSibling;
            if(nCell) nCell.focus();
            break;
        case 38:
            nRow = this.parentNode.previousSibling;
            if(nRow && nRow.firstChild.tagName == 'TD')
                nRow.getElementsByTagName('td')[this.cellIndex].focus();
            break;
        case 39:
            nCell =...