Search code examples
javascriptaccessibilitykeyboard-events

Setting click event to next tab in container with arrow keys


I have a filter container with three tabs. The currently selected tab has class ag-tab-selected. When the container loads, the first tab is always selected and has the ag-tab-selected class. I need to be able to navigate between the tabs with the left and right arrow keys.

As the user hits the right arrow key, the ag-tab-selected class should be applied to the next tab, and if the left arrow key is hit, the ag-tab-selected class should be applied to the previous tab. The current tab should also have .click() applied to it so that when the user does hit the arrow key, the view is changed based on which tab is selected. I'm currently able to loop through the available tabs and have a trigger applied to the current one, but having trouble iterating to the previous or next with the arrow keys:

if(e.key === 'ArrowRight') {
 for(let i = 0; i < tabTriggers.length; i++){
   //on arrow, trigger currently focused ag-tab with click
   if(tabTriggers[0].classList.contains('ag-tab-selected') === true){
     tabTriggers[i].click();
   }
 }
}

Link to current fiddle: Link


Solution

  • I finished the task based on the code you provided, i also extended it with some logic so that you'd have a working example. It's available here http://jsfiddle.net/631zjmcq/

    So I defined a click handler for each tab, so that you gain some interactivity (i wanted to see the solution in action) The basis of the code you provided was working well, it just had the problem that once you've found an element, you didn't stop the loop and it ran until it reached the last element in the list. This means it clicked every element until it reached the last one, so I put a break statement into that for loop.

    To go backwards, I modified the for loop, so that this time it would loop from the end of the list backwards.

    const selectedTabClass = 'ag-tab-selected';
    
    document.querySelectorAll('.ag-tab').forEach(tab => {
        tab.addEventListener('click', e => {
        if (tab.classList.contains('ag-tab-selected')) return
    
        document.querySelector(`.${selectedTabClass}`)
            .classList.remove(selectedTabClass)
            tab.classList.add(selectedTabClass)
      })
    })
    
    document.addEventListener('keydown', e => {
      let tabTriggers = document.querySelectorAll('.ag-tab');
    
      if (e.key === 'ArrowRight') {
        for (let i = 0; i < tabTriggers.length; i++) {
          if (tabTriggers[i].classList.contains('ag-tab-selected') === true) {
            tabTriggers[i+1].click();
            break;
          }
        }
      }
    
      if (e.key === 'ArrowLeft') {
        for (let i = tabTriggers.length-1; i > 0; i--) {
          if (tabTriggers[i].classList.contains('ag-tab-selected') === true) {
            tabTriggers[i-1].click();
            break;
          }
        }
      }
    });