Reputation: 4264
I have a simple form which works as intended. It is a multi-step form that only shows one question at a time. When the user clicks on an input field (all radio buttons) they get taken to the next question, which is different depending on what they clicked and then finally they get a submit button after the last question.
I currently have several .click
functions, and this works well. However, I am sure it is not the most efficient way to do this, in terms of both writing and performance. Is there a more efficient way to use multiple .click
functions?
$('.male').click(function() {
$('#male').show();
$('#gender').hide();
});
$('.female').click(function() {
$('#female').show();
$('#gender').hide();
});
Upvotes: 1
Views: 176
Reputation: 18022
due to event bubbling you could do this:
$('body').on('click',function(e){
switch ($(e.target).attr('class')){
case "male":
$('#male').show();
$('#gender').hide();
break;
case "female":
$('#female').show();
$('#gender').hide();
break;
default:
alert("default function!");
break;
}
});
here's a demo: http://jsfiddle.net/748sE/2/
of course the default function will return on anything you click on that page that isn't already caught...
BTW, you can replace $(e.target).attr('class')
with e.target.className
to optimize it a bit, as David Thomas did in his answer...
Upvotes: 1
Reputation: 253328
Assuming a logical structure to your HTML, such as:
<form action="#" method="post">
<fieldset>
<legend>Question 1: gender</legend>
<label for="m">Male</label>
<input type="radio" name="gender" id="m" />
<label for="f">Female</label>
<input type="radio" name="gender" id="f" />
</fieldset>
<fieldset>
<legend>Question title</legend>
<!-- answer options -->
</fieldset>
<!-- other questions... -->
</form>
Then the simplest option I can think of is the following:
$('form').on('click','input',
function(){
var fieldset = $(this).closest('fieldset');
fieldset.fadeOut(500,
function(){
fieldset.next('fieldset').fadeIn(500);
});
});
To allow for revisiting previous questions, I'd suggest an adaptation along the following lines:
<form action="#" method="post">
<fieldset>
<legend>Question 1: gender</legend>
<label for="m">Male</label>
<input type="radio" name="gender" id="m" />
<label for="f">Female</label>
<input type="radio" name="gender" id="f" />
<div class="controls">
<a href="#" class="prev">Previous</a>
<a href="#" class="next">Next</a>
</div>
</fieldset>
<!-- other questions... -->
</form>
And coupled with the jQuery:
$('fieldset').not($('fieldset:eq(0)')).hide();
$('.controls a.prev:first, .controls a.next:last').addClass('disabled');
$('form').on('click', 'input, a', function(e) {
var target = e.target,
targetType = target.tagName.toLowerCase(),
targetClass = target.className,
fieldset = $(this).closest('fieldset'),
prev = fieldset.prev().length,
next = fieldset.next().length;
if (targetType == 'input' && next > 0) {
fieldset.fadeOut(500, function() {
fieldset.next('fieldset').fadeIn(500);
});
}
else if (targetType == 'a') {
if (targetClass == 'prev' && prev > 0) {
fieldset.fadeOut(500, function() {
fieldset.prev('fieldset').fadeIn(500);
});
}
else if (targetClass == 'next' && next > 0) {
fieldset.fadeOut(500, function() {
fieldset.next('fieldset').fadeIn(500);
});
}
}
});
References:
jQuery stuff:
Native JavaScript stuff:
Upvotes: 3
Reputation: 2915
You could give all of the questions the class of 'question' and then each answer could have an id corresponding to a class (or other) property of the upcoming branch you wanted to display.
Therefore each response would hold the name for what to display next for you and you would be able to only have one click handler.
I.e.:
$("input").click(function() {
$(".question").hide();
var itemToShow = $(this).attr("id");
//alert(itemToShow);
if ($("."+itemToShow).length > 0) {
$("."+itemToShow).show("normal");
} else {
$(".finale").show("normal");
}
});
You'll probably need to play around with it a little bit until the control works as you'd like. Here's a fiddle to work off of.
Update: Here's the latest fiddle demonstration.
Upvotes: 0
Reputation: 337580
Because both of your #male
and #female
elements require code to run when they are clicked on they both need their own click handler. However, you could simplify this code by including them both in the same selector and calling a single function to handle them both. Try this:
$(".male, .female").click(showDivs);
function showDivs() {
if ($(this).hasClass("male")) {
$("#male").show();
}
else {
$("#female").show();
}
$("#gender").hide();
}
Upvotes: 0