peakersky peakersky - 2 months ago 5
CSS Question

JavaScript Quiz – animation has glitch when changing classes with jQuery (Animation Que Buildup)



function main() {
$('.btnBack').click(function () {
var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.prev().stop().fadeIn(500).addClass('active-slide');
});

$('.btnNext1').click(function() {
var checkedRadioButtons = $(':radio:checked[name=q1]');
if(!checkedRadioButtons.length) {
alert('please select an answer before you proceed!');
}
else {
var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.next().stop().fadeIn(500).addClass('active-slide'); }
});


$('.btnNext2').click(function() {
var checkedRadioButtons = $(':radio:checked[name=q2]');
if(!checkedRadioButtons.length) {
alert('please select an answer before you proceed!');
}
else {
var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.next().stop().fadeIn(500).addClass('active-slide'); }
});

$('.btnNext3').click(function() {
var checkedRadioButtons = $(':radio:checked[name=q3]');
if(!checkedRadioButtons.length) {
alert('please select an answer before you proceed!');
}
else {
var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.next().stop().fadeIn(500).addClass('active-slide');
}
});
}

$(document).ready(main);


function btnSubmit_onclick() {
var myForm = document.form1;
var totalScore = 0;
var value;
var q1Ans = document.getElementById('q1correct');
if(q1Ans.checked == true) {
totalScore ++;
}
var q2Ans = document.getElementById('q2correct');
if(q2Ans.checked == true) {
totalScore ++;
}
var q3Ans = document.getElementById('q3correct');
if(q3Ans.checked == true) {
totalScore ++;
}
myForm.showResults.value ="your total score is "
+ totalScore + "/3!";
}

.slide {
display: none;
}
.slide.active-slide {
display: block;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<form name="form1" action="" method="post">
<div class="slide active-slide">
<h3>Question 1: Answer is A!</h3>
<input type="radio" name="q1" id="q1correct" >A</input><br>
<input type="radio" name="q1" >B</input><br>
<input type="radio" name="q1" >C</input><br>
<input type="radio" name="q1" >D</input>
<input type="button" class="btnBack" value="Back">
<input type="button" class="btnNext1" value="Next" >
</div>
<div class="slide">
<h3>Question 2: Answer is B! </h3>
<input type="radio" name="q2" >A</input><br>
<input type="radio" name="q2" id="q2correct">B</input><br>
<input type="radio" name="q2" >C</input><br>
<input type="radio" name="q2" >D</input>
<input type="button" class="btnBack" value="Back">
<input type="button" class="btnNext2" value="Next">
</div>
<div class="slide">
<h3>Question 3: Answer is B! </h3>
<input type="radio" name="q3">A</input><br>
<input type="radio" name="q3" id="q3correct">B</input><br>
<input type="radio" name="q3">C</input><br>
<input type="radio" name="q3">D</input>
<input type="button" class="btnBack" value="Back">
<input type="button" class="btnNext3" value="Submit"
onclick="btnSubmit_onclick()">
</div>
<div class="slide">
<h3>Your Total Score</h3>
<textarea name="showResults" rows="8" cols="40" readonly="readonly"></textarea>
<input type="button" class="btnBack" value="Back">
</div>
</form>
</body>





I'm creating a quiz with JavaScript where I'm trying to have 1 question appear at a time.

I’ve successfully hid and shown questions through changing classes with jQuery and CSS. However, the animations glitch when showing the next slide. The next slide is shown under the previous slide and it takes time for the previous slide to disappear.

Doing some research I've seen I've tried using the stop() method about animation que buildup, but that too doesn't seem to fix the problem.

My jQuery is the following

$('.btnBack').click(function () {
var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.prev().stop().fadeIn(500).addClass('active-slide');
});

$('.btnNext1').click(function() {

var currentSlide = $('.active-slide').stop().fadeOut(500).removeClass('active-slide');
currentSlide.next().stop().fadeIn(500).addClass('active-slide'); }
});


CSS

.slide {
display: none;
}
.slide.active-slide {
display: block;
}


HTML

<div class="slide active-slide">
<h3>Question 1: Answer is A!</h3>
<input type="radio" name="q1" id="q1correct" >A</input><br>
<input type="radio" name="q1" >B</input><br>
<input type="radio" name="q1" >C</input><br>
<input type="radio" name="q1" >D</input>
<input type="button" class="btnBack" value="Back">
<input type="button" class="btnNext1" value="Next" >
</div>
<div class="slide">
<h3>Question 2: Answer is B! </h3>
<input type="radio" name="q2" >A</input><br>
<input type="radio" name="q2" id="q2correct">B</input><br>
<input type="radio" name="q2" >C</input><br>
<input type="radio" name="q2" >D</input>
<input type="button" class="btnBack" value="Back">
<input type="button" class="btnNext2" value="Next">
</div>


The jQuery seems right and no error message appears on the console.

Your help is greatly appreciated.

Answer

If you want the animation to fade out the previous question, then fade in the next, you need to wait for the fade to complete before continuing by using the fadeOut callback:

$('.btnBack').click(function() {
  var currentSlide = $('.active-slide').stop().fadeOut(500, function() {
    $(this).removeClass('active-slide');
    currentSlide.prev().stop().fadeIn(500).addClass('active-slide');
  });
});

$('.btnNext1').click(function() {

  var currentSlide = $('.active-slide').stop().fadeOut(500, function() {
    $(this).removeClass('active-slide');
    currentSlide.next().stop().fadeIn(500).addClass('active-slide');
  });
});

Note that I've moved the code that follows the fadeOut into the fadeOut callback.

Also note that the above relies on the fact you have only a single question matching .active-slide, because fadeOut will call its callback when each animated element finishes. In our case, that's just one so it's fine, but it's worth pointing out.

Live Example:

$('.btnBack').click(function() {
  var currentSlide = $('.active-slide').stop().fadeOut(500, function() {
    $(this).removeClass('active-slide');
    currentSlide.prev().stop().fadeIn(500).addClass('active-slide');
  });
});

$('.btnNext1').click(function() {

  var currentSlide = $('.active-slide').stop().fadeOut(500, function() {
    $(this).removeClass('active-slide');
    currentSlide.next().stop().fadeIn(500).addClass('active-slide');
  });
});
.slide {
  display: none;
}
.slide.active-slide {
  display: block;
}
<div class="slide active-slide">
  <h3>Question 1: Answer is A!</h3>
  <input type="radio" name="q1" id="q1correct">A
  <br>
  <input type="radio" name="q1">B
  <br>
  <input type="radio" name="q1">C
  <br>
  <input type="radio" name="q1">D
  <input type="button" class="btnBack" value="Back">
  <input type="button" class="btnNext1" value="Next">
</div>
<div class="slide">
  <h3>Question 2: Answer is B! </h3>
  <input type="radio" name="q2">A
  <br>
  <input type="radio" name="q2" id="q2correct">B
  <br>
  <input type="radio" name="q2">C
  <br>
  <input type="radio" name="q2">D
  <input type="button" class="btnBack" value="Back">
  <input type="button" class="btnNext2" value="Next">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>