'Why is my page not loading when clicking on event listener?

I'm creating an anime quiz. So when the user clicks on "Welcome to the anime quiz" s/he should be presented with 4 different anime titles. However, nothing happens when I do so. The page doesn't even load. The issue seems to come from the two lines of code I wrote in generateChoices(). When I comment them out and console.log("Hi") the code works. I don't know how to pin point the issue as when I uncomment the two lines of code in question I can't even use debugging. I think I might have created an infinite loop, but can't know for sure.

let japaneseAnime = [
  {
  name: "dragon ball",
  picture: "https://dbgbh.bn-ent.net/assets/img/news/news_thumb_kv.png"
},
{
  name: "Attack On Titans",
  picture: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJYjy_bS8t3ScWyG7q94fIltnar3ChaOHmGA&usqp=CAU"
},
{
  name: "naruto",
  picture: "https://res.cloudinary.com/jerrick/image/upload/v1616592065/605b3cc118e784001e22da0d.jpg"
},
{
  name: "Demon Slayer",
  picture: "https://cdn.vox-cdn.com/thumbor/gcVHhhZ4VwVswvbDPvI-RfQ7ECQ=/1400x1050/filters:format(png)/cdn.vox-cdn.com/uploads/chorus_asset/file/19721018/Tanjiro__Demon_Slayer_.png"
},
{
  name: "Ghost in the shell",
  picture: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8VBbI5HMki5cmjP_Gq0TdyA6VZn_0_fmkhg&usqp=CAU"
}

]

const intro = document.querySelector(".intro");
const choices = [...document.querySelector(".question").children];
const anime = document.querySelector(".anime");
let anime_picture = document.querySelector(".anime_picture img");
let counter = [0]

intro.addEventListener("click", startQuiz);

function startQuiz() {
  intro.classList.add("hide");
  anime.classList.remove("hide");
  generateChoices();

}

const getRandom = () => Math.floor(Math.random()*choices.length)


function uniqueChoices(count) {
  let choicesArray = new Set()

  while(!choicesArray.has(counter)) {
    choicesArray.clear();
    while(choicesArray.size < count) choicesArray.add(getRandom())
  }

  return [...choicesArray]
}

function generateChoices() {
  let choicesArray = uniqueChoices(choices.length);
  choices.forEach((choice, i) => choice.innerHTML = japaneseAnime[choicesArray[i]].name)
}
body {
  position: relative;
  display: flex;
  justify-content: center;
  align-content: center;
}

.intro {
  height: 300px;
  width: 300px;
  border: 1px blue solid;
  position: absolute;
  left: 25%;
  text-align: center;
}

.hide {
  visibility: hidden;
}

.show {
  visibility: visible;
}

.anime {
  height: 800px;
  width: 800px;
  border: 1px red solid;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.anime_picture {
  height: 400px;
  width: 400px;
  position: absolute;
}

.question {
  height: 100px;
  width: 100%;
  border: 1px blue solid;
  bottom: 0;
  position: absolute;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.question > div {
  height: 80px;
  width: auto;
  border: 1px black solid;
  background-color: #ddd;
}

img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

header {
  width: 100%;
  height: 100px;
  border: 1px black solid;
  position: absolute;
  top: 0;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="index.css">
    <title>anime page</title>

  </head>
  <body>
    <div class="intro">
      welcome to the anime website
    </div>
    <div class="anime hide">
      <div class="anime_picture">
        <img src="" alt="">

      </div>
      <div class="question">
        <div class="question1"></div>
        <div class="question2"></div>
        <div class="question3"></div>
        <div class="question4"></div>
      </div>
      <header>anime Quiz</header>

    </div>

  </body>
  <script src="index.js" type="text/javascript"></script>
</html>


Solution 1:[1]

Nested while statement at uniqueChoices making an infinite Loop.
So,

  • I made getUniqueChoices which returns a random element in japaneseAnime with the length of question list. Referencing code from how to make random elements form an array.
  • And replace innerHTML to textContent. Because innerHTML is vulnerable to security issues.

const japaneseAnime = [
  {
    name: "dragon ball",
    picture: "https://dbgbh.bn-ent.net/assets/img/news/news_thumb_kv.png"
  },
  {
    name: "Attack On Titans",
    picture:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJYjy_bS8t3ScWyG7q94fIltnar3ChaOHmGA&usqp=CAU"
  },
  {
    name: "naruto",
    picture:
      "https://res.cloudinary.com/jerrick/image/upload/v1616592065/605b3cc118e784001e22da0d.jpg"
  },
  {
    name: "Demon Slayer",
    picture:
      "https://cdn.vox-cdn.com/thumbor/gcVHhhZ4VwVswvbDPvI-RfQ7ECQ=/1400x1050/filters:format(png)/cdn.vox-cdn.com/uploads/chorus_asset/file/19721018/Tanjiro__Demon_Slayer_.png"
  },
  {
    name: "Ghost in the shell",
    picture:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8VBbI5HMki5cmjP_Gq0TdyA6VZn_0_fmkhg&usqp=CAU"
  }
];

const intro = document.querySelector(".intro");
const anime = document.querySelector(".anime");
const anime_picture = document.querySelector(".anime_picture img");
const choices = [...document.querySelector(".question").children];

intro.addEventListener("click", startQuiz);

function startQuiz() {
  intro.classList.add("hide");
  anime.classList.remove("hide");
  generateChoices();
}

function getUniqueChoices() {
  return japaneseAnime.sort(() => 0.5 - Math.random()).slice(0, choices.length);
}

function generateChoices() {
  const uniqueChoices = getUniqueChoices();
  const randomNumber = Math.floor(Math.random() * choices.length);
  
  anime_picture.src = uniqueChoices[randomNumber].picture;
  choices.forEach((choice, i) => {
    choice.textContent = uniqueChoices[i].name;
  });
}
body {
  position: relative;
  display: flex;
  justify-content: center;
  align-content: center;
}

.intro {
  height: 300px;
  width: 300px;
  border: 1px blue solid;
  position: absolute;
  left: 25%;
  text-align: center;
  cursor: pointer;
}

.hide {
  visibility: hidden;
}

.show {
  visibility: visible;
}

.anime {
  height: 800px;
  width: 800px;
  border: 1px red solid;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.anime_picture {
  height: 400px;
  width: 400px;
  position: absolute;
}

.question {
  height: 100px;
  width: 100%;
  border: 1px blue solid;
  bottom: 0;
  position: absolute;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.question > div {
  height: 80px;
  width: auto;
  border: 1px black solid;
  background-color: #ddd;
}

img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

header {
  width: 100%;
  height: 100px;
  border: 1px black solid;
  position: absolute;
  top: 0;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="index.css">
    <title>anime page</title>
  </head>
  <body>
    <div class="intro">
      welcome to the anime website
    </div>
    <div class="anime hide">
      <div class="anime_picture">
        <img src="" alt="">
      </div>
      <div class="question">
        <div class="question1"></div>
        <div class="question2"></div>
        <div class="question3"></div>
        <div class="question4"></div>
      </div>
      <header>anime Quiz</header>
    </div>
  </body>
  <script src="index.js" type="text/javascript"></script>
</html>

EDIT

I made it using Set object that you need.
Hope this helps.

const japaneseAnime = [
  {
    name: "dragon ball",
    picture: "https://dbgbh.bn-ent.net/assets/img/news/news_thumb_kv.png"
  },
  {
    name: "Attack On Titans",
    picture:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJYjy_bS8t3ScWyG7q94fIltnar3ChaOHmGA&usqp=CAU"
  },
  {
    name: "naruto",
    picture:
      "https://res.cloudinary.com/jerrick/image/upload/v1616592065/605b3cc118e784001e22da0d.jpg"
  },
  {
    name: "Demon Slayer",
    picture:
      "https://cdn.vox-cdn.com/thumbor/gcVHhhZ4VwVswvbDPvI-RfQ7ECQ=/1400x1050/filters:format(png)/cdn.vox-cdn.com/uploads/chorus_asset/file/19721018/Tanjiro__Demon_Slayer_.png"
  },
  {
    name: "Ghost in the shell",
    picture:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8VBbI5HMki5cmjP_Gq0TdyA6VZn_0_fmkhg&usqp=CAU"
  }
];

const intro = document.querySelector(".intro");
const anime = document.querySelector(".anime");
const anime_picture = document.querySelector(".anime_picture img");
const choices = [...document.querySelector(".question").children];
const numOfChoices = [...document.querySelector(".question").children].length;

intro.addEventListener("click", startQuiz);

function startQuiz() {
  intro.classList.add("hide");
  anime.classList.remove("hide");
  generateChoices();
}

function getRandomNumber () {
  return Math.floor(Math.random() * numOfChoices)
}

function getUniqueChoices() {
   const choicesArray = new Set()

   while(choicesArray.size < numOfChoices) {
      choicesArray.add(japaneseAnime[getRandomNumber()])  
   }  

  return [...choicesArray];
}

function generateChoices() {
  const uniqueChoices = getUniqueChoices();
  const randomNumber = getRandomNumber();
  
  anime_picture.src = uniqueChoices[randomNumber].picture;
  choices.forEach((choice, i) => {
    choice.textContent = uniqueChoices[i].name;
  });
}
body {
  position: relative;
  display: flex;
  justify-content: center;
  align-content: center;
}

.intro {
  height: 300px;
  width: 300px;
  border: 1px blue solid;
  position: absolute;
  left: 25%;
  text-align: center;
  cursor: pointer;
}

.hide {
  visibility: hidden;
}

.show {
  visibility: visible;
}

.anime {
  height: 800px;
  width: 800px;
  border: 1px red solid;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.anime_picture {
  height: 400px;
  width: 400px;
  position: absolute;
}

.question {
  height: 100px;
  width: 100%;
  border: 1px blue solid;
  bottom: 0;
  position: absolute;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.question > div {
  height: 80px;
  width: auto;
  border: 1px black solid;
  background-color: #ddd;
}

img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

header {
  width: 100%;
  height: 100px;
  border: 1px black solid;
  position: absolute;
  top: 0;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="index.css">
    <title>anime page</title>
  </head>
  <body>
    <div class="intro">
      welcome to the anime website
    </div>
    <div class="anime hide">
      <div class="anime_picture">
        <img src="" alt="">
      </div>
      <div class="question">
        <div class="question1"></div>
        <div class="question2"></div>
        <div class="question3"></div>
        <div class="question4"></div>
      </div>
      <header>anime Quiz</header>
    </div>
  </body>
  <script src="index.js" type="text/javascript"></script>
</html>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1