How to call the a function within itself and have it reselect a new DOM element in js?

I have a function A to select the .current element and do something to it. Then, (re)move the .current class name to another element and do the same thing to it.

function funA () {
    let state = []; 
    let currentRow = document.querySelector(".current");
    //...
    evaluateThings(function () {
        currentRow.classList.remove("current");
        currentRow.nextSibling.classList.add("current");
         funcA();
    });
}
function evaluateThings(callback) {
    //...
    callback()
}

funcA()

The issue is, funcA remembers the previous selector and makes changes to both, the new .current and the last one

here’s a demo

>Solution :

funcA adds a keydown listener to the document. When you recursively call funcA, you aren’t removing the previous listener, so on the next event, both run, and both elements get changed – and the cycle continues.

Remove the prior listener when doing the recursive call.

function funcA() {
  const currentRow = document.querySelector(".current");
  const handler = (e) => {
    if (e.key === 'Enter') {
      currentRow.nextElementSibling.classList.add("current");
      currentRow.classList.remove("current");
      document.removeEventListener("keydown", handler);
      evaluateThings(funcA);
    } else {
      currentRow.innerHTML += e.key
    }
  };
  document.addEventListener("keydown", handler);
}

function evaluateThings(callback) {
  //...
  callback()
}

funcA()
<div class="row current">a</div>
<div class="row">b</div>
<div class="row">c</div>
<div class="row">d</div>
<div class="row">e</div>
<div class="row"></div>

Or keep the listener attached, but reassign the variable that points to the element.

let currentRow = document.querySelector(".current");
function funcA() {
  document.addEventListener("keydown", (e) => {
    if (e.key === 'Enter') {
      currentRow.nextElementSibling.classList.add("current");
      currentRow.classList.remove("current");
      evaluateThings(() => currentRow = document.querySelector(".current"));
    } else {
      currentRow.innerHTML += e.key;
    }
  });
}

function evaluateThings(callback) {
  //...
  callback()
}

funcA()
<div class="row current">a</div>
<div class="row">b</div>
<div class="row">c</div>
<div class="row">d</div>
<div class="row">e</div>
<div class="row"></div>

Leave a Reply