Where should i put setTimeout()?

Viewed 50

Codepen

let rock = document.querySelector(".rock-btn");
    let paper = document.querySelector(".paper-btn");
    let scissors = document.querySelector(".scissors-btn");
    
    let select = document.querySelector(".select");
    let computerChoice = document.querySelector(".comp-choice");
    let result = document.querySelector(".result");
    
    rock.addEventListener("click", function press() {
      select.innerHTML = `Select: Rock`;
      let randomNum = Math.floor(Math.random() * 3);
      let compChoice = "";
      if (randomNum == 0) {
        compChoice = "Rock";
      } else if (randomNum == 1) {
        compChoice = "Paper";
      } else if (randomNum == 2) {
        compChoice = "Scissors";
      }
      result.style.removeProperty("color");
      computerChoice.innerHTML = `Computer choose: ${compChoice}`;
      if (compChoice == "Rock") {
        result.innerHTML = "Result: It's a draw!";
        result.style.color = "#5c3000";
      } else if (compChoice == "Paper") {
        result.innerHTML = "Result: Oh no, You lost!";
        result.style.color = "#8d1d1d";
      } else if (compChoice == "Scissors") {
        result.innerHTML = "Result: Congratulations, You won!";
        result.style.color = "#1e612b";
      }
    });
    
   

I want to click a rock,paper,scissors and then wait 1 seconds.Basically i want it delay. When i put it normal way it wont work after first time. I tried to solve on my on but sadly couldn't. I included codepen so that its easier for you to solve hopefully. Thanks for your help, I appreciate it.

1 Answers

āŒ don't add a setTimeout of 1s,
āœ… but instead, add some nice effect with CSS animations of 1s.

enter image description here


and for solving the bug

bug: first-time animation work, other times not start animation

you can use a setTimeout of also 1ms

1ms is enough for javascript to delete the class,
so after we successfully deleted that class, now we can re-add it so we have an animation


Javascript that I added:

/* THIS IS THE TRICK */
setTimeout(() => {
    result.classList.add("animation")
}, 1); // 1ms of Timeout

CSS that I added:

/* animation, this is added by javascript */

.animation {
    animation: move 1s ease-in-out;
}

@keyframes move {
    0% {
        transform: translateX(100%);
    }
    100% {
        transform: translateX(0);
    }
}

don't make the user wait for no reason,
instead make them see some beautiful animation that makes the user think that the site is faster.
with setTimeout the user thinks that the site is a lot slower.

I also refactored it for you, so you don't need to write multiple time the same code.
using forEach() and JSON object and arrays and switch statement.

/* the buttons  */
let rock = document.querySelector(".rock-btn");
let paper = document.querySelector(".paper-btn");
let scissors = document.querySelector(".scissors-btn");

/* elements where we will put a output the outputs */
let select = document.querySelector(".select");
let computerChoice = document.querySelector(".comp-choice");
let result = document.querySelector(".result");

/* all the buttons are one array, 
so we can use them in a forEach loop, 
without repeating a lot the code */
let allButtons = [rock, paper, scissors];

/* this is a array of choices (strings)
it must need to not be modified the order 
1. Rock 2. Paper 3. Scrissors */
let allChoices = ["Rock", "Paper", "Scissors"];

/* the firt {} is for victory, 
the second is for draw, 
the third is for losing */
/* and this array contain all the information you need 
for outputing the victory string with the color in #result */
let allResults = [{
  message: "Result: Congratulations, You won!",
  color: "#1e612b"
}, {
  message: "Result: It's a draw!",
  color: "#5c3000"
}, {
  message: "Result: Oh no, You lost!",
  color: "#8d1d1d"
}];

/* from this array we can see if user win or lose,
it must need to not be modified the order 
1. Rock 2. Paper 3. Scrissors */
let winLoseArray = [{
  toWin: allChoices[2],
  toLose: allChoices[1]
}, {
  toWin: allChoices[0],
  toLose: allChoices[2]
}, {
  toWin: allChoices[1],
  toLose: allChoices[0]
}]

/* forEach loop help us not writing the same code multiple times */
allButtons.forEach((choice, index) => {
  choice.addEventListener("click", () => {
    /* resetting the styles and animations */
    result.classList.remove("animation");
    result.style.removeProperty("color");

    /* random number */
    let randomNum = Math.floor(Math.random() * 3);

    /* get the choices of user, and computer */
    let compChoice = allChoices[randomNum];
    let userChoice = allChoices[index];

    /* display the choices in the UI */
    select.innerHTML = `select: ${userChoice}`;
    computerChoice.innerHTML = `Computer choose: ${compChoice}`;

    /* instead of If Else, We Will be using "switch" */
    switch (compChoice) {
      case winLoseArray[index].toWin:
        result.innerHTML = allResults[0].message;
        result.style.color = allResults[0].color;
        break;
      case winLoseArray[index].toLose:
        result.innerHTML = allResults[2].message;
        result.style.color = allResults[2].color;
        break;
      default:
        result.innerHTML = allResults[1].message;
        result.style.color = allResults[1].color;
        break;
    }

    /* THIS IS THE TRICK */
    setTimeout(() => {
      result.classList.add("animation")
    }, 1);
  });
});
.container {
  margin-top: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 25px;
}

h1 {
  font-size: 45px;
}

p {
  font-size: 35px;
  margin: 0;
}

.btn {
  padding: 8px 16px;
  font-size: 20px;
  background-color: #c2255c;
  color: #fff;
  border-radius: 20px;
  margin-right: 5px;
}

.rock-btn:hover {
  background-color: #70bdc9;
}

.paper-btn:hover {
  background-color: #f8e9d1;
}

.scissors-btn:hover {
  background-color: #89d0b4;
}

.rock-btn {
  background-color: #4cacbc;
}

.paper-btn {
  background-color: #f6e3c5;
}

.scissors-btn {
  background-color: #6cc4a1;
}

img {
  width: 100px;
  border-radius: 10px;
}

.icons {
  display: flex;
  justify-content: space-between;
  gap: 15px;
}

body {
  background-color: rgb(136, 152, 167);
}


/* animation, this is added by javascript */

.animation {
  animation: move 1s ease-in-out;
}

@keyframes move {
  0% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(0);
  }
}
<div class="container">
  <h1>Rock Paper Scissors!</h1>
  <p class="select">Select:</p>
  <div class="icons">
    <img alt="" src="https://www.shareicon.net/data/256x256/2015/11/15/672596_open_512x512.png" class="scissors-btn">
    <img src="https://i.pinimg.com/originals/f5/2a/23/f52a2361f819785f37256d8eacd64a0d.png" class="paper-btn">
    <img src="https://img.icons8.com/emoji/256/rock-emoji.png" class="rock-btn">
  </div>
  <p class="comp-choice">Computer choice:</p>
  <p class="result">Result:</p>
</div>

<script src="script.js"></script>

Related