Reputation: 1437
I have a JQuery file to display only one question of a quiz. When you click the submit button it should advance to the next question, which it does, but only for a split second when the button is pressed, after which it switches back to the first question.
My code is as follows:
$(document).ready(function() {
"use strict";
// Question 01
$('button#FlexibilityNext01').click(function() {
$('#FlexibilityQ01').css({'display':'none'});
$('#FlexibilityQ02').css({'display':'block'});
});
// Question 02
$('button#FlexibilityNext02').click(function() {
$('#FlexibilityQ02').css({'display':'none'});
$('#FlexibilityQ03').css({'display':'block'});
});
$('button#FlexibilityPrev02').click(function() {
$('#FlexibilityQ01').css({'display':'block'});
$('#FlexibilityQ02').css({'display':'none'});
});
// Question 03
$('button#FlexibilityNext03').click(function() {
$('#FlexibilityQ03').css({'display':'none'});
$('#FlexibilityQ04').css({'display':'block'});
});
$('button#FlexibilityPrev03').click(function() {
$('#FlexibilityQ02').css({'display':'block'});
$('#FlexibilityQ03').css({'display':'none'});
});
// Question 04
$('button#FlexibilityNext04').click(function() {
$('#FlexibilityQ04').css({'display':'none'});
$('#FlexibilityQ05').css({'display':'block'});
});
$('button#FlexibilityPrev04').click(function() {
$('#FlexibilityQ03').css({'display':'block'});
$('#FlexibilityQ04').css({'display':'none'});
});
// Question 05
$('button#FlexibilityNext05').click(function() {
$('#FlexibilityQ05').css({'display':'none'});
$('#FlexibilityQ06').css({'display':'block'});
});
$('button#FlexibilityPrev05').click(function() {
$('#FlexibilityQ04').css({'display':'block'});
$('#FlexibilityQ05').css({'display':'none'});
});
// Question 06
$('button#FlexibilityNext06').click(function() {
$('#FlexibilityQ06').css({'display':'none'});
$('#FlexibilityQ07').css({'display':'block'});
});
$('button#FlexibilityPrev07').click(function() {
$('#FlexibilityQ06').css({'display':'block'});
$('#FlexibilityQ07').css({'display':'none'});
});
// Question 07
$('button#FlexibilityNext07').click(function() {
$('#FlexibilityQ07').css({'display':'none'});
$('#FlexibilityQ08').css({'display':'block'});
});
$('button#FlexibilityNext03').click(function() {
$('#FlexibilityQ07').css({'display':'block'});
$('#FlexibilityQ08').css({'display':'none'});
});
// Question 08
$('button#FlexibilityNext08').click(function() {
$('#FlexibilityQ08').css({'display':'none'});
$('#FlexibilityQ09').css({'display':'block'});
});
$('button#FlexibilityNext03').click(function() {
$('#FlexibilityQ08').css({'display':'block'});
$('#FlexibilityQ09').css({'display':'none'});
});
// Question 09
$('button#FlexibilityNext09').click(function() {
$('#FlexibilityQ09').css({'display':'none'});
$('#FlexibilityQ10').css({'display':'block'});
});
$('button#FlexibilityNext03').click(function() {
$('#FlexibilityQ09').css({'display':'block'});
$('#FlexibilityQ10').css({'display':'none'});
});
// Question 10
$('button#FlexibilityFinishQuiz').click(function() {
$('#FlexibilityQ10').css({'display':'none'});
$('#RetakeQuiz').css({'display':'block'});
});
$('button#FlexibilityNext03').click(function() {
$('#FlexibilityQ10').css({'display':'block'});
$('#RetakeQuiz').css({'display':'none'});
});
// RetakeQuiz
$('#FlexibilityRetakeQuiz').click(function() {
$('#FlexibilityRetakeQuiz').css({'display':'none'});
$('#FlexibilityQ01').css({'display':'block'});
});
});
<div class="Question" id="FlexibilityQ01">
<form id="FlexibilityFormQ01">
<!-- form question here -->
<button type="submit" id="FlexibilityNext01">Next Question</button>
</form>
</div> <!-- class="Question" id="Q1" -->
<div class="Hidden Question" id="FlexibilityQ02">
<form id="FlexibilityFormQ02">
<button type="button" id="FlexibilityPrev02">Previous Question</button>
<button type="submit" id="FlexibilityNext02">Next Question</button>
</form>
</div> <!-- class="Question" id="Q2" -->
<div class="Hidden Question" id="FlexibilityQ03">
<form id="FlexibilityFormQ03">
<button type="button" id="FlexibilityPrev03">Previous Question</button>
<button type="submit" id="FlexibilityNext03">Next Question</button>
</form>
</div> <!-- class="Question" id="Q3" -->
<!-- Questions 4-9 are the same exact format but with changed numbers -->
<div class="Hidden Question" id="FlexibilityQ10">
<form id="FlexibilityFormQ10">
<button type="button" id="FlexibilityPrev10">Previous Question</button>
<button type="submit" id="FlexibilityFinishQuiz">Finish Quiz</button>
</form>
</div> <!-- class="Question" id="Q10" -->
I also tried using:
$('#id').hide();
$('#id').show();
and
$("#id").css("display", "none");
$("#id").css("display", "block");
but all seem to be having the same problem.
Upvotes: 0
Views: 130
Reputation: 4400
Since your comment mentions also needing to send this view to the server I will include an answer that addresses that. You should probably have included that in your initial question.
That being said, brush up on your knowledge about how event handlers work in JavaScript and jQuery. Certain elements give off certain events other than click, so you need to be aware of what the browser default is for certain types of elements. In this case, the default action of a "submit" button is to POST the form back to the page. Easy to disable that.
I took the liberty of DRYing up your code.. A little more complex, but less code overall - Easier to maintain :)
$(document).ready(function() {
var currentQuestion = 1
// ignore form submits
$('.Question form').on('submit', function(e) {
e.preventDefault()
})
// Loop through all the questions
$('.Question').each(function(i, qEl) {
var question = $(qEl)
// When the 'submit' button is clicked, fire our next function
// You could make these more readable by adding classes to the buttons.
question.find('button[type="submit"]').on('click', next);
// Same for previous
question.find('button[type="button"]').on('click', prev);
function next() {
// Add 1 to the question counter. Notice how the current question
// variable is *outside* of this `closure`. Look that term up.
currentQuestion++
// If the counter goes outside how many questions we have
// reset it to be 10
if (currentQuestion > 10) {
currentQuestion = 10
}
updateQuestions()
// Here we could send off the form state, and wait till the
// server responds before we show the next question.
// $.ajax({
// type: 'post',
// url: location.pathname,
// data: question.find('form').serialize()
// }).then(updateQuestions)
}
// Same as next except the opposite.
function prev() {
currentQuestion--
if (currentQuestion < 1) {
currentQuestion = 1
}
updateQuestions()
}
})
// Here we just loop through all the questions, and based on the
// currentQuestion variable, we only show the active one.
function updateQuestions() {
$('.Question').each(function(i, qEl) {
var question = $(qEl)
var id = question.attr('id')
// Here we strip off the string, and parse '01' into a number.
var num = parseInt(id.replace('FlexibilityQ', ''), 10)
if (num === currentQuestion) {
question.show()
} else {
question.hide()
}
// If you need to do special logic for the finish
// you can just say
// if (num === 10) { doSomethingSpecial() }
})
}
})
Upvotes: 0
Reputation: 11450
If all of your questions are on the page and you're just showing/hiding them, you'd be better suited using <a href="#" class="next">
type entries instead of forms/buttons for this navigation. Actually just two links total - one for next, one for previous, then store where you currently are in the questionnaire in a variable. Something like this.
Anyways, the quick fix here is to simply prevent the forms from submitting using $.preventDefault()
.
$('_selector_').click(function(e) {
e.preventDefault();
$('_selector_').css({'display':'none'});
$('_selector_').css({'display':'block'});
});
Upvotes: 0
Reputation: 1511
By using submit
buttons, you're telling the page to submit the form when the button is clicked. Since no action is specified for the form, it's going to default to the current page. So, each time one of the submit buttons is clicked, the click event is triggered, and your bound handler is executed, which makes the next question visible. However it then submits the form to itself, which reloads the page. The reloaded page has no clue about the state it was in before the form was submitted, so it shows the initial state (the first question) again.
Based on the code you've posted, there's no reason for the buttons to have a type of submit
. So unless there's a reason not included in this code, you can just change them to type="button"
and it will fix the problem. That would also allow you to get rid of all the <form>
elements.
Upvotes: 3