0

In my below work,I fetched serial 10 data,and show this data in button.

When I click button,the desired result is to show next choices.

But when I try this,$(".choice") selector may not work well.

The following button is generated by js, is this cause of issue?

<button class='choice'>"+arr[i]+"</button>

If someone has any opinion, please let me know.

Thanks

// const fetch = require("node-fetch");

let clicked=0;

var apikey="https://opentdb.com/api.php?amount=10&type=multiple";

$(".start").on("click",function(){

  
  fetch(apikey)
  fetch(apikey)
    .then(response => response.json())
    .then(json => {
      
      console.log(json);
      
      display(json,0);
      
      $(".choice").on("click",function() {
          clicked++;
          console.log("#");
          console.log("clicked",clicked);
          display(json,clicked);
      });
    });
});



function display(json,clicked){
  
      const arr = [json.results[clicked].correct_answer].concat(json.results[clicked].incorrect_answers);
  
      let html="";
      
      for (let i=0;i<arr.length; i++){
        html+= "<button class='choice'>"+arr[i]+"</button><br>";
      }
      document.querySelector('.btn').innerHTML = html;
}
<!DOCTYPE html>


<html>
    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script data-main="js/main.js" src="bower_components/requirejs/require.js"></script>

        
        <div class="btn">       
            <button type="button" class="start">Start</button>
        </div>
    
    <script type="text/javascript" src="main.js"></script>
    
</html>
Heisenberg
  • 4,787
  • 9
  • 47
  • 76
  • try using `$(document).find('.choice')` – Mohan Singh May 03 '20 at 13:58
  • 1
    Try using $(document).on("click", ".choice", function() { }); as you need to delegate events from already existing parent elements to dynamically created elements in order to work. Check this for details: https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – matthias_h May 03 '20 at 14:04

1 Answers1

0

I set up the game that I understood from your code (no jQuery).

  1. You can only start if the data has arrived
  2. The choices (buttons) are shuffled, so it's not always the first that wins (shuffling came from here: How to randomize (shuffle) a JavaScript array?)
  3. The game keeps track of correct answers

Maybe it looks a bit more complicated than you did, but (almost) everything is separated to functions, so modifying them is easier (the display, the data and the game logic is decoupled)

// used variables
const url = "https://opentdb.com/api.php?amount=10&type=multiple"
const startBtn = document.getElementById('btn-start')
const progress = document.getElementById('progress')
const question = document.getElementById('question')
const choices = document.getElementById('choices')
let results = ''
let questionId = 0
let correct = 0

// fetching the data
const fetchData = async(url) => {
  // try-catch for handling fetch errors
  try {
    const resp = await fetch(url)
    const json = await resp.json()
    // only returning the questions and results
    return json.results
  } catch (err) {
    console.log(err)
  }
}

// only allow clicks on start button if the data has arrived
(async function() {
  results = await fetchData(url)
  startBtn.removeAttribute('disabled')
})();

// starting off with the game
startBtn.addEventListener('click', function(e) {
  this.classList.add('started')
  nextQuestion(correct, results, questionId)
})

// setting up the next question
const nextQuestion = (correct, results, questionId) => {
  // set progress indicator
  progress.innerHTML = progressText(correct, results.length)

  // set question string
  question.innerHTML = results[questionId].question

  // set buttons to click
  choices.innerHTML = setChoices(results[questionId].correct_answer, results[questionId].incorrect_answers)

  // adding event listeners to buttons
  const answerBtns = document.querySelectorAll(".answer")
  answerBtns.forEach(e => {
    e.addEventListener('click', function(e) {
      const answer = e.target.getAttribute('data-val')

      // checking for correct answer (and existence of next answer)
      if (results[questionId] && answer === results[questionId].correct_answer) {
        correct++
      }
      questionId++

      // creating next question 'scene'
      if (questionId < results.length) {
        nextQuestion(correct, results, questionId)
      }
    })
  })
}

// creating progress indicator string
const progressText = (correct, all) => {
  return `${correct}/${all}`
}

// setting choice buttons
const setChoices = (correct, incorrect) => {
  let answers = shuffleArray([correct, ...incorrect])
  let html = ''
  answers.forEach(e => {
    html += `<button class="answer" data-val="${e}">${e}</button><br />`
  })
  return html
}

// shuffling the choice array for a little fun
const shuffleArray = (array) => {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array
}
.start.started {
  display: none;
}
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<div class="btn">
  <button id="btn-start" type="button" class="start" disabled>Start</button>
  <div id="game">
    <h3 id="progress"></h3>
    <h2 id="question"></h2>
    <div id="choices"></div>
  </div>
</div>
muka.gergely
  • 8,063
  • 2
  • 17
  • 34