简体   繁体   中英

Changing the class of the next() element is changing the class of the last sibling using jQuery

I'm learning Javascript and I having a problem which I don't seem to understand. I am making a simple quiz app. Each question is within a div tag that can be active or inactive. If the div tag is active the question is red and if its inactive the question is black.

The questions are added to the HTML based on this js code.

var questionOne = { question: "A?",
                    choices: ["4", "7", "6", "5"],
                    correctAnswer:3 }
var questionTwo = { question: "B?",
                    choices: ["4", "7", "6", "5"],
                    correctAnswer:0 }
var questionThree = { question: "C",
                    choices: ["4", "7", "6", "5"],
                    correctAnswer:2 }
var allQuestions = [questionOne,questionTwo,questionThree]

var questionNumber = 0;
var selectedAnswerValue;
var score = 0;

var main = function() {
  for(var j=0; j<allQuestions.length; j++) {
    var currentQuestion = allQuestions[j];

    var questionDiv = $('<div/>', {
                         "class": ("question" + j + " inactive")
                        });
    questionDiv.appendTo('.form-group');

    var h1Question = $('<h1/>').text(currentQuestion.question);
    h1Question.appendTo(('.question' + j));

    var answersDiv = $('<div/>', {
                       "class": ("answers" + j)
                        });
    answersDiv.appendTo(('.question' + j));


    for(var i=0;i<currentQuestion.choices.length;i++) {
      var radioBtn = $('<div class="radio"><label><input type="radio" name="question' + j + '" value="'
                        + i + '">' + currentQuestion.choices[i]
                        + '</label></div>');
      radioBtn.appendTo(('.answers' + j));
    }

    $('.btn').click(function() {
      var currentActiveQuestion = $('.active');
      var nextQuestion = currentActiveQuestion.next();

      nextQuestion.addClass('active').removeClass('inactive');
      currentActiveQuestion.removeClass('active').addClass('inactive');

    });
  }
};

$(document).ready(main);

This code also have an event listener on a button that triggers on click and in theory changes the active(BLACK) div to inactive(RED) and the next() inactive div to active. So in this case, what I want is the question A to turn red and all other black. But instead changes only the last element to active like this:

在此处输入图片说明 在此处输入图片说明

Then after ONE button click:

在此处输入图片说明 在此处输入图片说明

I have tried lots of changes but nothing seems to work. Any help is welcome. Thanks!

My HTML code is this:

    <!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">
        <title>Quiz App</title>
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <link href="quiz.css" rel="stylesheet">
      </head>
      <body>
        <div class="form-group">
          <div class="tittle active">
            <h1>Quiz</h1>
          </div>
        </div>
        <div>
          <button id="btn" type="button" class="btn btn-success">NEXT</button>
        </div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script src="js/bootstrap.min.js"></script>
        <script src="quiz.js"></script>
      </body>
    </html>

And the resulting html formed from my js is this:

<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">
    <title>Quiz App</title>
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="quiz.css" rel="stylesheet">
  </head>
  <body>
      <div class="form-group">
        <div class="tittle active">
          <h1>Quiz</h1>
        </div>
      <div class="question0 inactive">
        <h1>A?</h1>
        <div class="answers0">
          <div class="radio"><label><input type="radio" name="question0" value="0">4</label></div>
          <div class="radio"><label><input type="radio" name="question0" value="1">7</label></div>
          <div class="radio"><label><input type="radio" name="question0" value="2">6</label></div>
          <div class="radio"><label><input type="radio" name="question0" value="3">5</label></div>
        </div>
      </div>
      <div class="question1 inactive">
        <h1>B?</h1>
        <div class="answers1">
          <div class="radio"><label><input type="radio" name="question1" value="0">4</label></div>
          <div class="radio"><label><input type="radio" name="question1" value="1">7</label></div>
          <div class="radio"><label><input type="radio" name="question1" value="2">6</label></div>
          <div class="radio"><label><input type="radio" name="question1" value="3">5</label></div>
        </div>
      </div>
      <div class="question2 inactive">
        <h1>C</h1>
        <div class="answers2">
          <div class="radio"><label><input type="radio" name="question2" value="0">4</label></div>
          <div class="radio"><label><input type="radio" name="question2" value="1">7</label></div>
          <div class="radio"><label><input type="radio" name="question2" value="2">6</label></div>
          <div class="radio"><label><input type="radio" name="question2" value="3">5</label></div>
        </div>
      </div>
    </div>
    <div>
      <button id="btn" type="button" class="btn btn-success">NEXT</button>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script src="quiz.js"></script>
</body></html>

After trying several things I finally found the solution:

ORDER IS IMPORTANT

The solution was to put the event listener of the button first and then the script dynamicaly generating the elements. Like this:

var main = function() {
  $('#btn').click(function() {
    var currentActiveQuestion = $('.active');
    var nextQuestion = currentActiveQuestion.next();

    currentActiveQuestion.removeClass('active');

    nextQuestion.addClass('active');
  });

  for(var j=0; j<allQuestions.length; j++) {
    var currentQuestion = allQuestions[j];

    var questionDiv = $('<div/>', {
                         "class": ("question" + j)
                        });
    questionDiv.appendTo('.form-group');

    var h1Question = $('<h1/>').text(currentQuestion.question);
    h1Question.appendTo(('.question' + j));

    var answersDiv = $('<div/>', {
                       "class": ("answers" + j)
                        });
    answersDiv.appendTo(('.question' + j));


    for(var i=0;i<currentQuestion.choices.length;i++) {
      var radioBtn = $('<div class="radio"><label><input type="radio" name="question' + j + '" value="'
                        + i + '">' + currentQuestion.choices[i]
                        + '</label></div>');
      radioBtn.appendTo(('.answers' + j));
    }
  }
};

$(document).ready(main);

I'm not completely sure of the cause, because I'm a beginner, but I can't imagine the scrypt for the dynamically generated elements was messing with the classes of the elements before the click event.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM