JSFiddle - React, Tailwind, and code Playground
by kpowz
HTML
<table id="navigableTable">
<tr>
<td><input id="a1" /></td>
<td></td>
<td><input /></td>
<td><input /></td>
<td><input disabled /></td>
</tr>
<tr>
<td><input /></td>
<td><input disabled/></td>
<td></td>
<td><input /></td>
<td><input /></td>
</tr>
<tr>
<td><input /></td>
<td><input disabled/></td>
<td><input disabled/></td>
<td></td>
<td><input /></td>
</tr>
<tr>
<td></td>
<td><input /></td>
<td><input disabled/></td>
<td><input /></td>
<td><input /></td>
</tr>
<tr>
<td><input /></td>
<td></td>
<td><input /></td>
<td><input /></td>
<td><input disabled/></td>
</tr>
</table>
<!-- a plain cell cannot recieve focus -->
<table>
<tr><td>a1</td><td>b1</td><td>c1</td>
</tr>
<tr><td>a2</td><td>b2</td><td>c2</td>
</tr>
<tr><td>a3</td><td>b3</td><td>c3</td>
</tr>
<tr><td>a4</td><td>b4</td><td>c4</td>
</tr>
</table>
<form>
<input type="number"></input>
<input type="text"></input>
<button>form button</button>
</form>
JavaScript
(function($) {
var eligibleRowSelector = 'tr:has( td:has(input:enabled))';
var eligibleRowInputSelector = 'td:has(input:enabled)';
var nextRowWithEligibleInputs = function(current){
return $(current).closest('tr').nextUntil('table', eligibleRowSelector).first();
}
var priorRowWithEligibleInputs = function(current){
return $(current).closest('tr').prevUntil('table', eligibleRowSelector).first();
}
var nextCellWithEligibleInputs = function(row){
return row.find(eligibleRowInputSelector).first();
}
var priorCellWithEligibleInputs = function(row){
return row.find(eligibleRowInputSelector).last();
}
$.fn.keysNavigation = function() {
if (!this.is( "table" ) ) {
console.warn("keysNavigation not applied. Must be called on <table> element");
return;
}
this.find('input').keyup(function(e){
e = e || window.event;
switch(e.which || e.keyCode) {
case 37: // left
alert("left!");
var eligibleInRow = $(this).closest('td').prevUntil('tr', eligibleRowInputSelector);
if(eligibleInRow.length > 0){
eligibleInRow.first().find('input').focus();
}else{
//current functionality doesn't do this
alert('beginning of row');
priorCellWithEligibleInputs(priorRowWithEligibleInputs(this)).find('input').focus();
}
break;
case 38: // up
alert("up!");
var eligibleInCol = $(this).closest('tr').prevUntil('table', 'tr:has( td:eq('+$(this).closest('td').index()+'):has(input:enabled))');
if(eligibleInCol.length > 0){
...