0

I am creating a simple picture matching game and I will love to make sure when the picture is clicked once, the event listener is removed, this will help me stop the user from clicking on the same image twice to get a win, and then when the user clicks on another element the listener should be added back, I tried doing this with an if statement but the listener is only removed and never added back, I decided to reload the page which somehow makes it look like a solution but I need a better solution that can help me not to reload the page but add the listener back so that the element can be clicked again after the last else if statement run.

here is the sample code below.

//Selecting query elements
const aniSpace = document.querySelector(".container");
const firstCard = document.querySelector("#fstcard");
const secondCard = document.querySelector("#sndcard");
const thirdCard = document.querySelector("#thrdcard");
const playGame = document.querySelector('#play');
const scores = document.querySelector('.scoreboard');

count = 0;
var firstIsClicked = false;
var isCat = false;
var isElephant = false;
var isDog = false;
var isButterfly = false;
var isEmpty = false;


const animatchApp = () => {

    const animals = {
        cat: {
            image: "asset/images/cat.png",
            name: "Cat"
        },
        dog: {
            image: "asset/images/puppy.png",
            name: "Dog"
        },
        elephant: {
            image: "asset/images/elephant.png",
            name: "Elephant"
        },
        butterfly: {
            image: "asset/images/butterfly.png",
            name: "butterfly"
        }
    }
var score = 0;
    firstCard.addEventListener('click', function firstBtn() {
        var type = animals.cat.name;
        if (firstIsClicked === true && isCat === true) {
            firstCard.innerHTML = `<img src="${animals.cat.image}">`;
            firstCard.classList.add('display');
            alert("You won");
            score = score + 50;
            console.log(score);
            document.getElementById('scores').innerHTML = score;
            firstIsClicked = false;
            isElephant = false;
            if (score >= 200){
                alert("You are unstoppable, Game won.");
                count = 0;
                score = 0;
                document.getElementById('scores').innerHTML = score;
                document.getElementById('attempts').innerHTML = count;
                }
            firstCard.removeEventListener('click', firstBtn);
        } else if (firstIsClicked === false) {
            firstCard.innerHTML = `<img src="${animals.cat.image}">`;
            firstCard.classList.add('display');
            firstIsClicked = true;
            isCat = true;
            firstCard.removeEventListener('click', firstBtn);
        } else if (firstIsClicked === true && isCat != true) {
            alert("Not Matched");
            count++;
            document.getElementById('attempts').innerHTML = count;
            firstCard.innerHTML = '';
            secondCard.innerHTML = '';
            thirdCard.innerHTML = '';
            
            firstCard.classList.remove('display');
            secondCard.classList.remove('display');
            thirdCard.classList.remove('display');
           
            firstIsClicked = false;
            isCat = false;
            isDog = false;
            isElephant = false;
            isButterfly = false;
            score = 0;
            document.getElementById('scores').innerHTML = score;
            location.reload(true);
        }
    })

    secondCard.addEventListener('click', function secondBtn() {
        var type = animals.elephant.name;
        if (firstIsClicked === true && isElephant === true) {
            secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
            secondCard.classList.add('display');
            alert("You won");
            score = score + 50;
            console.log(score);
            document.getElementById('scores').innerHTML = score;
            firstIsClicked = false;
            isElephant = false;
            if (score >= 200){
                alert("You are unstoppable, Game won.");
                count = 0;
                score = 0;
                document.getElementById('scores').innerHTML = score;
                document.getElementById('attempts').innerHTML = count;
                }
            secondCard.removeEventListener('click', secondBtn);
        } else if (firstIsClicked === false) {
            secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
            secondCard.classList.add('display');
            firstIsClicked = true;
            isElephant = true;
            secondCard.removeEventListener('click', secondBtn);
        } else if (firstIsClicked === true && isElephant != true) {
            alert("Not Matched");
            count++;
            document.getElementById('attempts').innerHTML = count;
            firstCard.innerHTML = '';
            secondCard.innerHTML = '';
            thirdCard.innerHTML = '';
            
            firstCard.classList.remove('display');
            secondCard.classList.remove('display');
            thirdCard.classList.remove('display');
            
            firstIsClicked = false;
            isCat = false;
            isDog = false;
            isElephant = false;
            isButterfly = false;
            score = 0;
            document.getElementById('scores').innerHTML = score;
            location.reload(true);
        }
    })
    
    thirdCard.addEventListener('click', function thirdBtn() {
        var type = animals.dog.name;
        if (firstIsClicked === true && isDog === true) {
            thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
            thirdCard.classList.add('display');
            alert("You won");
            score = score + 50;
            console.log(score);
            document.getElementById('scores').innerHTML = score;
            firstIsClicked = false;
            isDog = false;
            if (score >= 200){
                alert("You are unstoppable, Game won.");
                count = 0;
                score = 0;
                document.getElementById('scores').innerHTML = score;
                document.getElementById('attempts').innerHTML = count;
                }
            thirdCard.removeEventListener('click', thirdBtn);
        } else if (firstIsClicked === false) {
            thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
            thirdCard.classList.add('display');
            firstIsClicked = true;
            isDog = true;
            thirdCard.removeEventListener('click', thirdBtn);
        } else if (firstIsClicked === true && isDog != true) {
            alert("Not Matched");
            count++;
            document.getElementById('attempts').innerHTML = count;
            firstCard.innerHTML = '';
            secondCard.innerHTML = '';
            thirdCard.innerHTML = '';
           
            firstCard.classList.remove('display');
            secondCard.classList.remove('display');
            thirdCard.classList.remove('display');
            
            firstIsClicked = false;
            isCat = false;
            isDog = false;
            isElephant = false;
            isButterfly = false;
            score = 0;
            document.getElementById('scores').innerHTML = score;
            location.reload(true);
        }
    })


    document.getElementById('attempts').innerHTML = count;
}

animatchApp();
.h1 {
    text-align: center;
    background-color: azure;
    background-image: url("");
}

* {
    box-sizing: border-box;
}

.container {
    width: 500px;
}

.card1 {
    background-color: blue;
    float: left;
    width: 30%;
    padding: 10px;
    height: 150px; /* Should be removed. Only for demonstration */
    border: 1px solid rgb(179, 177, 177);
    transition: transform 0.8s;
    transform-style: preserve-3d;
}

.card2 {
    background-color: blue;
    float: left;
    width: 30%;
    padding: 10px;
    height: 150px; /* Should be removed. Only for demonstration */
    border: 1px solid rgb(179, 177, 177);
    transition: transform 0.8s;
    transform-style: preserve-3d;}

.card3 {
    background-color: blue;
    float: left;
    width: 30%;
    padding: 10px;
    height: 150px; /* Should be removed. Only for demonstration */
    border: 1px solid rgb(179, 177, 177);
    transition: transform 0.8s;
    transform-style: preserve-3d;
}

.scoreboard {
    float: left;
    width: 100%;
    padding: 10px;
    height: 150px; /* Should be removed. Only for demonstration */
}

img {
    width: 100%;
    height: 100%;
    background-color: white;
}

.display {
    background-color: white;
    transform: rotateY(180deg);
}
<div class="container">
        <h1 class="h1">Animatch</h1>
        <div class="first">
            <div class="card1" id="fstcard"></div>
            <div class="card1" id="sndcard"></div>
            <div class="card1" id="thrdcard"></div>
        </div>
</div>
<div class="scoreboard">
        <p>
            <button id="play" onclick="animatchApp()">Play</button>
            <br>
            Score: <span id="scores">0</span>
            <br>
            Failed attempts: <span id="attempts"></span>
        </p>
    </div>
Tsquare07
  • 67
  • 10
  • 1
    if i can see how your game works so i could suggest you better way to achieve it your current code is too big i believe it can be reduced drastically – Amir Rahman Sep 19 '21 at 00:09
  • 2
    Instead of adding and removing event listeners, add a *[custom tag](https://stackoverflow.com/a/17769716/14958486)*, for example *data-accept-click*, and toggle or check the tag instead. – GoWiser Sep 19 '21 at 00:29
  • Okay, @AmirRahman should I create a fiddle or a GitHub project for you to see the code and assist me, because I will appreciate your help. – Tsquare07 Sep 25 '21 at 21:37
  • @Tsquare07 i wanted to know how your game works because your current snippet code is not working which is obvious so it will be usefull for suggesting any solution if we know exact goal or desired result more clearly – Amir Rahman Sep 26 '21 at 07:14
  • Okay, here is the game itself: https://jsfiddle.net/Iamtsquare07/4c9jo25w/16/ @AmirRahman – Tsquare07 Sep 27 '21 at 23:59

2 Answers2

1

you have to define function outside of onclick because you will need this function reference to remove or add it to eventlistener later see a example below

function onload(){
    var main = document.querySelector(".main"),
        btns = main.querySelectorAll(".buttons input"),
        box = main.querySelector(".box")       

    btns[0].addEventListener("click",function(){
        box.addEventListener("click",functionForEvent)
    })

    btns[1].addEventListener("click",function(){
        box.removeEventListener("click",functionForEvent)
    })

    function functionForEvent(e){
        console.log("clicked")
    }
}
onload()
<div class="main">
    <div class="box" style="height:120px;width:120px;border:1px solid black;">Click Me</div>
    <div class="buttons">
        <input type="button" value="Add Event">
        <input type="button" value="Remove Event">
    </div>
</div>
Amir Rahman
  • 1,076
  • 1
  • 6
  • 15
  • Thanks for your answer, it gives me the kind of advice I need to solve the issue, If you have a similar problem, make sure you add the event listener outside the onclick as Amir suggested, it work for me. – Tsquare07 Sep 25 '21 at 22:25
  • @Tsquare07 your most wellcome – Amir Rahman Sep 26 '21 at 07:09
  • @Tsquare07 see i have created one with some technique to reduce hardcoding everything . take a look at codes i have provided comments in each section where needed for you understand easily if there's still any confusion ask freely https://jsfiddle.net/amirrahman132132/7rw24x6o/5/ – Amir Rahman Sep 28 '21 at 15:01
  • Thanks @AmirRahman I learn a lot from that, I will take some time to go through the code more carefully and give you some feedback or questions, I appreciate it a lot. – Tsquare07 Oct 06 '21 at 20:59
0

Here is an example, that shows how to remove the click event from the item clicked and add it to the other items.

It colors the items that can be clicked green, and the item that can't be clicked red.

To keep the example short, it doesn't check, if the elements it operates on, are well defined.

function myonload() {
    let elems = document.querySelectorAll('.mydiv');
    for(let i = 0; i < elems.length; ++i) {
        let elem = elems[i];
        elem.addEventListener('click', mydiv_clicked);
    }
}
function mydiv_clicked(e) {
    let elems = document.querySelectorAll('.mydiv');
    for(let i = 0; i < elems.length; ++i) {
        let elem = elems[i];
        if(elem == e.target) {
            elem.removeEventListener('click', mydiv_clicked);
            elem.classList.add('mycolor_clicked');
            elem.classList.remove('mycolor');
            // Do additional logic here
        } else {
            elem.addEventListener('click', mydiv_clicked);
            elem.classList.remove('mycolor_clicked');
            elem.classList.add('mycolor');
            // Do additional logic here
        }
    }
}
.mydiv {
    height:30px;
    width: 200px;
    border:1px solid black;
    margin-bottom:2px;
}
.mycolor {
    background-color:#00ff00;
}
.mycolor_clicked {
    background-color:#ff0000;
}
<body onload="myonload()">
    <div class="mydiv mycolor">First area</div>
    <div class="mydiv mycolor">Second area</div>
    <div class="mydiv mycolor">Third area</div>
</body>

The example shown here does not need to check if an event handler already exists, as adding the same event handler twice, replaces the existing one.

You could also add a custom attribute to your elements and toggle it, instead of adding and removing event listeners as shown here and name your attribute data-something, for example data-can-be-clicked.

GoWiser
  • 857
  • 6
  • 20