Arrow Key Table Navigation

by Jason Crowther

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<p>Press <strong>a</strong> to toggle on arrow mode.</p>
<table>
<thead>
<tr>
  <th colspan="7">October 2017</th>
</tr>
<tr>
  <th>sunday</th>
  <th>monday</th>
  <th>tuesday</th>
  <th>wednesday</th>
  <th>thursday</th>
  <th>friday</th>
  <th>satday</th>
</tr>
</thead>
<tbody>
  <tr>
    <td data-d="1">1<br><a href="#" class="a">Link 1</a><br><a href="#" class="a" >Link 2</a><br><a href="#" class="a">Link 3</a> </td>
    <td data-d="2">2<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="3">3<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="4">4<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="5">5<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="6">6<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="7">7<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
  </tr>
  <tr>
    <td data-d="8">8<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="9">9<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="10">10<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="11">11<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link 3</a></td>
    <td data-d="12">12<br><a href="#" class="a">Link 1</a><br><a href="#" class="a">Link 2</a><br><a href="#" class="a">Link...

CSS

table { border-spacing: 0}
th,td { border: 1px solid black; margin: 0; padding: 1em}
.selected { background-color: yellow }

JavaScript

var arrowMode = false
var lastDay = 31
  
$(document).ready(function(){
  
  // capture keypresses on body and links that have the 'a' class
  // need the 'a' links because as they become focused, the trigger
  // from the body no longer works
  jQuery(document).keydown(function(e){
		if( e.target.nodeName == 'BODY' || $(e.target).hasClass('a') ) {
    	if( e.keyCode == 65 ) { // 'a' to toggle arrow mode
      	toggleArrowMode();
        e.preventDefault();
      } else if( e.keyCode == 39 ) { // left arrow
       	nextDay()
        e.preventDefault();
      } else if( e.keyCode == 37) { // right arrow
       	prevDay()
        e.preventDefault();
      } else if( e.keyCode == 40) { // down arrow
       	addWeek()
      	e.preventDefault();
      } else if( e.keyCode == 38) { // up arrow
       	subWeek()
        e.preventDefault();
      }
    }
  });

	// give some feedback when an event is clicked
  $('a.a').click(function(){
    alert('clicked link: ' + $(this).html() + " on day " + $(this).parent().data('d'))
  })
}); // end of ready


// turn arrowMode on/off

function toggleArrowMode() {
	if( arrowMode ) {
   	arrowMode = false;
  	clearSelected(); // turn off current selection
  } else {
  	arrowMode = true;
    selectCell(1); // always start with first day
  }
}
  
// add selected class the currently selected
// cell and focus the first link (or any other
// link if that makes more sense.)

function selectCell(cid) {
  clearSelected()
  var $c =  $("td[data-d='"+ cid +"']");
  $c.addClass('selected');
  $c.find('a').first().focus();
}

// clear the selected cell

function clearSelected() {
	$("table tbody td").removeClass('selected');
}
  
// get the id for the currently selected day

function currentDay() {
	return $("td.selected").data('d')
}
  
// figure out and select the next day, with wrap around for end of month

function nextDay() {
	var d = currentDay();
  if( d == lastDay ) {
  	d = 1;
  } else {
    d++
  }
	selectCell(d)
}
  
// figure out...