需要帮助重置我在函数外部声明并在函数内部迭代的变量吗?

huangapple go评论96阅读模式
英文:

Need help resetting variable I declared outside a function and iterated inside it?

问题

基本上我试图让网页能够使用箭头键在字段之间导航。我已经完成了大部分,只是变量 I 必须增加或减少 1 才能获得通过类访问的元素数组的索引,如下所示:

  1. var isFocus;
  2. var I = 0;
  3. const prev = document.getElementsByClassName('prev');
  4. const curr = document.getElementsByClassName('curr');
  5. prev[0].focus()
  6. var isFocused1;
  7. var isFocused2;
  8. document.addEventListener('keydown', fX)
  9. function fX(event) {
  10. key = event.key
  11. isFocused1 = document.activeElement.classList.contains("prev");
  12. isFocused2 = document.activeElement.classList.contains("curr");
  13. if (isFocused1 == true) {
  14. isFocus = prev
  15. } else if (isFocused2 == true) {
  16. isFocus = curr
  17. }
  18. if (key == 'ArrowDown' && I < 5) {
  19. I++;
  20. isFocus[I].focus();
  21. } else if (key == 'ArrowUp' && I > 0) {
  22. I--;
  23. isFocus[I].focus();
  24. }
  25. }
  1. <p>尝试选择第一列的顶部输入框,向下点击 3 次以到达第四个输入框,然后点击第二列的第一个输入框。现在向下点击一次,你会看到光标跳到第五个框。 </p>
  2. <table>
  3. <tr>
  4. <td><input type="text" name="" class="prev"></td>
  5. <td><input type="text" name="" class="curr"></td>
  6. <td>
  7. <p class="mtr-Result"></p>
  8. </td>
  9. </tr>
  10. <tr>
  11. <td><input type="text" name="" class="prev"></td>
  12. <td><input type="text" name="" class="curr"></td>
  13. <td>
  14. <p class="mtr-Result"></p>
  15. </td>
  16. </tr>
  17. <tr>
  18. <td><input type="text" name="" class="prev"></td>
  19. <td><input type="text" name="" class="curr"></td>
  20. <td>
  21. <p class="mtr-Result"></p>
  22. </td>
  23. </tr>
  24. <tr>
  25. <td><input type="text" name="" class="prev"></td>
  26. <td><input type="text" name="" class="curr"></td>
  27. <td>
  28. <p class="mtr-Result"></p>
  29. </td>
  30. </tr>
  31. <tr>
  32. <td><input type="text" name="" class="prev"></td>
  33. <td><input type="text" name="" class="curr"></td>
  34. <td>
  35. <p class="mtr-Result"></p>
  36. </td>
  37. </tr>
  38. <tr>
  39. <td><input type="text" name="" class="prev"></td>
  40. <td><input type="text" name="" class="curr"></td>
  41. <td>
  42. <p class="mtr-Result"></p>
  43. </td>
  44. </tr>
  45. </table>
英文:

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:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

  1. var isFocus;
  2. var I = 0;
  3. const prev = document.getElementsByClassName(&#39;prev&#39;);
  4. const curr = document.getElementsByClassName(&#39;curr&#39;);
  5. prev[0].focus()
  6. var isFocused1;
  7. var isFocused2;
  8. document.addEventListener(&#39;keydown&#39;, fX)
  9. function fX(event) {
  10. key = event.key
  11. isFocused1 = document.activeElement.classList.contains(&quot;prev&quot;);
  12. isFocused2 = document.activeElement.classList.contains(&quot;curr&quot;);
  13. if (isFocused1 == true) {
  14. isFocus = prev
  15. } else if (isFocused2 == true) {
  16. isFocus = curr
  17. }
  18. if (key == &#39;ArrowDown&#39; &amp;&amp; I &lt; 5) {
  19. I++;
  20. isFocus[I].focus();
  21. } else if (key == &#39;ArrowUp&#39; &amp;&amp; I &gt; 0) {
  22. I--;
  23. isFocus[I].focus();
  24. }
  25. }

<!-- language: lang-html -->

  1. &lt;p&gt; try selecting first column&#39;s top input box, click down 3 times to get to the fourth one, then click the second column&#39;s first input box. Now click down once and you&#39;ll see the cursor skip to the fifth box. &lt;/p&gt;
  2. &lt;table&gt;
  3. &lt;tr&gt;
  4. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  5. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  6. &lt;td&gt;
  7. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  8. &lt;/td&gt;
  9. &lt;/tr&gt;
  10. &lt;tr&gt;
  11. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  12. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  13. &lt;td&gt;
  14. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  15. &lt;/td&gt;
  16. &lt;/tr&gt;
  17. &lt;tr&gt;
  18. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  19. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  20. &lt;td&gt;
  21. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  22. &lt;/td&gt;
  23. &lt;/tr&gt;
  24. &lt;tr&gt;
  25. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  26. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  27. &lt;td&gt;
  28. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  29. &lt;/td&gt;
  30. &lt;/tr&gt;
  31. &lt;tr&gt;
  32. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  33. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  34. &lt;td&gt;
  35. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  36. &lt;/td&gt;
  37. &lt;/tr&gt;
  38. &lt;tr&gt;
  39. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  40. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  41. &lt;td&gt;
  42. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  43. &lt;/td&gt;
  44. &lt;/tr&gt;
  45. &lt;/table&gt;

<!-- end snippet -->

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

The cursor will move down the fields, however upon switching to the other column input class = &#39;curr&#39; , 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!

答案1

得分: 1

因为您在两种类型的 <input> 上都使用了相同的变量。此外,当焦点在元素上时,您需要重置索引。

  1. ['prev', 'curr'].forEach(selector => {
  2. // selector 是 'prev' 或 'curr'
  3. // 选择所有具有该类的输入框
  4. const inputs = [...document.querySelectorAll(`.${selector}`)];
  5. let index = 0;
  6. inputs[index].focus();
  7. // 在按键按下时,如果可能,将焦点移动到另一个 <input>
  8. function onkeydown(event) {
  9. const key = event.key;
  10. if (key == 'ArrowDown' && index < 5) {
  11. index++;
  12. } else if (key == 'ArrowUp' && index > 0) {
  13. index--;
  14. }
  15. inputs[index].focus();
  16. }
  17. // 在焦点上时,我们找到原始列表中目标的索引,该列表始终由具有相同类的 <input> 组成
  18. function onfocus(event) {
  19. index = inputs.indexOf(event.target);
  20. }
  21. // 遍历列表,为这些 <input> 添加事件监听器
  22. inputs.forEach(input => {
  23. input.addEventListener('keydown', onkeydown);
  24. input.addEventListener('focus', onfocus);
  25. });
  26. });
  1. <p>尝试选择第一列的顶部输入框,点击三次向下箭头以到达第四个输入框,然后点击第二列的第一个输入框。</p>
  2. <table>
  3. <tr>
  4. <td><input type="text" name="" class="prev"></td>
  5. <td><input type="text" name="" class="curr"></td>
  6. <td>
  7. <p class="mtr-Result"></p>
  8. </td>
  9. </tr>
  10. <tr>
  11. <td><input type="text" name="" class="prev"></td>
  12. <td><input type="text" name="" class="curr"></td>
  13. <td>
  14. <p class="mtr-Result"></p>
  15. </td>
  16. </tr>
  17. <tr>
  18. <td><input type="text" name="" class="prev"></td>
  19. <td><input type="text" name="" class="curr"></td>
  20. <td>
  21. <p class="mtr-Result"></p>
  22. </td>
  23. </tr>
  24. <tr>
  25. <td><input type="text" name="" class="prev"></td>
  26. <td><input type="text" name="" class="curr"></td>
  27. <td>
  28. <p class="mtr-Result"></p>
  29. </td>
  30. </tr>
  31. <tr>
  32. <td><input type="text" name="" class="prev"></td>
  33. <td><input type="text" name="" class="curr"></td>
  34. <td>
  35. <p class="mtr-Result"></p>
  36. </td>
  37. </tr>
  38. <tr>
  39. <td><input type="text" name="" class="prev"></td>
  40. <td><input type="text" name="" class="curr"></td>
  41. <td>
  42. <p class="mtr-Result"></p>
  43. </td>
  44. </tr>
  45. </table>

如果要覆盖 ArrowRightArrowLeft 的行为,则上面的代码不起作用。在这种情况下,您将需要一个二维坐标。

英文:

That's because you're using the same variable for both types of &lt;input&gt;s. Also, you need to reset the index when an element is focused.

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

  1. [&#39;prev&#39;, &#39;curr&#39;].forEach(selector =&gt; {
  2. // selector is either &#39;prev&#39; or &#39;curr&#39;
  3. // Selects all inputs with that class
  4. const inputs = [...document.querySelectorAll(`.${selector}`)];
  5. let index = 0;
  6. inputs[index].focus();
  7. // On keydown, we move focus to another &lt;input&gt; if possible.
  8. function onkeydown(event) {
  9. const key = event.key;
  10. if (key == &#39;ArrowDown&#39; &amp;&amp; index &lt; 5) {
  11. index++;
  12. } else if (key == &#39;ArrowUp&#39; &amp;&amp; index &gt; 0) {
  13. index--;
  14. }
  15. inputs[index].focus();
  16. }
  17. // On focus, we find the index of the target in the original list
  18. // which always consists of &lt;input&gt;s with the same class
  19. function onfocus(event) {
  20. index = inputs.indexOf(event.target);
  21. }
  22. // Iterate over the list, add event listeners for those &lt;input&gt;s
  23. inputs.forEach(input =&gt; {
  24. input.addEventListener(&#39;keydown&#39;, onkeydown);
  25. input.addEventListener(&#39;focus&#39;, onfocus);
  26. });
  27. });

<!-- language: lang-html -->

  1. &lt;p&gt;Try selecting first column&#39;s top input box, click down 3 times to get to the fourth one, then click the second column&#39;s first input box.&lt;/p&gt;
  2. &lt;table&gt;
  3. &lt;tr&gt;
  4. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  5. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  6. &lt;td&gt;
  7. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  8. &lt;/td&gt;
  9. &lt;/tr&gt;
  10. &lt;tr&gt;
  11. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  12. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  13. &lt;td&gt;
  14. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  15. &lt;/td&gt;
  16. &lt;/tr&gt;
  17. &lt;tr&gt;
  18. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  19. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  20. &lt;td&gt;
  21. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  22. &lt;/td&gt;
  23. &lt;/tr&gt;
  24. &lt;tr&gt;
  25. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  26. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  27. &lt;td&gt;
  28. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  29. &lt;/td&gt;
  30. &lt;/tr&gt;
  31. &lt;tr&gt;
  32. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  33. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  34. &lt;td&gt;
  35. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  36. &lt;/td&gt;
  37. &lt;/tr&gt;
  38. &lt;tr&gt;
  39. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;prev&quot;&gt;&lt;/td&gt;
  40. &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;&quot; class=&quot;curr&quot;&gt;&lt;/td&gt;
  41. &lt;td&gt;
  42. &lt;p class=&quot;mtr-Result&quot;&gt;&lt;/p&gt;
  43. &lt;/td&gt;
  44. &lt;/tr&gt;
  45. &lt;/table&gt;

<!-- end snippet -->

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.

答案2

得分: 1

你可以使导航与键盘按键的行和列数量无关 - 独立于keydown处理程序中的行和列计数:

  1. const inputCols = document.querySelector("input#colCount");
  2. const inputRows = document.querySelector("input#rowCount");
  3. inputCols.addEventListener("input", buildTable);
  4. inputRows.addEventListener("input", buildTable);
  5. buildTable();
  6. function buildTable() {
  7. const html = Array.from({length: inputRows.value},
  8. _ =>
  9. "<tr>" +
  10. Array.from({length: inputCols.value},
  11. _ => "<td><input></td>"
  12. ).join("") +
  13. "</tr>"
  14. )
  15. .join("");
  16. const table = document.querySelector("table");
  17. table.innerHTML = html;
  18. table.querySelector("input").focus();
  19. }
  20. document.addEventListener("keydown", ({key}) => {
  21. const delta = { ArrowDown: 1, ArrowUp: -1 }[key];
  22. if (!delta) {
  23. return; // 不是箭头上/下键
  24. }
  25. const table = document.querySelector("table");
  26. const focused = table.querySelector("input:focus");
  27. if (!focused) {
  28. table.querySelector("input").focus(); // 焦点放在第一个输入框上
  29. return;
  30. }
  31. // 查找具有给定列数的下一个输入框
  32. const colCount = table.querySelectorAll("tr:first-child > td > input").length;
  33. const inputs = [...table.querySelectorAll("td > input")];
  34. const rowCount = inputs.length / colCount;
  35. let idx = inputs.indexOf(focused);
  36. const rowIdx = Math.floor(idx / colCount);
  37. // 最后一个单元格,转到第一个
  38. if (idx === inputs.length - 1 && delta > 0) {
  39. idx = 0;
  40. // 第一个单元格,转到最后一个
  41. } else if (idx === 0 && delta < 0) {
  42. idx = inputs.length - 1;
  43. // 最后一行,转到下一列/第一行
  44. } else if (rowIdx === rowCount - 1 && delta > 0 && idx) {
  45. idx = (idx % colCount) + 1;
  46. // 第一行,转到最后一行/前一列
  47. } else if (rowIdx === 0 && delta < 0 && idx) {
  48. idx = (idx % colCount) - 1 + (rowCount - 1) * colCount;
  49. // 转到下一行
  50. } else {
  51. idx += delta * colCount;
  52. }
  53. inputs[idx].focus();
  54. });
  1. <p>
  2. <label>列数
  3. <input id="colCount" type="number" min="2" max="4" value="2">
  4. </label>
  5. <label>行数
  6. <input id="rowCount" type="number" min="2" max="10" value="6">
  7. </label>
  8. </p>
  9. <table>
  10. </table>
英文:

You can make the navigation agnostic - independent of row and column count in the keydown handler:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

  1. const inputCols = document.querySelector(&quot;input#colCount&quot;);
  2. const inputRows = document.querySelector(&quot;input#rowCount&quot;);
  3. inputCols.addEventListener(&quot;input&quot;, buildTable);
  4. inputRows.addEventListener(&quot;input&quot;, buildTable);
  5. buildTable();
  6. function buildTable() {
  7. const html = Array.from({length: inputRows.value},
  8. _ =&gt;
  9. &quot;&lt;tr&gt;&quot; +
  10. Array.from({length: inputCols.value},
  11. _ =&gt; &quot;&lt;td&gt;&lt;input&gt;&lt;/td&gt;&quot;
  12. ).join(&quot;&quot;) +
  13. &quot;&lt;/tr&gt;&quot;
  14. )
  15. .join(&quot;&quot;);
  16. const table = document.querySelector(&quot;table&quot;);
  17. table.innerHTML = html;
  18. table.querySelector(&quot;input&quot;).focus();
  19. }
  20. document.addEventListener(&quot;keydown&quot;, ({key}) =&gt; {
  21. const delta = { ArrowDown: 1, ArrowUp: -1 }[key];
  22. if (!delta) {
  23. return; // not an arrow up/down key
  24. }
  25. const table = document.querySelector(&quot;table&quot;);
  26. const focused = table.querySelector(&quot;input:focus&quot;);
  27. if (!focused) {
  28. table.querySelector(&quot;input&quot;).focus(); // focus the first input
  29. return;
  30. }
  31. // find next input with given column count
  32. const colCount = table.querySelectorAll(&quot;tr:first-child &gt; td &gt; input&quot;).length;
  33. const inputs = [...table.querySelectorAll(&quot;td &gt; input&quot;)];
  34. const rowCount = inputs.length / colCount;
  35. let idx = inputs.indexOf(focused);
  36. const rowIdx = Math.floor(idx / colCount);
  37. // last cell, go to first
  38. if (idx === inputs.length - 1 &amp;&amp; delta &gt; 0) {
  39. idx = 0;
  40. // first cell, go to last
  41. } else if (idx === 0 &amp;&amp; delta &lt; 0) {
  42. idx = inputs.length - 1;
  43. // last row, go to next column / first row
  44. } else if (rowIdx === rowCount - 1 &amp;&amp; delta &gt; 0 &amp;&amp; idx) {
  45. idx = (idx % colCount) + 1;
  46. // first row, go to last row / prevous column
  47. } else if (rowIdx === 0 &amp;&amp; delta &lt; 0 &amp;&amp; idx) {
  48. idx = (idx % colCount) - 1 + (rowCount - 1) * colCount;
  49. // go to next row
  50. } else {
  51. idx += delta * colCount;
  52. }
  53. inputs[idx].focus();
  54. });

<!-- language: lang-html -->

  1. &lt;p&gt;
  2. &lt;label&gt;Number of cols
  3. &lt;input id=&quot;colCount&quot; type=&quot;number&quot; min=&quot;2&quot; max=&quot;4&quot; value=&quot;2&quot;&gt;
  4. &lt;/label&gt;
  5. &lt;label&gt;Number of rows
  6. &lt;input id=&quot;rowCount&quot; type=&quot;number&quot; min=&quot;2&quot; max=&quot;10&quot; value=&quot;6&quot;&gt;
  7. &lt;/label&gt;
  8. &lt;/p&gt;
  9. &lt;table&gt;
  10. &lt;/table&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月30日 06:17:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定