Я нахожусь в процессе создания игры типа викторины с использованием JQuery. Моя игра работает так, как я хочу, но только для первого вопроса.

var progress = 0;
var score = 0;

var running = true;

var questions = [
  {question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
  {question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];

var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');

var showQuestion = q => {
  if (progress < questions.length) {
    $question.html(q.question);
    $answers.html(' ');
    q.answers.forEach(function(ans) {
      $answers.append("<div class='answer'>" + ans + "</div>");
    })
  } else {
    $results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
    $quiz.hide();
    $results.show();
  }
};

showQuestion(questions[progress]);

$(document).ready(function(){
  $next.hide();
  $results.hide();

  $('.answer').on('click', function(){
    if($(this).html() === questions[progress].correct && running) {
      progress++;
      running = false;
      score++;
      $(this).css('color', 'green');
      $(this).css('border', '3px solid green');
      $(this).css('font-weight', 'bold');
      $next.show();
    } else if ($(this).html() !== questions[progress] && running) {
      $(this).css('color', 'red');
      $(this).css('border', '3px solid red');
      $(this).css('font-weight', 'bold');
      progress++;
      running = false;
      $next.show();
    }
  })

  $next.on('click', function() {
    running = true;
    showQuestion(questions[progress]);
  })
})
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background-color: #c7ecee;
  font-family: 'Karla', sans-serif;
}

main {
  min-height: 500px;
  width: 100%;
  display: flex;
  align-items: flex-end;
}

main .quiz {
  width: 40%;
  margin: 0 auto;
  text-align: center;
}

main .quiz #quiz-question {
  font-size: 2rem;
  width: 100%;
  border: 2px solid #4d4d4d;
  color: #fff;
  background-color: #4d4d4d;
  padding: 1rem;
}

main .quiz #answers {
  font-size: 1.5rem;
  border: 1px solid #4d4d4d;
}

main .quiz #answers .answer {
  width: 100%;
  padding: 1rem;
  background-color: #fff;
  border: 1px solid #4d4d4d;
  cursor: pointer;
}

main .quiz #answers .answer:hover {

}

div#ui {
  text-align: center;
  width: 100%;
  padding: .75rem;
}

div#ui button {
  font-size: 1.75rem;
  padding: .75rem;
  background-color: #4d4d4d;
  border: 1px solid #4d4d4d;
  color: #fff;
  cursor: pointer;
}
  <main>
    <div class='quiz'>
      <div id='quiz-question'>
      </div>
      <div id='answers'>
      </div>
    </div>
    <div id='results'>
    </div>
  </main>

  <div id='ui'>
    <button id='next'>Next</button>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Как правило, отображается вопрос и ответы на него, при щелчке по ответу игра останавливается, поэтому нельзя щелкнуть другие ответы (или нельзя щелкнуть ответ более одного раза, чтобы увеличить счет). Когда на вопрос будет дан ответ, внизу появится кнопка для перехода к следующему вопросу. Если вопросов больше нет, отображается экран результатов.

Это работает именно так, как я хочу - для одного вопроса. Когда я добавляю какие-либо дополнительные вопросы, он отображает вопрос именно так, как должен, но эффекты по щелчку больше не применяются. Я предполагаю, что это связано с элементами, которые не существуют при вызове функции $(document).ready(). Может ли кто-нибудь пролить свет на то, как я могу решить эту проблему?

Отредактировано, чтобы включить фрагмент кода. Раскомментируйте второй квест

0
D. Winning 25 Сен 2018 в 23:40

2 ответа

Лучший ответ

В строке 37 измените:

$('.answer').on('click', function(){

Кому

 $('body').on('click', '.answer', function(){

Дело в том, что когда вы пишете:

$(document).ready(function(){
    $next.hide();
    $results.hide();

    $('.answer').on('click', function(){

Вы нацеливаете все элементы (на текущий момент), которые имеют класс .answer. Поскольку это только первый вопрос (в начале), он не будет работать с вопросами после первого.

Если вы вместо этого напишите:

$(document).ready(function(){
    $next.hide();
    $results.hide();

    $('body').on('click', '.answer', function(){

Вы указываете jQuery добавить событие click к любым текущим и новым элементам, которые будут добавлены с классом .answer (внутри элемента body). Лучше оставить это конкретным, например, с идентификатором для викторины.

Посмотрите весь пример:

var progress = 0;
var score = 0;

var running = true;

var questions = [
  {question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
  {question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];

var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');

var showQuestion = q => {
  if (progress < questions.length) {
    $question.html(q.question);
    $answers.html(' ');
    q.answers.forEach(function(ans) {
      $answers.append("<div class='answer'>" + ans + "</div>");
    })
  } else {
    $results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
    $quiz.hide();
    $results.show();
  }
};

showQuestion(questions[progress]);

$(document).ready(function(){
  $next.hide();
  $results.hide();

  $('body').on('click', '.answer', function(){
    if($(this).html() === questions[progress].correct && running) {
      progress++;
      running = false;
      score++;
      $(this).css('color', 'green');
      $(this).css('border', '3px solid green');
      $(this).css('font-weight', 'bold');
      $next.show();
    } else if ($(this).html() !== questions[progress] && running) {
      $(this).css('color', 'red');
      $(this).css('border', '3px solid red');
      $(this).css('font-weight', 'bold');
      progress++;
      running = false;
      $next.show();
    }
  })

  $next.on('click', function() {
    running = true;
    showQuestion(questions[progress]);
  })
})
<body>
  <main>
    <div class='quiz'>
      <div id='quiz-question'>
      </div>
      <div id='answers'>
      </div>
    </div>
    <div id='results'>
    </div>
  </main>

  <div id='ui'>
    <button id='next'>Next</button>
  </div>

  <script src='https://code.jquery.com/jquery-3.2.1.min.js' integrity='sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=' crossorigin='anonymous'></script>
  <script src='includes/js/main.js'></script>
</body>
1
Tibbelit 25 Сен 2018 в 21:00

Вот минимальное изменение, чтобы ваш код заработал:

var progress = 0;
var score = 0;

var running = true;

var questions = [
  {question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
  {question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];

var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');

var showQuestion = q => {
  if (progress < questions.length) {
    $question.html(q.question);
    $answers.html(' ');
    q.answers.forEach(function(ans) {
      $answers.append("<div class='answer'>" + ans + "</div>");
    })

    $('.answer').on('click', function(){
      if($(this).html() === questions[progress].correct && running) {
        progress++;
        running = false;
        score++;
        $(this).css('color', 'green');
        $(this).css('border', '3px solid green');
        $(this).css('font-weight', 'bold');
        $next.show();
      } else if ($(this).html() !== questions[progress] && running) {
        $(this).css('color', 'red');
        $(this).css('border', '3px solid red');
        $(this).css('font-weight', 'bold');
        progress++;
        running = false;
        $next.show();
      }
    })
  } else {
    $results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
    $quiz.hide();
    $results.show();
  }
};

showQuestion(questions[progress]);

$(document).ready(function(){
  $next.hide();
  $results.hide();

  $next.on('click', function() {
    running = true;
    showQuestion(questions[progress]);
  })
})
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background-color: #c7ecee;
  font-family: 'Karla', sans-serif;
}

main {
  min-height: 500px;
  width: 100%;
  display: flex;
  align-items: flex-end;
}

main .quiz {
  width: 40%;
  margin: 0 auto;
  text-align: center;
}

main .quiz #quiz-question {
  font-size: 2rem;
  width: 100%;
  border: 2px solid #4d4d4d;
  color: #fff;
  background-color: #4d4d4d;
  padding: 1rem;
}

main .quiz #answers {
  font-size: 1.5rem;
  border: 1px solid #4d4d4d;
}

main .quiz #answers .answer {
  width: 100%;
  padding: 1rem;
  background-color: #fff;
  border: 1px solid #4d4d4d;
  cursor: pointer;
}

main .quiz #answers .answer:hover {

}

div#ui {
  text-align: center;
  width: 100%;
  padding: .75rem;
}

div#ui button {
  font-size: 1.75rem;
  padding: .75rem;
  background-color: #4d4d4d;
  border: 1px solid #4d4d4d;
  color: #fff;
  cursor: pointer;
}
<main>
    <div class='quiz'>
      <div id='quiz-question'>
      </div>
      <div id='answers'>
      </div>
    </div>
    <div id='results'>
    </div>
  </main>

  <div id='ui'>
    <button id='next'>Next</button>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

По сути, вы прикрепляли прослушиватель событий к элементам .answer один раз, а затем заменяли эти элементы, что означает, что когда пользователь щелкает новые, ничего не происходит. Здесь мы добавляем слушателей каждый раз, когда создается вопрос.

Имейте в виду, есть способы рефакторинга этого кода. Я бы рассмотрел делегирование событий, если вы не хотите создавать слушателей для каждого элемента .answer.

1
Damon 25 Сен 2018 в 20:59