I am trying to teach myself JavaScript. I've read some online tutorials and watched some Douglas Crockford videos and decided to dive right in.
I made a little table editor in JavaScript: there's been quite a bit of fighting with the DOM but I think I've mostly figured this out.
Am I on the right track? Any comments on what I could do better or have misconceptions about?
HTML:
<!DOCTYPE html><html>
<head><title>Learning JS</title><style>
div.body { padding-top: 30px; padding-left: 10%; }
table { border-collapse:collapse; }
td { border-top: 2px solid #ddd; padding: 0 16px; }
td:focus { outline-style: none; box-shadow: 0px 0px 4px 4px #87CEEB }
</style>
</head>
<body><div class=body>
<table><tr>
<th>Name</th>
<th>Value</th>
<th>Col3</th>
<th>Col4</th>
<th>Col5</th>
</tr><tr>
<td></td>
<td>Testing, testing, 123</td>
<td>Another Column</td>
<td>test</td>
<td>end</td>
</tr><tr>
<td></td>
<td>This Time</td>
<td>nothing else</td>
<td>testing some more</td>
<td></td>
</tr><tr>
<td>3</td>
<td>This other time</td>
<td>nothing more</td>
<td>test this</td>
<td></td>
</tr>
</table>
</div>
<script src=te.js></script>
</body>
</html>
JavaScript:
"use strict";
window.onload = function() {
var firstColumn;
var lastColumn;
{
let tables=document.getElementsByTagName("table");
var width=tables[0].rows[0].cells.length;
let td=document.getElementsByTagName("td");
for (let i=0,len=td[0].parentNode.cells.length;i<len;++i) {
if (firstColumn===undefined) firstColumn=i;
lastColumn=i;
}
for (let i = 0;i < td.length; ++i) {
td[i].onkeydown = kbhandle;
if (!td[i].className) td[i].setAttribute("contentEditable", true);
}
}
var tabpos=1;
function kbhandle(e) {
switch (e.which) {
case 9:
if (tabpos>this.cellIndex) tabpos=this.cellIndex;
break;
case 13:
if (e.shiftKey || e.altKey || e.ctrlKey) break;
return function(that) {
let row=that.parentNode;
if (row.rowIndex < row.parentNode.rows.length-1) row.nextSibling.cells[tabpos].focus();
return false;
} (this);
case 37: //Left Arrow
return function(that,sel) {
if (e.altKey || (!sel.anchorOffset && (sel.focusNode.tagName==='TD' || sel.focusNode.previousSibling === null))) {
if (that.cellIndex > firstColumn) {
tabpos=that.cellIndex-1;
that.parentNode.cells[tabpos].focus();
if (sel.rangeCount) {
let node;
let range = sel.getRangeAt(0);
if (node = that.parentNode.cells[that.cellIndex-1].lastChild) {
range.setStart(node,node.length);
range.setEnd(node,node.length);
sel.removeAllRanges(); //needed for Webkit
sel.addRange(range); //needed for Webkit
}
}
}
return false;
}
return true;
} (this,window.getSelection());
case 38: //Up Arrow
return function(that,sel) {
if (e. ctrlKey || e.altKey || (!sel.anchorOffset && (sel.focusNode.tagName==='TD' || sel.focusNode.previousSibling === null))) {
tabpos=that.cellIndex;
that.parentNode.previousSibling.cells[that.cellIndex].focus();
if (sel.rangeCount) {
let node;
let range = sel.getRangeAt(0);
if ((node = that.parentNode.previousSibling.cells[that.cellIndex].lastChild) && node.parentElement.tagName === 'TD') {
range.setStart(node,node.length);
range.setEnd(node,node.length);
sel.removeAllRanges(); //needed for Webkit
sel.addRange(range); //needed for Webkit
}
}
return false;
}
return true;
} (this,window.getSelection());
case 39: //Right Arrow
return function(that,sel) {
let len=sel.focusNode.textContent.length;
if (that.cellIndex<lastColumn && (e.altKey || !len || (len === sel.anchorOffset && sel.focusNode.nextSibling === null))) {
tabpos=that.cellIndex+1;
that.parentNode.cells[that.cellIndex+1].focus();
return false;
}
return true;
} (this,window.getSelection());
case 40: //Down Arrow
return function(that,sel) {
let len=sel.focusNode.textContent.length;
if (e. ctrlKey || e.altKey || !len || (len === sel.anchorOffset && sel.focusNode.nextSibling === null)) {
let row=that.parentNode;
tabpos=that.cellIndex;
if (row.rowIndex < row.parentNode.rows.length-1) row.nextSibling.cells[that.cellIndex].focus();
return false;
}
return true;
} (this,window.getSelection());
}
return true;
}
}