skip to Main Content

basically i am trying to get the web page to navigate between fields with arrow keys. Ive got most if it down, just that the variable I has to be increased or decreased by 1 to get the index of the array of elements accessed by class, as such:

var isFocus;

var I = 0;

const prev = document.getElementsByClassName('prev');
const curr = document.getElementsByClassName('curr');

prev[0].focus()

var isFocused1;
var isFocused2;

document.addEventListener('keydown', fX)

function fX(event) {
  key = event.key

  isFocused1 = document.activeElement.classList.contains("prev");
  isFocused2 = document.activeElement.classList.contains("curr");

  if (isFocused1 == true) {
    isFocus = prev
  } else if (isFocused2 == true) {
    isFocus = curr
  }

  if (key == 'ArrowDown' && I < 5) {
    I++;
    isFocus[I].focus();
  } else if (key == 'ArrowUp' && I > 0) {
    I--;
    isFocus[I].focus();
  }
}
<p> try selecting first column's top input box, click down 3 times to get to the fourth one, then click the second column's first input box. Now click down once and you'll see the cursor skip to the fifth box. </p>
<table>
  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>

  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>

  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>

  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>
  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>
  <tr>
    <td><input type="text" name="" class="prev"></td>
    <td><input type="text" name="" class="curr"></td>
    <td>
      <p class="mtr-Result"></p>
    </td>
  </tr>
</table>

https://jsfiddle.net/nw259to6/1/

The cursor will move down the fields, however upon switching to the other column input class = 'curr' , I‘s value keeps on iterating from whatever value it left of from. Meaning the next field to be active would be curr[I], clicking on the first input text box, then pressing down, makes the cursor skip a few input boxes.

Id like that every time i switch fields I goes back to 0 so that i can scroll from top to bottom. THX!

2

Answers


  1. If you change the last focused column, the I will be set to 0.

    So you can fill up first column, then click to the first element of the second column and start filling it up. hitting down will go to the second element in second column since I==0 after focusing to second column.

    One sorta unwanted behavior – regardless of which element you click on the other column, the focused element will be the first element.

    var isFocus;
    
    var I = 0;
    
    const prev = document.getElementsByClassName('prev');
    const curr = document.getElementsByClassName('curr');
    
    prev[0].focus()
    var lastFocused1
    var lastFocused2
    var isFocused1;
    var isFocused2;
    
    document.addEventListener('keydown', fX)
    
    function fX(event) {
      key = event.key
        
      isFocused1 = document.activeElement.classList.contains("prev");
      isFocused2 = document.activeElement.classList.contains("curr");
      
      if (isFocused1 != lastFocused1 || isFocused2 != lastFocused2) I = 0
    
      lastFocused1 = isFocused1
      lastFocused2 = isFocused2
    
    
    
      if (isFocused1 == true) {
        isFocus = prev
      } else if (isFocused2 == true) {
        isFocus = curr
      }
    
      if (key == 'ArrowDown' && I < 5) {
        I++;
        isFocus[I].focus();
      } else if (key == 'ArrowUp' && I > 0) {
        I--;
        isFocus[I].focus();
      }
    }
    <p> try selecting first column's top input box, click down 3 times to get to the fourth one, then click the second column's first input box. Now click down once and you'll see the cursor skip to the fifth box. </p>
    <table>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    </table>
    Login or Signup to reply.
  2. That’s because you’re using the same variable for both types of <input>s. Also, you need to reset the index when an element is focused.

    ['prev', 'curr'].forEach(selector => {
      // selector is either 'prev' or 'curr'
    
      // Selects all inputs with that class
      const inputs = [...document.querySelectorAll(`.${selector}`)];
      let index = 0;
      
      inputs[index].focus();
      
      // On keydown, we move focus to another <input> if possible.
      function onkeydown(event) {
        const key = event.key;
      
        if (key == 'ArrowDown' && index < 5) {
          index++;
        } else if (key == 'ArrowUp' && index > 0) {
          index--;
        }
        
        inputs[index].focus();
      }
      
      // On focus, we find the index of the target in the original list
      // which always consists of <input>s with the same class
      function onfocus(event) {
        index = inputs.indexOf(event.target);
      }
      
      // Iterate over the list, add event listeners for those <input>s
      inputs.forEach(input => {
        input.addEventListener('keydown', onkeydown);
        input.addEventListener('focus', onfocus);
      });
    });
    <p>Try selecting first column's top input box, click down 3 times to get to the fourth one, then click the second column's first input box.</p>
    <table>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
      <tr>
        <td><input type="text" name="" class="prev"></td>
        <td><input type="text" name="" class="curr"></td>
        <td>
          <p class="mtr-Result"></p>
        </td>
      </tr>
    </table>

    The above will not work if you were to override ArrowRight and ArrowLeft‘s behaviour. In such a case, you will need a 2D coordinate.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search