How to removeListener while keeping function chain

const X_IMAGE_URL = "res/x.png";
const O_IMAGE_URL = "res/circle.png";
const SYMBOLS = {
    'x': X_IMAGE_URL,
    'o': O_IMAGE_URL
};

function playGame() {
    const freeBoxes = [];
    const takenBoxes = {};
    for (box of document.querySelectorAll('#grid div')) {
        box.addEventListener('click', function playX(event) {
            playXHandler(event, freeBoxes, takenBoxes);

            box.removeEventListener('click', playX);
        });
        freeBoxes.push(box);
    }
}

function deleteFromArray(element, array) {
    let index = array.indexOf(element);
    array.splice(index, 1);
}

function assignToBox(box, player, freeBoxes, takenBoxes) {
    /*
        `box` is a div element
        `player` is a single character string
        representing the respective symbols
        of both player
     */
    const image = document.createElement('img');
    image.src = SYMBOLS[player];
    box.appendChild(image);

    deleteFromArray(box, freeBoxes);
    takenBoxes[box.dataset.index] = player;
}

function playXHandler(event, freeBoxes, takenBoxes) {
    assignToBox(event.currentTarget, 'x', freeBoxes, takenBoxes);
    checkForWinner(takenBoxes);
    computerPlayO(freeboxes, takenBoxes);
}

function checkForWinner(takenBoxes) {
    console.log(takenBoxes);
}

function computerPlayO(freeBoxes, takenBoxes) {
    let index = Math.random() * freeBoxes.length;
    let box = freeBoxes[index];

    assignToBox(box, 'o', freeBoxes, takenBoxes);
}

playGame();

I want to pass arguments (freeBoxes, takenBoxes) to the event handler as I am doing in playGame(). However, I can’t seem to find a way to remove the event listener successfully. When I play the game and click on the same div twice, it duplicates the character. This means that the event listener was not successfully removed.

Any suggestions, please?
@zedshaw

Do:

function playGame() {
    const freeBoxes = [];
    const takenBoxes = {};
    for (box of document.querySelectorAll('#grid div')) {
        box.addEventListener('click', function playX(event) {
            playXHandler(event, freeBoxes, takenBoxes);
        }, {once: true});
        freeBoxes.push(box);
    }
}
3 Likes

Thank you for the help. @io_io

1 Like