Home > Enterprise >  JS - I can get the value of input but not compare it
JS - I can get the value of input but not compare it

Time:02-03

I'm learning JS and I'm trying to create a web game with javascript. The goal is simple: a flag is displayed at random, and the player must guess the name of the country associated with the flag. The flag is randomly selected and displayed correctly, but I have a problem with the user interaction. I'd like to display "bad answer" in a <p> and if it's correct, display "good answer" (in a <p>), regenerate a flag and start again, indefinitely. The problem is that I can get the user's answer but i can't compare it to real answer and then display true or false.

I would like to know if someone could explain to me what is wrong and correct me please. Here is my code :

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function getVal() {
  const inputValue = document.querySelector('input').value;
  console.log(inputValue);
}

function getData() {
  var json = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/index.json'

  fetch(json)
    .then(data => data.json())
    .then(data => {
      const randomInt = getRandomInt(data.length);
      console.log(data[randomInt]);
      var image = document.getElementById("flag");
      image.src = data[randomInt].image;
    });

  if (inputValue != data[randomInt].name.toLowerCase()) {
    document.getElementsByClassName('result').class.add("result-false");
    document.getElementsByClassName('result').innerHTML = 'Mauvaise Réponse';
  } else if (inputValue == data[randomInt].name.toLowerCase()) {
    document.getElementsByClassName('result').class.add("result-true");
    document.getElementsByClassName('result').innerHTML = 'Bonne Réponse';
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Guess The Flag - </title>
  <link rel="stylesheet" href="style.css">
  <!-- <script type="text/js" src="app.js"></script> -->
</head>

<body>

  <h1>GuessTheFlag</h1>

  <div >
    <img id="flag" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/images/KH.svg" alt="">
  </div>

  <input type="text" name="flagName">
  <button type="submit" onclick="getVal()">Je valide</button>

  <p ></p><br>
  <button onclick="getData()">Next</button>

</body>

</html>

CodePudding user response:

The reason is because the scope of inputValue is inside the function getVal only. So in function getData it doesn't know inputValue.

The scope is the perimeter where the variable is known, it could be globally, local to a function, or at other level. It depends where and how you declare the variable. It's an important thing to understand in most of the computer langage.

CodePudding user response:

Here's a refactored working version with some comments to help clear things out:

function getRandomInt(max) {
    return Math.floor(Math.random() * max);
}

let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()

  function getVal() {
    const inputValue = document.querySelector('input').value;

    //>> Move the flag vs input comparison inside the input event handler:
    if ( inputValue.toLowerCase() !== flag.toLowerCase()) { // <= Lowercasing both input and flag name to avoid case sensitive comparison failures
            // Use `classList` instead of `class` to have access to the add() method
            // Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
            document.querySelector('.result').classList.add("result-false");
            document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
    // No need for an else if here:
    } else {
        document.querySelector('.result').classList.add("result-true");
        document.querySelector('.result').innerHTML = 'Bonne Réponse';
    }   
}

// TIP: Ideally the next function should be split into 2 functions:
// 1) fetchData(), runs once to grab the JSON
// 2) getRandomFlag(), runs on 'Next' click to get a random flag 
// without re-fetching the JSON.
function getData() {
    var json = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/index.json'
    fetch(json)
        .then(data=>data.json())
        .then(data=> {
            const randomInt = getRandomInt(data.length);
            console.log(data[randomInt]);        
            var image = document.getElementById("flag");
            image.src = data[randomInt].image;
            flag = data[randomInt].name; // <= Set the value for the newly fetched flag name
        });


}

Working demo:

function getRandomInt(max) {
    return Math.floor(Math.random() * max);
}

let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()

  function getVal() {
    const inputValue = document.querySelector('input').value;

    //>> Move the flag vs input comparison inside the input event handler:
    if(inputValue.toLowerCase() != flag.toLowerCase()) {
            // Use `classList` instead of `class` to have access to the add() method
            // Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
            document.querySelector('.result').classList.add("result-false");
            document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
    } else {
        document.querySelector('.result').classList.add("result-true");
        document.querySelector('.result').innerHTML = 'Bonne Réponse';
    }   
}
function getData() {
    var json = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/index.json'
    fetch(json)
        .then(data=>data.json())
        .then(data=> {
            const randomInt = getRandomInt(data.length);
            console.log(data[randomInt]);        
            var image = document.getElementById("flag");
            image.src = data[randomInt].image;
            flag = data[randomInt].name;
        });


}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Guess The Flag - </title>
    <link rel="stylesheet" href="style.css">
    <!-- <script type="text/js" src="app.js"></script> -->
</head>
<body>
    
<h1>GuessTheFlag</h1>

    <div >
        <img width="100" id="flag" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/images/KH.svg" alt="">
    </div>

    <input type="text" name="flagName">
    <button type="submit" onclick="getVal()">Je valide</button>  

    <p ></p><br>
    <button onclick="getData()">Next</button>
    
</body>
</html>

There's a lot of refactoring that we can do (e.g. caching the selected elements, cache the json response to avoid re-fetching the data, removing global variables, etc.) to improve the code, but this is just a good start for a functional code.

  • Related