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){
                       ...