1

My Next button on my quiz breaks, if I answer up to a particular question then return back a few questions and then proceed to continue the quiz. After you hit next you won't be able to proceed until you re-select an answer even though there already is an answer selected.

Full JSFiddle:
JSFiddle Link

The issue is with this: (line 121 JSFiddle)

btnNxt.onclick = function() {
   if(document.getElementById('btnNxt').hasAttribute('disabled')){
     return false;
   }
   document.getElementById('btnNxt').setAttribute('disabled', true);
   buildQuiz(page + 1)
}

When the next button is clicked it disables the attribute. I believe I need to wrap

document.getElementById('btnNxt').setAttribute('disabled', true);

Within an if statement that checks if an answer has already been provided or if it's on a new question

I tried to create something to check if there was a class with the value myAns before setting the attribute but didn't have much success

var element = document.getElementsByClassName('btnAns');
for(var i = 0; i < element.length; i++){
   if(element[i].classList.contains('selAnswer')) {
      document.getElementById('btnNxt').setAttribute('disabled', true);
      break;
   } else {
      document.getElementById('btnNxt').removeAttribute('disabled');
   }
   console.log(element[i].classList.contains('selAnswer'));
}

2 Answers 2

1

I think you need to put this "if there's already an answer to this question" check into your buildQuiz function, because the selected answer will only be visible to a DOM query after the next (but previously answered) question has been built:

function buildQuiz(pg) { 
    //code omitted for clarity...
    if (page >= 0) { 
       //code omitted for clarity...

      } else {
        //code omitted for clarity..

        if(!document.querySelector('.selAnswer')) {
           document.getElementById('btnNxt').setAttribute('disabled', true);
            console.log("no answer yet, disabling button.");       
        } else {
            console.log("success! we found an answer, enabling button.");
        }
      }
    }
  } 

var startButton = document.getElementById("startButton");
startButton.addEventListener("click", startClick);

function startClick() {
  /* Declare global variables to use throughout the quiz */
  var output = document.getElementById('output'); //Declare variable output for the element "output"
  var btn = document.getElementsByClassName('btnAns'); //Declare a variable for the class "btnAns"
  var myObj = ''; //Declare variable myObj as empty string
  var page = 0; //Declare variable page and set it to 0
  var result = 0; //Declare variable result and set it to 0
  var myQueRep = []; //Declare variable myQueRep and set as empty array
  loadQuestions(); //Fire off function loadQuestions to bring in data

  /* Create a function to retrieve JSON Object. Once object is retrieved fire the buildQuiz function*/
  function loadQuestions() { //Create a function called loadQuestions
    var xhttp = new XMLHttpRequest(); //Declare variable xhttp and asign it to create a new XMLHttpRequest
    xhttp.open('GET', 'https://api.myjson.com/bins/1453rb', true); //
    xhttp.onreadystatechange = function() { //
      if (this.readyState == 4 && this.status == 200) { //if XMLHttpRequest readyState is 4 and status code is 200
        myObj = JSON.parse(this.responseText); //Asign global variable myObj to parse the JSON string into a JavaScript object 
        buildQuiz(0); //Fire off the build quiz function passing value 0
      }
    }
    xhttp.send(); //Sends the XMLHttpRequest to the server
  }
  document.getElementById('btnNxt').setAttribute('disabled', true); //Disable the next button until an answer is provided
  /* Create a function to build a quiz */
  function buildQuiz(pg) { //Create a function called buildQuiz with variable pg that contains the value 0 that was passed through the function when fired
    page = pg; // Asign the pg to global variable page
    hideshow(); //Fire hideshow function
    if (page >= 0) { //Check if variable page is greater or equal to 0
      if (myObj.length < (page + 1)) { //Check if the object
        page = myObj.length;
        var holderHTML = '';
        var score = 0;
        var answerTxt = '';
        for (var item in myObj) {
          if (myObj[item].correct == myQueRep[item]) {
            score++;
            answerTxt = '<p class="correct"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span> ' + myObj[item].answers[myQueRep[item]] + '</p>';
          } else {
            answerTxt = '<p class="incorrect"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> ' + myObj[item].answers[myQueRep[item]] + '</p>';
          }
          holderHTML += '<div class="col-sm-12"><h4><strong>Question: ' + myObj[item].question + '</strong></h4>' + answerTxt + '</div>';
        }
        var outCome = '';
        if (score === 0) {
          outCome = 'A Dummy!';
        } else if ((score / myObj.length) * 100 <= 25) {
          outCome = 'Not So Smart';
        } else if ((score / myObj.length) * 100 <= 50) {
          outCome = ' Kinda Smart!';
        } else if ((score / myObj.length) * 100 <= 75) {
          outCome = 'Smart!';
        } else if ((score / myObj.length) * 100 <= 90) {
          outCome = 'Very Smart!';
        } else {
          outCome = 'Extremely Smart!';
        }

        output.innerHTML = '<h1>Quiz Results</h1>';
        output.innerHTML += '<h3>You Are ' + outCome + '</h3>';
        output.innerHTML += '<p><strong>You Got ' + score + ' Answers Correct</p></strong>';
        output.innerHTML += '<div class="endScore">' + holderHTML + '</div>';
        output.innerHTML += '<a href="http://localhost/quiz" class="btn btn-success btn-restart">Retake Quiz</a>';


      } else {
        var myQuestion = myObj[page].question;
        var myCorrect = myObj[page].correct;
        result = myObj[page].answers[myCorrect];
        var questionHolder = '';
        var yesCor = '';
        for (var i in myObj[page].answers) {
          var aClass = '';
          if (myObj[page].mySel == i) {
            aClass = ' selAnswer';
          }
          if (i == myCorrect) {
            yesCor = '*';
          } else {
            yesCor = '';
          }
          questionHolder += '<div class="btnAns ' + aClass + '" data-id="' + parseInt(i) + '">' + myObj[page].answers[i] + '</div>';
        }
        output.innerHTML = 'Question ' + (page + 1) + ' / ' + (myObj.length);
        output.innerHTML += '<h4 class="myQ">' + myQuestion + ' </h4>';
        output.innerHTML += questionHolder;
        for (var x = 0; x < btn.length; x++) {
          btn[x].addEventListener('click', myAnswer, false);
        }
        document.getElementById('quiz-buttons').classList.remove("hidden");

        if (!document.querySelector('.selAnswer')) {
          document.getElementById('btnNxt').setAttribute('disabled', true);
          console.log("no answer yet, disabling button.");
        } else {
          console.log("success! we found an answer, enabling button.");
        }
      }
    }
  }

  function myAnswer() {
    document.getElementById('btnNxt').removeAttribute('disabled');
    var myResult = '';
    var iId = this.getAttribute('data-id');
    myObj[page].mySel = iId;

    if (this.innerText == result) {
      myResult = 'correct';
    } else {
      myResult = 'incorrect';
    }

    myQueRep[page] = iId;
    for (var x = 0; x < btn.length; x++) {
      if (iId == x) {
        btn[x].classList.add('selAnswer');
      } else {
        btn[x].classList.remove('selAnswer');
      }
    }
  }

  //event listeners
  btnPre.onclick = function() {
    buildQuiz(page - 1);
    document.getElementById('btnNxt').removeAttribute('disabled');
  }
  btnNxt.onclick = function() {
    if (document.getElementById('btnNxt').hasAttribute('disabled')) {
      return false;
    }

    buildQuiz(page + 1)
  }

  function hideshow() {
    if (0 >= page) {
      document.getElementById('btnPre').style.display = 'none';
    } else {
      document.getElementById('btnPre').style.display = 'block';
    }

    if (myObj.length <= page) {
      document.getElementById('quiz-buttons').classList.add('hidden');
    }
  }
}
#intro h2 {
  margin-top: 0;
}

#output h1 {
  margin-top: 0;
}

#output h3 {
  margin-top: 10px;
}

#output .btn-restart {
  margin-top: 10px;
}

.myQ {
  font-size: 12px;
  font-weight: bold;
}

.btnAns {
  border: 1px solid #ddd;
  padding: 10px;
  text-align: center;
  display: block;
  font-size: 12px;
  background: #fff;
  -moz-user-select: -moz-none;
  -khtml-user-select: none;
  -webkit-user-select: none;
}

.endScore p {
  font-size: 18px;
}

.endScore .correct {
  color: #5cb85c;
}

.endScore .incorrect {
  color: #d9534f;
}

.endScore h4 {
  margin-bottom: 3px;
}

.endScore span {
  font-size: 15px;
}

.btnAns:hover {
  background-color: #6c757d;
  color: #ffffff;
  cursor: pointer;
}

.selAnswer {
  background-color: #337ab7;
  color: #ffffff;
}

.selAnswer:hover {
  background-color: #337ab7;
}

#quiz-buttons {
  margin: 1px 0;
}

#quiz-buttons .col-xs-6 {
  padding: 0;
}

.quiz {
  margin: 50px auto;
}

@media(min-width: 700px) {
  .quiz {
    width: 650px;
  }
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="quiz container">
  <div class="quiz-output row">
    <div class="col-xs-12">

      <div id="output">
        <div id="intro">
          <h2>Online Quiz</h2>
          <p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. </p>
          <div id="startButton" class="btn btn-success">Start quiz</div>
        </div>
      </div>
    </div>
  </div>
  <div id="quiz-buttons" class="row hidden">
    <div class="col-xs-6">
      <div id="btnPre" class="btn btn-primary pull-left"><span class="glyphicon glyphicon-chevron-left"></span></div>
    </div>
    <div class="col-xs-6">
      <div id="btnNxt" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-chevron-right"></span></div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

1

I would suggest using the mySel object on your myObj. That way you aren't depending on css and classes, but rather the data your using. Here is a fiddle.

   //event listeners
   btnPre.onclick = function() {
      buildQuiz(page - 1);
      document.getElementById('btnNxt').removeAttribute('disabled');
   }

   btnNxt.onclick = function() {
      if (document.getElementById('btnNxt').hasAttribute('disabled')) {
         return false;
      }
      // change is here. Checking to see if next question has been answered.
      if (typeof myObj[page + 1].mySel === "undefined") {
         document.getElementById('btnNxt').setAttribute('disabled', true);
      }

      buildQuiz(page + 1)
   }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.