Search code examples
javascriptdomtokenlist

Remove relevant DOMTokenList item from array on button click


I'm trying to figure out how to remove an item from an array on a button click. I've already figured out how to push the item to the array, but removing it is proving more difficult. The JS code is below:

let sideArray = [];
let sideButtons = document.querySelectorAll('div.side-buttons button');

for (let i = 0; i < sideButtons.length; i++) {
  if(sideButtons[i].textContent !== "RANDOM" ) {
    sideButtons[i].onclick = function (e) {
      //alert (this.innerHTML)

    this.classList.toggle('on');
    let tokenNum = this.className[0] + this.className[1];
    let index = sideArray.indexOf(tokenNum);
    if (this.classList.contains('on')) {

      sideArray.push(+(tokenNum));
      
      sortNumbers(sideArray);
      console.log(tokenNum);
      console.log(index);
      console.log(sideArray);

    } else if (!this.classList.contains('on')) {


      sideArray.splice(index, 1)
      sortNumbers(sideArray);
      console.log(sideArray);
    }
      let buttonHTML = this.textContent;

      //link to create choice button function
      //choiceButtons(buttonHTML)
    }
  }
}


function sortNumbers(array) {
  array.sort(function(a, b) {
    return a - b;
  });
}

Each button has a number as a class that helps me iterate through them. Once I push the relevant number to an array on click, I want to remove the relevant number from the array when the button is clicked a second time. Can you help?

Edit: At it stands, the splice method removes the last element in the array, no matter which button you click.

Here's my code in full : https://codepen.io/david-webb/pen/JjXRqBQ


Solution

  • The main issue was the way you were gathering the token.

    You're trying to gather the first and second characters of the button's class, but often there's only a first character - no second - so this produces a string like 4undefined. We can fix this by retrieving the token via REGEX, allowing for any number of characters (1, 2, 6891, whatever).

    I've fixed this and also refactored your code. This replaces your for loop. I've delegated the events, and also removed some unnecessary duplication.

    document.body.addEventListener('click', evt => {
        if (!evt.target.matches('div.side-buttons button') || evt.target.textContent == 'RANDOM') return;
        evt.target.classList.toggle('on');
        let tokenNum = evt.target.className.match(/\d+/); //<-- better way of getting token
        if (evt.target.classList.contains('on'))
            sideArray.push(tokenNum[0]);
        else {
            let index = sideArray.indexOf(tokenNum[0]); //<-- need this only in the else block, not if
            sideArray.splice(index, 1)
        }
        sortNumbers(sideArray);
        let buttonHTML = evt.target.textContent; //<-- you don't currently do anything with this
    });