Jaquarh
Jaquarh

Reputation: 6693

Event listeners for click do not get called when the element is clicked

I am trying to add an onclick listener to my classes. I have added alert() methods inside but it seems that the onclick is never executed. I have tried to use event listeners too which gave me the same issue.

My code is below, how can I loop through my classes and append an event listener?

/* Easier function to use than rewriting document.get... */
function getById(id) {
    return document.getElementById(id)
}

function getByClass(c) {
    return document.getElementsByClassName(c)
}

/* Random number calculation */
function random(xOrY) {
    return Math.floor(Math.random() * (+xOrY - +1)) + 1
}

/* Create a grid */
function createGrid(isHiding) {
    var grid = document.createElement("div")
    grid.className = isHiding ? "hiding" : "grid"
    return grid
}

/* Set configurations we will use */
var settings = {
    hiding: 4,
    x: 6,
    y: 6,
    maxAttempts: 6 * 6,
    container: 'grid-container'
}

/* Set up the game */
var game = {
    settings: settings,
    attempts: 0,
    numberFound: 0,
    hidingGrids: []
}

/* Generate the hiding grids */
for (i = 1; i <= game.settings.hiding; i++) {
    game.hidingGrids.push({
        x: random(game.settings.x),
        y: random(game.settings.y)
    })
}

/* Generate the grids */
for (y = 1; y <= game.settings.y; y++) {
    for (x = 1; x <= game.settings.x; x++) {
        var gridHasHid = false
        game.hidingGrids.forEach(function(grid) {
            if (y == grid.y && x == grid.x) {
                gridHasHid = true
                /* Create a hidden grid */
                getById(game.settings.container).appendChild(createGrid(true))
            }
        })
        if (!gridHasHid) {
            /**
             *If it gets here, the grid wasn't a hidden grid
             * thus we need to add a standard grid.
             */
            getById(game.settings.container).appendChild(createGrid(false))
        }
    }
    /* Append a break line to start the next row */
    var br = document.createElement("br")
    getById(game.settings.container).appendChild(br)
}

/* Lets set listen handlers on the incorrect and correct grids */
for (el in getByClass("grid")) {
    el.onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "red") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "red"
        alert("Incorrect, you have " + ++game.attempts + " attempts left.")
    }
}

for (el in getByClass("hiding")) {
    el.onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "blue") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "blue"
        alert("Correct, you have " + ++game.attempts + " attempts left.")
    }
}
#grid-container {
  display: inline-block;
  width: 100%;
}

.grid {
  display: inline-block;
  background-color: #000;
  padding: 5%;
  margin: 2%;
}

.hiding {
  background-color: #000;
  display: inline-block;
  padding: 5%;
  margin: 2%;
}

/* Uncomment below to see where they're hiding (DEBUG) */

.hiding {
  background-color: blue;
}
<div id="grid-container"></div>

Upvotes: 0

Views: 56

Answers (3)

leonheess
leonheess

Reputation: 21411

I know this isn't CodeReview but I tried to improve your code and fix the issue.

Array.from(getByClass("grid")).forEach(el => {
    el.addEventListener('click', () => {
        // your code
    });
});

This converts the array-like object of all child elements returned by Document​.get​Elements​ByClass​Name() into an actual array and iterates through each element. You also have to use to el instead of this here because there is no this defined in that scope.

function getById(id) {
    return document.getElementById(id)
}

function getByClass(c) {
    return document.getElementsByClassName(c)
}

/* Random number calculation */
function random(xOrY) {
    return Math.floor(Math.random() * (+xOrY - +1)) + 1
}

/* Create a grid */
function createGrid(isHiding) {
    let grid = document.createElement("div");
    grid.className = isHiding ? "hiding" : "grid";
    return grid
}

/* Set configurations we will use */
let settings = {
    hiding: 4,
    x: 6,
    y: 6,
    maxAttempts: 6 * 6,
    container: 'grid-container'
};

/* Set up the game */
let game = {
    settings: settings,
    attempts: 0,
    numberFound: 0,
    hidingGrids: []
};

/* Generate the hiding grids */
for (let i = 1; i <= game.settings.hiding; i++) {
    game.hidingGrids.push({
        x: random(game.settings.x),
        y: random(game.settings.y)
    })
}

/* Generate the grids */
for (let y = 1; y <= game.settings.y; y++) {
    for (let x = 1; x <= game.settings.x; x++) {
        let gridHasHid = false;
        game.hidingGrids.forEach(function(grid) {
            if (y === grid.y && x === grid.x) {
                gridHasHid = true;
                /* Create a hidden grid */
                getById(game.settings.container).appendChild(createGrid(true))
            }
        });
        if (!gridHasHid) {
            /**
             *If it gets here, the grid wasn't a hidden grid
             * thus we need to add a standard grid.
             */
            getById(game.settings.container).appendChild(createGrid(false))
        }
    }
    /* Append a break line to start the next row */
    let br = document.createElement("br")
    getById(game.settings.container).appendChild(br)
}

/* Lets set listen handlers on the incorrect and correct grids */
Array.from(getByClass("grid")).forEach(el => {
    el.addEventListener('click', () => {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts === game.settings.maxAttempts || game.numberFound === game.settings.hiding) {
            alert("The game is already over.");
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (el.style.background === "red") return;
        /* If it got here, all checks passed. Lets update the colour and send an message */
        el.style.background = "red";
        alert(`Incorrect, you have ${++game.attempts} attempts left.`)
    });
});

Array.from(getByClass("hiding")).forEach(el => {
    el.addEventListener('click', () => {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts === game.settings.maxAttempts || game.numberFound === game.settings.hiding) {
            alert("The game is already over.");
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (el.style.background === "blue") return;
        /* If it got here, all checks passed. Lets update the colour and send an message */
        el.style.background = "blue";
        alert(`Correct, you have ${++game.attempts} attempts left.`)
    });
});
#grid-container {
  display: inline-block;
  width: 100%;
}

.grid {
  display: inline-block;
  background-color: #000;
  padding: 5%;
  margin: 2%;
}

.hiding {
  background-color: #000;
  display: inline-block;
  padding: 5%;
  margin: 2%;
}

/* Uncomment below to see where they're hiding (DEBUG) */

.hiding {
  background-color: blue;
}
<div id="grid-container"></div>

Upvotes: 1

Shiv Kumar Baghel
Shiv Kumar Baghel

Reputation: 2480

getElementsByClassName returns NodeList array. and for...in is used to iterate over the properties of objects. so use basic for loop to iterate over array here.

Try below solution.

/* Easier function to use than rewriting document.get... */
function getById(id) {
    return document.getElementById(id)
}

function getByClass(c) {
    return document.getElementsByClassName(c)
}

/* Random number calculation */
function random(xOrY) {
    return Math.floor(Math.random() * (+xOrY - +1)) + 1
}

/* Create a grid */
function createGrid(isHiding) {
    var grid = document.createElement("div")
    grid.className = isHiding ? "hiding" : "grid"
    return grid
}

/* Set configurations we will use */
var settings = {
    hiding: 4,
    x: 6,
    y: 6,
    maxAttempts: 6 * 6,
    container: 'grid-container'
}

/* Set up the game */
var game = {
    settings: settings,
    attempts: 0,
    numberFound: 0,
    hidingGrids: []
}

/* Generate the hiding grids */
for (i = 1; i <= game.settings.hiding; i++) {
    game.hidingGrids.push({
        x: random(game.settings.x),
        y: random(game.settings.y)
    })
}

/* Generate the grids */
for (y = 1; y <= game.settings.y; y++) {
    for (x = 1; x <= game.settings.x; x++) {
        var gridHasHid = false
        game.hidingGrids.forEach(function(grid) {
            if (y == grid.y && x == grid.x) {
                gridHasHid = true
                /* Create a hidden grid */
                getById(game.settings.container).appendChild(createGrid(true))
            }
        })
        if (!gridHasHid) {
            /**
             *If it gets here, the grid wasn't a hidden grid
             * thus we need to add a standard grid.
             */
            getById(game.settings.container).appendChild(createGrid(false))
        }
    }
    /* Append a break line to start the next row */
    var br = document.createElement("br")
    getById(game.settings.container).appendChild(br)
}

/* Lets set listen handlers on the incorrect and correct grids */
for (el in getByClass("grid")) {
    el.onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "red") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "red"
        alert("Incorrect, you have " + ++game.attempts + " attempts left.")
    }
}

var hidingClass = getByClass("hiding");
for(var i = 0; i < hidingClass.length; i++){
   var el = hidingClass[i];

    el.onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "blue") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "blue"
        alert("Correct, you have " + ++game.attempts + " attempts left.")
    }
}
#grid-container {
  display: inline-block;
  width: 100%;
}

.grid {
  display: inline-block;
  background-color: #000;
  padding: 5%;
  margin: 2%;
}

.hiding {
  background-color: #000;
  display: inline-block;
  padding: 5%;
  margin: 2%;
}

/* Uncomment below to see where they're hiding (DEBUG) */

.hiding {
  background-color: blue;
}
<div id="grid-container"></div>

Upvotes: 0

Syed mohamed aladeen
Syed mohamed aladeen

Reputation: 6755

you have some mistakes in your code. for eg. in this for loop for (el in getByClass("hiding")) the el will only give you the key value not the entire element.

you need to get the element like this getByClass("hiding")[el].onclick = function() {

I have added some code. Try this

/* Easier function to use than rewriting document.get... */
function getById(id) {
    return document.getElementById(id)
}

function getByClass(c) {
    return document.getElementsByClassName(c)
}

/* Random number calculation */
function random(xOrY) {
    return Math.floor(Math.random() * (+xOrY - +1)) + 1
}

/* Create a grid */
function createGrid(isHiding) {
    var grid = document.createElement("div")
    grid.className = isHiding ? "hiding" : "grid"
    return grid
}

/* Set configurations we will use */
var settings = {
    hiding: 4,
    x: 6,
    y: 6,
    maxAttempts: 6 * 6,
    container: 'grid-container'
}

/* Set up the game */
var game = {
    settings: settings,
    attempts: 0,
    numberFound: 0,
    hidingGrids: []
}

/* Generate the hiding grids */
for (i = 1; i <= game.settings.hiding; i++) {
    game.hidingGrids.push({
        x: random(game.settings.x),
        y: random(game.settings.y)
    })
}

/* Generate the grids */
for (y = 1; y <= game.settings.y; y++) {
    for (x = 1; x <= game.settings.x; x++) {
        var gridHasHid = false
        game.hidingGrids.forEach(function(grid) {
            if (y == grid.y && x == grid.x) {
                gridHasHid = true
                /* Create a hidden grid */
                getById(game.settings.container).appendChild(createGrid(true))
            }
        })
        if (!gridHasHid) {
            /**
             *If it gets here, the grid wasn't a hidden grid
             * thus we need to add a standard grid.
             */
            getById(game.settings.container).appendChild(createGrid(false))
        }
    }
    /* Append a break line to start the next row */
    var br = document.createElement("br")
    getById(game.settings.container).appendChild(br)
}

/* Lets set listen handlers on the incorrect and correct grids */
for (el in getByClass("grid")) {
    getByClass("grid")[el].onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "red") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "red"
        alert("Incorrect, you have " + ++game.attempts + " attempts left.")
    }
}

for (el in getByClass("hiding")) {
    getByClass("hiding")[el].onclick = function() {
        /* We need to go through all our checks to ensure the game hasn't ended */
        if (game.attempts == game.settings.maxAttempts || game.numberFound == game.settings.hiding) {
            alert("The game is already over.")
            return
        }
        /* Check that the tile hasn't already been clicked using our colour factor */
        if (this.style.background == "blue") return
        /* If it got here, all checks passed. Lets update the colour and send an message */
        this.style.background = "blue"
        alert("Correct, you have " + ++game.attempts + " attempts left.")
    }
}
#grid-container {
  display: inline-block;
  width: 100%;
}

.grid {
  display: inline-block;
  background-color: #000;
  padding: 5%;
  margin: 2%;
}

.hiding {
  background-color: #000;
  display: inline-block;
  padding: 5%;
  margin: 2%;
}

/* Uncomment below to see where they're hiding (DEBUG) */

.hiding {
  background-color: blue;
}
<div id="grid-container"></div>

Upvotes: 3

Related Questions