NVA
NVA

Reputation: 1692

Setting focus on table row elements

I have a table list of items that I want to be able to scroll through using the keyboard up and down buttons. I am currently able to get the similar desired effect of moving down the list with the tabindex attribute. I am also using ng repeat to generate the instances of the elements. Tips or clues on how to achieve being able to focus and scroll up and down the list by using the up and down keys?

Sample code below.

table ng-if="!toolbarCtrl.loadingContacts" class="table dataTable hover" id="table3">
                <tbody role="alert" aria-live="polite" aria-relevant="all">
                    <tr class="pointer" tabindex="0" ng-repeat="contact in toolbarCtrl.contactEntities | filter:toolbarCtrl.toolbarSearchStringAfterDelay | orderBy: toolbarCtrl.tab == toolbarCtrl.tabs.RECENT ? '-dateSeen' : (toolbarCtrl.tab == toolbarCtrl.tabs.ALL ? '+data.fileAs' : '')"
                        ng-class="" ng-if="toolbarCtrl.toolbarSearchStringAfterDelay" ng-click="toolbarCtrl.selectContact(contact)"> 
                        <td rel="popover_dark" ng-class="contact.loading ? 'contactDisabled' : '' " data-container="body" data-toggle="popover" data-placement="right" data-content="" data-original-title="" title="" class="sorting_1 has_popover">
                        </td>
                    </tr>
                </tbody>
            </table>

I mutated your checkKey function to become this

 controller.checkKey = function (event) {
        $("tr[tabindex=0]").focus();
        var event = window.event;
        if (event.keyCode == 40) { //down
            var idx = $("tr:focus").attr("tabindex");
            idx++;
            if (idx > 6) {
                idx = 0;
            }
            $("tr[tabindex=" + idx + "]").focus();
        }
        if (event.keyCode == 38) { //up
            var idx = $("tr:focus").attr("tabindex");
            idx--;
            if (idx < 0) {
                idx = 6;
            }
            $("tr[tabindex=" + idx + "]").focus();
        }
    }

I'm close but its skipping straight to the last element. Does this look right?

Upvotes: 6

Views: 26300

Answers (3)

Charles Owen
Charles Owen

Reputation: 2840

There's an easier way without using the indexes. You can merely use nextElementSibling and previousElementSibling. This example is adopted for selecting the table header instead. I'm just using plain ole JavaScript:

<!DOCTYPE html>
<html>
<body>
<table>
<thead>
    <tr>
        <th tabindex="0">Col 1</th>
        <th tabindex="1">Col 2</th>
    </tr>
</thead>
<tbody>
    <tr>
        <td>first row</td>
        <td>first row</td>
    </tr>
    <tr>
        <td>second row</td>
        <td>first row</td>
    </tr>
    <tr>
        <td>third row</td>
        <td>first row</td>
    </tr>
</tbody>
</table>
<script>
const d = document;
d.addEventListener("DOMContentLoaded", function() {

d.querySelector("th[tabindex='0']").focus();
  
d.addEventListener("keydown", function (event) {
    const t = event.target;
    const k = event.keyCode;
    if (k === 40) { //right
        const next = t.nextElementSibling;
        if (next) { next.focus(); }
    } else if (k === 38) { //left 
        const prev = t.previousElementSibling;
        if (prev) { prev.focus(); }
    }
});
});
</script>
</body>
</html>

Upvotes: 0

NVA
NVA

Reputation: 1692

This was the approach that I used. It operates the jquery focus on a custom id that is created using the name and angular index. The preventDefault is merely because the up and down keys were also shifting my page up and down, this gets rid of that.

controller.checkKey = function (event, index) {
        event.preventDefault();
        if (event.keyCode === 40) {
            $('#item-' + (++index)).focus();
        }
        if (event.keyCode === 38) {
            $('#item-' + (--index)).focus();
        }
    };

This approach works well for angular paradigm and the jquery examples above are great too.

Upvotes: 0

mjw
mjw

Reputation: 1206

Here is a little technique for handling the keydown events for up/down arrows to navigate your table rows (<tr>). You may need to tweak the upper and lower tabindex handling from your generated data but that's on you. GL!

(jsfiddle: https://jsfiddle.net/qkna8jgu/2/ )

Sample HTML:

<table>
  <tr tabindex="0">
    <td>first row</td>
  </tr>
  <tr tabindex="1">
    <td>second row</td>
  </tr>
  <tr tabindex="2">
    <td>third row</td>
  </tr>
  <tr tabindex="3">
    <td>fourth row</td>
  </tr>
  <tr tabindex="4">
    <td>fifth row</td>
  </tr>
  <tr tabindex="5">
    <td>sixth row</td>
  </tr>
  <tr tabindex="6">
    <td>seventh row</td>
  </tr>
</table>

jQuery:

$(document).ready(function() {
    $("tr[tabindex=0]").focus();    
    document.onkeydown = checkKey;
});

function checkKey(e) {
    var event = window.event ? window.event : e;
    if(event.keyCode == 40){ //down
      var idx = $("tr:focus").attr("tabindex");
      idx++;
      if(idx > 6){
        idx = 0;
      }
      $("tr[tabindex="+idx+"]").focus();
    }
    if(event.keyCode == 38){ //up
      var idx = $("tr:focus").attr("tabindex");
      idx--;
      if(idx < 0){
        idx = 6;
      }
      $("tr[tabindex="+idx+"]").focus();      
    }
}

Upvotes: 4

Related Questions