Обновление трекера ответов на тесты с использованием JavaScript

#javascript #html

#javascript #HTML

Вопрос:

Я разрабатываю простое приложение для викторины с использованием ванильного JavaScript и HTML. Функциональность, позволяющая узнать, правильный или неправильный выбранный ответ, и отобразить некоторую обратную связь, работает, но не функциональность для установки .quiz__marker атрибута данных div на «Правильный» или «Неправильный» при выборе переключателя вопроса. Мой упрощенный код включен в приведенный ниже фрагмент.

Я установил .quiz__marker для divs значение зеленого или красного цвета в зависимости от того, выбран правильный или неправильный ответ. Как вы можете видеть, все кружки становятся зелеными или красными при выборе переключателя.

Как я должен настроить свой JS-код, чтобы применять изменение цвета только к одному кругу? Кроме того, что мне нужно реализовать, чтобы цвет сохранялся на протяжении всего теста?

Я изучаю JavaScript по ходу дела. Предпочтительнее использовать ванильные ответы на JS.

Приветствия!

Обновление — включено полное quiz.js для целей проверки

 function answerTracker() {
  const tracker = document.querySelector(".quiz__tracker");
  // Each quiz contains eight or less questions
  const questions = 8;
  for (let i = 1; i <= questions; i  ) {
    let trackerMarker = document.createElement("div");
    trackerMarker.className = "quiz__marker";
    trackerMarker.id = "marker_"   i;
    trackerMarker.setAttribute("data-answer", "");
    tracker.appendChild(trackerMarker);
  }
}

function questionMarkers() {
  let labels = document.querySelectorAll("div[class*='rsform-block-question'] .formControlLabel");
  let count = labels.length;
  for (let i = 0; i < count; i  ) {
    let marker = `<span class="question-marker">${i   1}</span>`;
    labels[i].insertAdjacentHTML("beforebegin", marker);
  }
}

const runQuiz = (() => {
  // Generate tracker
  answerTracker();

  // Append question markers to labels
  questionMarkers();

  // Set quiz score to zero
  let score = 0;

  let markers = document.querySelectorAll(".quiz__marker");

  let answers = document.querySelectorAll(".rsform-radio");
  answers.forEach(function (answer) {
    answer.addEventListener("click", (e) => {
      let target    = e.target;
      let container = target.closest(".formContainer");
      let correct   = container.querySelector("div[class$='true']");
      let wrong     = container.querySelector("div[class$='false']");
      let feedback  = container.querySelector("div[class$='feedback']");
      let question  = container.querySelector("div[class*='rsform-block-question']");
      let next      = container.querySelector(".js-btn--next.success");
      let submit    = container.querySelector(".js-btn--submit.rsform-submit-button");

      if (e.target.value == "t") {
        // If answer is correct, increment the user's score by one
        score  ;
        correct.style.display = "block";
        wrong.style.display = "none";
        feedback.style.display = "block";
        document.getElementById("marker_"   e.target.dataset.num).setAttribute("data-answer", "Correct");
      } else {
        correct.style.display = "none";
        wrong.style.display = "block";
        feedback.style.display = "block";
        document.getElementById("marker_"   e.target.dataset.num).setAttribute("data-answer", "Incorrect");
      }
  
      if (next !== null amp;amp; next !== "") {
        next.style.display = "block";
      }
  
      if (submit !== null amp;amp; submit !== "") {
        submit.style.display = "block";
      }
      question.style.display = "none";
    });
  });
  // If this is the final question in the quiz, assign the score variable to the final-score hidden HTML field
  // document.getElementById("final-score").value = score;
})();
 
 function answerTracker() {
  const tracker = document.querySelector(".quiz__sidebar");
  // Each quiz contains eight questions
  const questions = 8;
  for (let i = 1; i <= questions; i  ) {
    let trackerMarker = document.createElement("div");
    trackerMarker.className = "quiz__marker";
    trackerMarker.setAttribute("data-answer", "");
    tracker.appendChild(trackerMarker);
  }
}

const runQuiz = (() => {
  // Generate answer tracker
  answerTracker();

  // Set quiz score to zero
  let score = 0;

  // Get node list of .quiz__marker DIVs
  let markers = document.querySelectorAll(".quiz__marker");

  // Get node list of answer radio buttons
  let answers = document.querySelectorAll(".rsform-radio");

  answers.forEach(function(answer) {
    answer.addEventListener("click", (e) => {
      let target = e.target;
      let container = target.closest(".formContainer");
      let correct = container.querySelector("div[class$='true']");
      let wrong = container.querySelector("div[class$='false']");
      let feedback = container.querySelector("div[class$='feedback']");
      let question = container.querySelector("div[class*='rsform-block-question']");
      let next = container.querySelector(".js-btn--next.success");

      if (e.target.value == "t") {
        // If answer is correct, increment the user's score by one
        score  ;
        correct.style.display = "block";
        wrong.style.display = "none";
        feedback.style.display = "block";
      } else {
        correct.style.display = "none";
        wrong.style.display = "block";
        feedback.style.display = "block";
      }

      // Loop through node list and set data-attribute to "Correct" or "Incorrect" depending on e.target value
      Array.from(markers).forEach(link => {
        if (e.target.value == "t") {
          link.setAttribute("data-answer", "Correct");
        } else {
          link.setAttribute("data-answer", "Incorrect");
        }
      });

      // If question has been answered, display the next button
      if (next !== null amp;amp; next !== "") {
        next.style.display = "block";
      }

    });
  });

  // If this is the final question in the quiz, assign the score variable to the final-score hidden HTML field
  // document.getElementById("final-score").value = score;
})(); 
 .quiz__sidebar .quiz__marker {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin: 6px;
  background-color: grey;
  border-radius: 50%;
}

.quiz__sidebar .quiz__marker[data-answer="Correct"] {
  background-color: green;
}

.quiz__sidebar .quiz__marker[data-answer="Incorrect"] {
  background-color: red;
}

form.quiz__form .formHidden,
form.quiz__form div[class$="true"],
form.quiz__form div[class$="false"],
form.quiz__form div[class$="feedback"],
form.quiz__form .rsform-block .rsform-button {
  display: none;
} 
 <div class="quiz">
  <div class="quiz__sidebar"></div>
  <form class="quiz__form">
    <div class="formContainer">
      <div class="rsform-block-question-one">
        <input type="radio" name="form[question-one]" value="f" id="question-one0" class="rsform-radio">
        <label for="question-one0">To attract a mate</label>
        <br>
        <input type="radio" name="form[question-one]" value="t" id="question-one1" class="rsform-radio">
        <label for="question-one1">To defend themselves against predators</label>
        <br>
        <input type="radio" name="form[question-one]" value="f" id="question-one2" class="rsform-radio">
        <label for="question-one2">To mark their territory</label>
        <br>
        <input type="radio" name="form[question-one]" value="f" id="question-one3" class="rsform-radio">
        <label for="question-one3">Because they like the smell</label>
      </div>
      <div class="rsform-block-question-one-true">
        <p>
          <strong>Correct!</strong>
        </p>
      </div>
      <div class="rsform-block-question-one-false">
        <p>
          <strong>Nice try</strong>
        </p>
      </div>
      <div class="rsform-block-question-one-feedback">
        <p>Skunks spray an extremely offensive odour to make predators go away and leave them alone. If they feel their life is in danger, they have no other defence as they cannot run fast, climb, burrow under the ground, or fight.</p>
      </div>
      <div class="rsform-block">
        <button type="button" class="btn--next js-btn--next rsform-button success button" style="display: none;">
                    Next
                </button>
      </div>
    </div>
    <div class="formContainer formHidden">
      <div class="rsform-block-question-two">
        <input type="radio" name="form[question-two]" value="f" id="question-two0" class="rsform-radio">
        <label for="question-two0">1 cup</label>
        <br>
        <input type="radio" name="form[question-two]" value="f" id="question-two1" class="rsform-radio">
        <label for="question-two1">Endless supply</label>
        <br>
        <input type="radio" name="form[question-two]" value="t" id="question-two2" class="rsform-radio">
        <label for="question-two2">2 tbsp</label>
        <br>
        <input type="radio" name="form[question-two]" value="f" id="question-two3" class="rsform-radio">
        <label for="question-two3">1 tsp</label>
      </div>
      <div class="rsform-block-question-two-true">
        <p>
          <strong>Correct!</strong>
        </p>
      </div>
      <div class="rsform-block-question-two-false">
        <p>
          <strong>Nice try</strong>
        </p>
      </div>
      <div class="rsform-block-question-two-feedback">
        <p>Skunks have only 2 tbsp (30ml) of spray and it takes them more than a week to re-supply. They cannot spray every day as they will simply run out. Skunks use spraying as a last resort only as if they run out, they are defenceless against predators.</p>
      </div>
      <div class="rsform-block">
        <button type="button" class="btn--next js-btn--next rsform-button success button" style="display: none;">
                    Next
                </button>
      </div>
    </div>
  </form>
</div> 

Комментарии:

1. Я бы, конечно, создал CSS — классы, например. неправильно / .правильно; и применяйте эти атрибуты к каждому ответу, так что скажите, что они отвечают на B (будет сделана ссылка на элемент, и вы установите его неправильно / правильно.

2. Пожалуйста, проверьте ответ, который я опубликовал ниже

Ответ №1:

Вам нужно добавить некоторые характерные «маркеры» для маркеров викторины, например идентификатор с номером вопроса:

   for (let i = 1; i <= questions; i  ) {
    let trackerMarker = document.createElement("div");
    trackerMarker.className = "quiz__marker";
    trackerMarker.id = "marker_"   i; // specific id for each marker
    trackerMarker.setAttribute("data-answer", "");
    tracker.appendChild(trackerMarker);
  }
 

и затем не перебирайте каждый маркер — установите цвет для маркера с тем же номером, что и вопрос. Что-то вроде:

 document.getElementById("marker_"   questionNumber).setAttribute("data-answer", "Correct");
 

Я не вижу кода для обработки нажатия на кнопку далее, но это не имеет значения для вопроса.

 function answerTracker() {
  const tracker = document.querySelector(".quiz__sidebar");
  // Each quiz contains eight questions
  const questions = 8;
  for (let i = 1; i <= questions; i  ) {
    let trackerMarker = document.createElement("div");
    trackerMarker.className = "quiz__marker";
    trackerMarker.id = "marker_"   i;
    trackerMarker.setAttribute("data-answer", "");
    tracker.appendChild(trackerMarker);
  }
}

const runQuiz = (() => {
  // Generate answer tracker
  answerTracker();

  // Set quiz score to zero
  let score = 0;

  // Get node list of .quiz__marker DIVs
  let markers = document.querySelectorAll(".quiz__marker");

  // Get node list of answer radio buttons
  let answers = document.querySelectorAll(".rsform-radio");

  answers.forEach(function(answer) {
    answer.addEventListener("click", (e) => {
      let target = e.target;
      let container = target.closest(".formContainer");
      let correct = container.querySelector("div[class$='true']");
      let wrong = container.querySelector("div[class$='false']");
      let feedback = container.querySelector("div[class$='feedback']");
      let question = container.querySelector("div[class*='rsform-block-question']");
      let next = container.querySelector(".js-btn--next.success");

      if (e.target.value == "t") {
        // If answer is correct, increment the user's score by one
        score  ;
        correct.style.display = "block";
        wrong.style.display = "none";
        feedback.style.display = "block";
        document.getElementById("marker_"   e.target.dataset.num).setAttribute("data-answer", "Correct");
      } else {
        correct.style.display = "none";
        wrong.style.display = "block";
        feedback.style.display = "block";
        document.getElementById("marker_"   e.target.dataset.num).setAttribute("data-answer", "Incorrect");
      }


      // If question has been answered, display the next button
      if (next !== null amp;amp; next !== "") {
        next.style.display = "block";
      }

    });
  });

  // If this is the final question in the quiz, assign the score variable to the final-score hidden HTML field
  // document.getElementById("final-score").value = score;
})(); 
 .quiz__sidebar .quiz__marker {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin: 6px;
  background-color: grey;
  border-radius: 50%;
}

.quiz__sidebar .quiz__marker[data-answer="Correct"] {
  background-color: green;
}

.quiz__sidebar .quiz__marker[data-answer="Incorrect"] {
  background-color: red;
}

form.quiz__form .formHidden,
form.quiz__form div[class$="true"],
form.quiz__form div[class$="false"],
form.quiz__form div[class$="feedback"],
form.quiz__form .rsform-block .rsform-button {
  display: none;
} 
 <div class="quiz">
  <div class="quiz__sidebar"></div>
  <form class="quiz__form">
    <div class="formContainer">
      <div class="rsform-block-question-one">
        <input type="radio" name="form[question-one]" data-num="1" value="f" id="question-one0" class="rsform-radio">
        <label for="question-one0">To attract a mate</label>
        <br>
        <input type="radio" name="form[question-one]" data-num="1" value="t" id="question-one1" class="rsform-radio">
        <label for="question-one1">To defend themselves against predators</label>
        <br>
        <input type="radio" name="form[question-one]" data-num="1" value="f" id="question-one2" class="rsform-radio">
        <label for="question-one2">To mark their territory</label>
        <br>
        <input type="radio" name="form[question-one]" data-num="1" value="f" id="question-one3" class="rsform-radio">
        <label for="question-one3">Because they like the smell</label>
      </div>
      <div class="rsform-block-question-one-true">
        <p>
          <strong>Correct!</strong>
        </p>
      </div>
      <div class="rsform-block-question-one-false">
        <p>
          <strong>Nice try</strong>
        </p>
      </div>
      <div class="rsform-block-question-one-feedback">
        <p>Skunks spray an extremely offensive odour to make predators go away and leave them alone. If they feel their life is in danger, they have no other defence as they cannot run fast, climb, burrow under the ground, or fight.</p>
      </div>
      <div class="rsform-block">
        <button type="button" class="btn--next js-btn--next rsform-button success button" style="display: none;">
                    Next
                </button>
      </div>
    </div>
    <div class="formContainer formHidden">
      <div class="rsform-block-question-two">
        <input type="radio" name="form[question-two]" data-num="2" value="f" id="question-two0" class="rsform-radio">
        <label for="question-two0">1 cup</label>
        <br>
        <input type="radio" name="form[question-two]" data-num="2" value="f" id="question-two1" class="rsform-radio">
        <label for="question-two1">Endless supply</label>
        <br>
        <input type="radio" name="form[question-two]" data-num="2" value="t" id="question-two2" class="rsform-radio">
        <label for="question-two2">2 tbsp</label>
        <br>
        <input type="radio" name="form[question-two]" data-num="2" value="f" id="question-two3" class="rsform-radio">
        <label for="question-two3">1 tsp</label>
      </div>
      <div class="rsform-block-question-two-true">
        <p>
          <strong>Correct!</strong>
        </p>
      </div>
      <div class="rsform-block-question-two-false">
        <p>
          <strong>Nice try</strong>
        </p>
      </div>
      <div class="rsform-block-question-two-feedback">
        <p>Skunks have only 2 tbsp (30ml) of spray and it takes them more than a week to re-supply. They cannot spray every day as they will simply run out. Skunks use spraying as a last resort only as if they run out, they are defenceless against predators.</p>
      </div>
      <div class="rsform-block">
        <button type="button" class="btn--next js-btn--next rsform-button success button" style="display: none;">
                    Next
                </button>
      </div>
    </div>
  </form>
</div> 

Комментарии:

1. Спасибо за ваш код. Я реализовал это на своем промежуточном сайте, но получаю эту ошибку JS в Chrome: Uncaught TypeError: не удается прочитать свойство ‘setAttribute’ null в строке 58 из quiz.js . Вот промежуточная ссылка . Я также обновил свой вопрос с помощью полного JS из quiz.js для ознакомления.

2. Пожалуйста, проигнорируйте мой первый комментарий. Я полностью пропустил data-num атрибут, который вы добавили к переключателям. Я добавил его, и теперь код работает.