0

I am trying to make a quizz with random questions. I would like each question to be accompanied by a sound clip that plays automatically as soon as the question is shown. I would also like to have a button that makes it possible for the user to replay the sound clip. How can I achieve this, exactly?

I know how to play individual audio clips with audioClips.play();. But how about playing audio clips from an array, "synchronized" with the questions?

This is what I have so far:

var country = ["Italy", "Spain", "Portugal", "France", "Greece", "Ireland", "Germany"];
var audioClips = ["italy.mp3", "spain.mp3", "portugal.mp3", "france.mp3", "greece.mp3", "ireland.mp3", "germany.mp3"];
var capital = ["rome", "madrid", "lisbon", "paris", "athens", "dublin", "berlin"];
var random001 = Math.floor(Math.random() * country.length);

document.getElementById("country").textContent = country[random001];

function submit001() {
    var b = input001.value.toLowerCase();
    var text;
    if (b === capital[random001]) {
    goToNextQuestion();
        text = "Correct!";
    } else {
        text = input001.value.bold() + " is not correct!";
    }
    document.getElementById("input001").value = "";
    document.getElementById("answer001").innerHTML = text;
}

function goToNextQuestion() {
    document.getElementById("answer001").innerHTML = "";
    random001 = Math.floor(Math.random() * country.length);
    document.getElementById("country").innerHTML = country[random001];
    document.getElementById("input001").focus();
}
<p id="message001">What is the capital of <text id="country"></text>?</p>
    <input type="text" id="input001" autofocus onKeyDown="if(event.keyCode==13) submit001()">
<p id="answer001"></p>
<button onclick="playAudio()" type="button">Replay Audio</button>
MikeMichaels
  • 454
  • 1
  • 6
  • 25
  • you will have an equal number of entries in both questions and audio array. If the random question is on 3rd index then use the same index with the audio array. – Mean Coder Oct 12 '18 at 17:41
  • Thank you for your help. I am still learning JavaScript so I'm sorry if it is a noob question, but how do I do that exactly? – MikeMichaels Oct 12 '18 at 17:51

2 Answers2

1

With this problem you're thinking in terms of Arrays and you need to think in terms of Objects. Combine the related information into an Object and you can accomplish your goal with clear, easy-to-read code.

To make this work I had to extensively refactor your code. Here's what I came up with.

HTML

<head>
  <style>
    #startButton {
      display: block;
    }

    #quiz {
      display: none;
    }
  </style>
</head>
<body>
  <div id="startButton">
    <button type="button" onclick="startQuiz()">Start Quiz</button>
  </div>
  <div id="quiz">
    <p id="message001">What is the capital of <text id="country"></text>?</p>
    <input type="text" id="input001" autofocus onKeyDown="if(event.keyCode==13) checkAnswer()" value="">
    <p id="answer001"></p>
    <button id="replayButton" type="button" onclick="setAudio()">Replay Audio</button>
  </div>
</body>

Javascript

<script>
  var country = {
    "Italy": {
      "audio": "italy.mp3",
      "capital": "rome"
    },
    "Spain": {
      "audio": "spain.mp3",
      "capital": "madrid"
    },
    "Portugal": {
      "audio": "portugal.mp3",
      "capital": "lisbon"
    },
    "France": {
      "audio": "france.mp3",
      "capital": "paris"
    },
    "Greece": {
      "audio": "greece.mp3",
      "capital": "athens"
    },
    "Ireland": {
      "audio": "ireland.mp3",
      "capital": "dublin"
    },
    "Germany": {
      "audio": "germany.mp3",
      "capital": "berlin"
    }
  };

  var countryArray = Object.keys(country);

  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;

  }

  function nextCountryName(){
    let randIndex = getRandomInt(1, countryArray.length) - 1;
    return countryArray[randIndex];
  };

  function playAudio(file){
    let playFile = new Audio(file);
    playFile.play();
  }

  function newCountry(newCountryName) {

    document.getElementById("country").textContent = newCountryName;
    document.getElementById("input001").value = "";
  }

  function isAnswerCorrect(answer, useCountry) {
    let answerId = document.getElementById("answer001");
    let ans = answer.toLowerCase();
    let text;

    if(ans == country[useCountry].capital){
      answerId.innerHTML = "Correct!";
      return true;
    } else {
      answerId.innerHTML = ans.bold() + " is not correct!";
      return false;
    }
  };

  function setAudio(){
    let thisCountry = document.getElementById("country").textContent;
    let audioFile = country[thisCountry].audio;
    let callStr = "playAudio(\'" + audioFile + "\')";
    document.getElementById('replayButton').setAttribute('onclick', callStr);
  }

  function checkAnswer(){
    let inputId = document.getElementById('input001');
    let answer = inputId.value;
    let thisCountry = document.getElementById("country").textContent;
    let audioFile = country[thisCountry].audio;
    let result = isAnswerCorrect(answer, thisCountry);

    if(result) {
      let cntryName = nextCountryName();
      newCountry(cntryName);
      playAudio(country[cntryName].audio);
    }
  };

  function startQuiz(){
    let startingCountry = nextCountryName();
    newCountry(startingCountry);

    document.getElementById('startButton').style.display = "none";
    document.getElementById('quiz').style.display = "block";

    playAudio(country[startingCountry].audio);
  };    
</script>
  • I converted var country, var audioClips, and var capital arrays into a single Object named var country. This way you can use country.capital or country.audio to get the value you're looking for.
  • According to this answer it is suggested that you set the audio file type new Audio("file_name") before calling the .play() method.

While answer002, answer003, input002, input003, etc is beyond the scope of your question this code could be easily modified accept such parameters to account for a more extensive quiz.

holaymolay
  • 520
  • 4
  • 17
  • Thank you very much for your help. But that doesn't seem to work as intended. It plays each countries' audio clip only after the user answers correctly. Instead, I would like the audio to play when the country is shown. – MikeMichaels Oct 12 '18 at 20:06
  • @MikeMichaels Easy enough to fix. I assumed you wanted to replay after the answer was submitted since the button name is "Replay Audio". Hold on and i'll fix it. – holaymolay Oct 12 '18 at 20:08
  • @MikeMichaels do you want to check the answer when the button is clicked or do you ONLY want to play the sound? – holaymolay Oct 12 '18 at 20:10
  • I want the button to only replay the sound of the current question. To check the answer, the user will press the Enter key. – MikeMichaels Oct 12 '18 at 20:13
  • @MikeMichaels yeah, i did notice that on second glance. Ok give me a sec – holaymolay Oct 12 '18 at 20:14
  • @MikeMichaels chrome is now blocking auto-play of sound. We can get the sound to play upon clicking a button, but not without user interaction such as an `onload` event. I will update my answer to play the sound when it goes to the next question, but I will not work on the first question. – holaymolay Oct 12 '18 at 20:35
  • So, if we add a "start button" to start the quizz, would it work? – MikeMichaels Oct 12 '18 at 20:44
  • @MikeMichaels yes a start button would work. I've found a quazi-workaround for the other questions, but for the first one you will need an onclick event to trigger the first sound. – holaymolay Oct 12 '18 at 21:02
  • @MikeMichaels just run the playAudio() method with the audio file name and it should play – holaymolay Oct 12 '18 at 21:07
  • I'm having trouble making the new button work. Could you please help me one more time and edit the code? I must be doing somethig wrong. I just don't know what... – MikeMichaels Oct 12 '18 at 21:18
  • It does work! Thank you very much for all the trouble. – MikeMichaels Oct 13 '18 at 12:03
0
function playAudio() {
  // if you know how to play audio then follow these step
  //1. get file name from audioClips array at index randome001 like
  audioClip = audioClips[random001]
  // do whatever you need to do before playing audio like loading audio file or whatever
  //2. play audioClip.
}`
Mean Coder
  • 304
  • 1
  • 12