0

So the goal of my website is to be a simple quiz game. It gets an array of json questions with ajax and then for each question in the array it displays the actual question and creates buttons with all kinds of options to choose from that also were stored in the question object. I can't seem to get this to work either. When you click a button, it should go to the next question-object in the json array. I'm using a Quiz object to keep track of that. Now I get errors while creating the objects, not when I initiate them as instances.

When I try to create a new QuestionHandler object by returning it through a getQuestionhandler function, it gives me this as an error in the Chrome dev tools:

Uncaught TypeError: Cannot read property 'undefined' of undefined
at getQuestionHandler (Handlers.js:95)
at new QuizGame (Handlers.js:68)
at QuizIndex.html:37

This is my whole code without css styling:

/*function GetJsonQuestions(){
   var url = "https://api.myjson.com/bins/10t76x";
    $.ajax({
    url: url,
    data: "json",
    success: function(){
        console.log("get is successfull");
    },
    dataType: dataType
});
}*/


var urlJson = "https://api.myjson.com/bins/10t76x";

var QuestionHandler = function(question, options, answer) {

  this.question = question;
  this.options = options;
  this.answer = answer;

  this.isCorrect = function(guess) {

    if (this.answer === guess) {
      return true;
    }

  };

};

var PointsHandler = function() {

  this.points = 0;

  this.addPoint = function() {
    this.points++;
  };


};

var getAllData = function() {
  var allData = null;

  $.ajax({
    url: urlJson,
    type: 'GET',
    dataType: 'json', // added data type
    success: function(res) {
      console.log(res);
      allData = res.questions;
    },
    error: function(err) {
      console.log("error: " + err);


    }
  });

  return allData;
};

var QuizGame = function() {
  this.index = 0;
  this.allJsonData = getAllData();
  this.pointHandler = getPointsHandler();
  this.questionHandler = getQuestionHandler();
  this.gameResult = getResult();
  this.getPoints = function() {
    return this.pointHandler.points;
  };


  this.nextQuestion = function(quess) {
    index++;
    var correct = questionHandler.isCorrect(guess);
    if (correct) {
      pointsHandler.addPoints();
    }

  };

  function getPointsHandler() {
    var handler = new PointsHandler();
    return handler;
  }


  function getResult() {
    return "You answered " + this.points + " correct out of " + this.index + " questions";
  }

  function getQuestionHandler() {
    var qHandler = new QuestionHandler(this.allJsonData[this.index].question, this.allJsonData[this.index].options, this.allJsonData[this.index].answer);
    return qHandler; //this function seems to be giving the error
  }
};

var myQuiz = new QuizGame();


console.log(myQuiz.allJsonData);

$("#question").text("Question nr " + myQuiz.index + " : " + myQuiz.questionHandler.question);

$.each(myQuiz.questionHandler.options, function(i, val) {

  $("#options").append("<button>" + val + "</button>");


});

$("button").click(function(e) {


  if (myQuiz.index <= myQuiz.allJsonData.length) {

    myQuiz.nextQuestion(e.target.nodeValue);


  }

});
<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="quizStyle.css">


  <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous">
  </script>


  <script src="Handlers.js"></script>
  <title>Quiz time</title>
</head>

<body>
  <h1></h1>

  <div id="quizDiv">
    <p>Question:</p>
    <h2 id="question">Test</h2>
    <p>Answers:</p>
    <div id="options">

    </div>
  </div>

  <div id="resultDiv">
    <p id="yourResult">You got x out x right!</p>
  </div>

  <script>
  </script>
</body>

</html>

What is causing the error and how do I fix it?

Ka ri ma
  • 13
  • 4
  • What is your line 95 exactly? – Eran Machiels Feb 13 '17 at 16:51
  • You're calling `getQuestionHandler` without the context. See [How does the this keyword work](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work/3127440#3127440). Note, that there are other similar issues in the code. – Teemu Feb 13 '17 at 17:03

2 Answers2

0

This is a functional and fixed example of your code. It does not move to the next question as it does not appear that you have programmed it to do so yet.

var urlJson = "https://api.myjson.com/bins/10t76x";

var QuestionHandler = function(question, options, answer) {

  this.question = question;
  this.options = options;
  this.answer = answer;

  this.isCorrect = function(guess) {
  rtn = false;
    if(this.answer === guess) rtn = true;
  return rtn;
  };

};

var PointsHandler = function() {

  this.points = 0;

  this.addPoint = function() {
    this.points++;
  };


};

var getAllData = function() {
  var allData = null;

  $.ajax({
    url: urlJson,
    type: 'GET',
  async: false,
    dataType: 'json',
    success: function(res) {
      allData = res.questions;
    },
    error: function(err) {
      console.log("error: " + err);
    }
  });
  return allData;
};

var QuizGame = function() {

  function getResult() {
    return "You answered " + this.points + " correct out of " + this.index + " questions";
  }
 
  this.index = 0;
  this.allJsonData = getAllData();
  this.pointsHandler = new PointsHandler();
  this.questionHandler = new QuestionHandler(this.allJsonData[this.index].question, this.allJsonData[this.index].options, this.allJsonData[this.index].answer);
  this.gameResult = getResult();
  this.getPoints = function() {
    return this.pointHandler.points;
  };


  this.nextQuestion = function(guess) {
  
  this.index++;
  
  var correct = this.questionHandler.isCorrect( guess );
    
  console.log( correct );

  if (correct) {
      this.pointsHandler.addPoint();
    }
  
  console.log(this);
  
  };
 
};

var myQuiz = new QuizGame();

$("#question").text("Question " + (myQuiz.index + 1) + ": " + myQuiz.questionHandler.question);

$.each(myQuiz.questionHandler.options, function(i, val) {

  $("#options").append("<button>" + val + "</button>");


});

$("button").click(function(e) {
  if (myQuiz.index <= myQuiz.allJsonData.length) {
    myQuiz.nextQuestion(this.innerText.trim());
  }
});
<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="quizStyle.css">


  <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous">
  </script>


  <script src="Handlers.js"></script>
  <title>Quiz time</title>
</head>

<body>
  <h1></h1>

  <div id="quizDiv">
    <p>Question:</p>
    <h2 id="question">Test</h2>
    <p>Answers:</p>
    <div id="options">

    </div>
  </div>

  <div id="resultDiv">
    <p id="yourResult">You got x out x right!</p>
  </div>

  <script>
  </script>
</body>

</html>
Lucas Shanley
  • 343
  • 1
  • 7
0

there are multiple mistakes/errors in your code.

Main issue: you cant return allData from getAllData since its a AJAX (async call)

i refactored all of them and here is a working example.

var urlJson = "https://api.myjson.com/bins/10t76x";

var QuestionHandler = function(question, options, answer) {
  var self = this;
  self.question = question;
  self.options = options;
  self.answer = answer;
  self.isCorrect = function(guess) { return self.answer === guess; }
};

var PointsHandler = function() {
  var self = this;
  self.points = 0;
  self.addPoints = function() { self.points++; }
};

var QuizGame = function(data) {
  var self = this;
  self.index = 0;
  self.allJsonData = data;
  self.pointsHandler = getPointsHandler();
  self.questionHandlers = getQuestionHandlers();
  self.gameResult = getResult;
  self.getPoints = function() {
    return self.pointsHandler.points;
  };

  self.nextQuestion = function(guess) {
    var correct = self.questionHandlers[self.index].isCorrect(guess);
    if (correct) {
      self.pointsHandler.addPoints();
    }
    self.index++;
    if (self.index < self.allJsonData.length) {
 update(self);
    } else {
        done(self);
    }
  };

  function getPointsHandler() { return  new PointsHandler(); }

  function getResult() {
    return "You answered " + self.pointsHandler.points + " correct out of " + self.index + " questions";
  }

  function getQuestionHandlers() {
    return self.allJsonData.map(function(d) { return new QuestionHandler(d.question, d.options, d.answer); });
  }
};


function getAllData() {
  $.ajax({
    url: urlJson,
    type: 'GET',
    dataType: 'json', // added data type
    success: onSuccess,
    error: function(err) { console.log("error: " + err); }
  });
};

function onSuccess(res) {
  var myQuiz = new QuizGame(res.questions);
  update(myQuiz);
}

function update(myQuiz) {
  $("#question").text("Question nr " + (myQuiz.index + 1) + " : " + myQuiz.questionHandlers[myQuiz.index].question);
  $("#options").empty();
  $.each(myQuiz.questionHandlers[myQuiz.index].options, function(i, val) {
    $("#options").append("<button>" + val + "</button>");
  });

  $("button").click(function(e) { myQuiz.nextQuestion(e.target.innerText); });
  $('#yourResult').text(myQuiz.gameResult());

}

function done(myQuiz) {
  $("#quizDiv").text('Completed.');
  $('#yourResult').text(myQuiz.gameResult());
}

getAllData();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="quizDiv">
  <p>Question:</p>
  <h2 id="question">Test</h2>
  <p>Answers:</p>
  <div id="options"></div>
</div>
<div id="resultDiv">
  <p id="yourResult">You got x out x right!</p>
</div>
Ja9ad335h
  • 4,405
  • 2
  • 16
  • 23