Navigation using keyboard arrows

2

I need to navigate through the DOM using the arrow keys. I can perform it when it goes only in two directions (up or down, front or back), but to move in the four directions I did not find a shape. I need this navigation to take into account only a certain selector, in this case the tag ' <a> ' Ex:

Source:

<body><ahref="#">teste</a> <a href="#">TESTE</a> <a href="#">teste</a> <a href="#">TESTE</a><br/>
    <a href="#">teste</a> <a href="#">TESTE</a> <a href="#">teste</a> <a href="#">TESTE</a><br/>
    <a href="#">teste</a> <a href="#">TESTE</a> <a href="#">teste</a> <a href="#">TESTE</a><br/>

    <script>
      $(document).ready(function(){
        $(document).keydown(function(e){
          switch (e.keyCode)
          {
            //esquerda
            case 37:
              var elAtivo    = document.activeElement;
              var elAnterior = $(elAtivo).prevAll('a').first();

              $(elAnterior).focus();
            break;
            //cima
            case 38:
            break;
            //direita
            case 39:
              var elAtivo   = document.activeElement;
              var elProximo = $(elAtivo).nextAll('a').first();
              $(elProximo).focus();
            break;
            //baixo
            case 40:
            break;

          }
        });
      });
    </script>
  </body>
    
asked by anonymous 21.08.2018 / 01:32

1 answer

0

You can by taking the coordinates of the items in question and checking which ones are closest.

I created a function to get the coordinates and implemented the up and down movements that were missing in your case.

It would be interesting to adopt the same pattern for all cases, so it would depend on the sequence of items in HTML , but on their position on the screen.

Follow the code:

<body>
  <a href="#">1</a> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a><br/>
  <a href="#">5</a> <a href="#">6</a> <a href="#">7</a> <a href="#">8</a><br/>
  <a href="#">9</a> <a href="#">10</a> <a href="#">11</a> <a href="#">12</a><br/>

  <script>
    $(document).ready(function () {
      $(document).keydown(function (e) {
        const elAtivo = document.activeElement;
        const as = [].slice.call($('a'));

        switch (e.keyCode) {
          //esquerda
          case 37:
            var elAnterior = $(elAtivo).prevAll('a').first();
            $(elAnterior).focus();
            break;
          //cima
          case 38:
            let elProximoCima;

            as.forEach(el => {
              if (elProximoCima === undefined)
                elProximoCima = el
              if (getOffset(el).top < getOffset(elAtivo).top &&
                getOffset(elAtivo).top - getOffset(el).top <= getOffset(elAtivo).top - getOffset(elProximoCima).top) {
                if (Math.abs(getOffset(el).left - getOffset(elAtivo).left) <=
                  Math.abs(getOffset(elProximoCima).left - getOffset(elAtivo).left))
                  elProximoCima = el
              }
            });

            $(elProximoCima).focus();
            break;
          //direita
          case 39:
            var elProximo = $(elAtivo).nextAll('a').first();
            $(elProximo).focus();
            break;
          //baixo
          case 40:
            let elProximoBaixo;

            as.forEach(el => {
              if (elProximoBaixo === undefined)
                elProximoBaixo = el
                if (getOffset(el).top > getOffset(elAtivo).top &&
                getOffset(el).top - getOffset(elAtivo).top >= getOffset(elProximoBaixo).top - getOffset(elAtivo).top) {
                if (Math.abs(getOffset(el).left - getOffset(elAtivo).left) <=
                  Math.abs(getOffset(elProximoBaixo).left - getOffset(elAtivo).left))
                  elProximoBaixo = el
              }
            });
            $(elProximoBaixo).focus();
            break;

        }
      });
    });

    function getOffset(el) {
      const rect = el.getBoundingClientRect();
      return {
        left: rect.left + window.scrollX,
        top: rect.top + window.scrollY
      };
    }
  </script>
</body>

I've also inserted a CSS to make the change more visual:

<style>
    a {
      margin: 30px;
    }

    a:focus {
      color: red;
    }
</style>
    
22.08.2018 / 04:59