Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have created a "Wizard" using JavaScript and based on people's answers you get taken to certain results divs. It works the way I want, but this code is VERY repetitive. Is there a way to clean up this JavaScript code?

Also, is there a way to add a "Back to Start" button on the results divs that take you back to the beginning and resets all of the radio buttons?

Thank you!

$(".hidden").hide();

$(function() {

$("#start_button").click(function(){
            $("#wizard_start").hide();
            $("#Q1").show();
});

$("#reset").click(function(){
        $("#wizard_start").show();
        $(".hidden").hide();
        $(":input").not(":button, :submit, :reset, :hidden").each( function() {
        this.value = this.defaultValue;     
});

});

$("#q1_button").click(function(){
        if ($("input[value='q1_1']:checked").val()){
            $("#Q2").show();
            $("#Q1").hide();
        }
        else if ($("input[value='q1_2']:checked").val()) {
            $("#results1").show();
            $("#Q1").hide();
        }
        else if ($("input[value='q1_3']:checked").val()) {
            $("#Q3").show();
            $("#Q1").hide();
        }
});

$("#q2_button").click(function(){
        if ($("input[value='q2_1']:checked").val()){
            $("#results2").show();
            $("#Q2").hide();
        }
        else {
            $("#results3").show();
            $("#Q2").hide();
        }


});

    $("#q3_button").click(function(){
        if ($("input[value='q3_1']:checked").val()){
            $("#Q4").show();
            $("#Q3").hide();
        }
        else {
            $("#results1").show();
            $("#Q3").hide();
        }

});

$("#q4_button").click(function(){
        if ($("input[value='q4_1']:checked").val()){
            $("#Q5").show();
            $("#Q4").hide();
        }
        else {
            $("#Q6").show();
            $("#Q4").hide();
        }

});

$("#q5_button").click(function(){
        if ($("input[value='q5_1']:checked").val()){
            $("#results4").show();
            $("#Q5").hide();
        }
        else {
            $("#Q7").show();
            $("#Q5").hide();
        }

});

$("#q6_button").click(function(){
        if ($("input[value='q6_1']:checked").val()){
            $("#Q8").show();
            $("#Q6").hide();
        }
        else {
            $("#Q9").show();
            $("#Q6").hide();
        }

});

$("#q7_button").click(function(){
        if ($("input[value='q7_1']:checked").val()){
            $("#results4").show();
            $("#Q7").hide();
        }
        else {
            $("#results5").show();
            $("#Q7").hide();
        }

});

$("#q8_button").click(function(){
        if ($("input[value='q8_1']:checked").val()){
            $("#results6").show();
            $("#Q8").hide();
        }
        else {
            $("#results7").show();
            $("#Q8").hide();
        }

});

$("#q9_button").click(function(){
        if ($("input[value='q9_1']:checked").val()){
            $("#results8").show();
            $("#Q9").hide();
        }
        else if ($("input[value='q9_2']:checked").val()) {
            $("#Q10").show();
            $("#Q9").hide();
        }

        else if ($("input[value='q9_3']:checked").val()) {
            $("#results3").show();
            $("#Q9").hide();
        }

});

$("#q10_button").click(function(){
        if ($("input[value='q10_1']:checked").val()){
            $("#results9").show();
            $("#Q10").hide();
        }
        else {
            $("#results3").show();
            $("#Q10").hide();
        }

});

$("#q2_backbutton").click(function(){
    $("#Q1").show();
    $("#Q2").hide();
});
$("#q3_backbutton").click(function(){
    $("#Q1").show();
    $("#Q3").hide();
});
$("#q4_backbutton").click(function(){
    $("#Q3").show();
    $("#Q4").hide();
});
$("#q5_backbutton").click(function(){
    $("#Q4").show();
    $("#Q5").hide();
});
$("#q6_backbutton").click(function(){
    $("#Q4").show();
    $("#Q6").hide();
});
$("#q7_backbutton").click(function(){
    $("#Q5").show();
    $("#Q7").hide();
});
$("#q8_backbutton").click(function(){
    $("#Q6").show();
    $("#Q8").hide();
});
$("#q9_backbutton").click(function(){
    $("#Q6").show();
    $("#Q9").hide();
});
$("#q10_backbutton").click(function(){
    $("#Q9").show();
    $("#Q10").hide();
});

});

Demo can be seen here: http://jsfiddle.net/dswinson/PXp7c/56/

share|improve this question

2 Answers

Something like this is probably a good way to start consolidating. Do the buttons share a class by chance?

$('.myButtonClass').click(function () {
  // Extract an id:
  var myid = this.id.substr(1, 3);

  switch (myid) {
    case 'reset':
      $('wizard_start').show();
      $('questionClass').hide();

    default:
      if ($("input[value='q' + myid + '_1']:checked").val()){
        $("#Q" + (myid + 1)).show();
      } else {
        $("#Q" + (myid + 2)).show();
      }

      $("#Q" + myid).hide();
  }

});

The amount of code duplication this will eliminate will depend on how similar your function bodies actually are. You'd add case statements to the switch to accommodate special cases.

Alternatively, you could add an object that contained values referring to what you check against, what you show, and what you hide. That would look something like this:

var wizardOrder = {
  'q1': {
    'check': "input[value='q1_1']:checked",
    'show': 'Q2',
    'hide': 'Q3'
  }
};

Then our click function becomes something like this:

$('myButtonClass').click(function () {
  var myid = this.id.substr(1, 3);

  if ($(wizardOrder[myid]['check']).val()) {
    $(wizardOrder[myid]['show'].show();
    $(wizardOrder[myid]['hide'].show();  
  }
});

Hopefully one of those two fit with your idea of reducing duplication and/or simplifying.

-- Edit --

I realized I didn't address your "Jump to start" functionality. I added that to the first example. It could be added to the second as well.

share|improve this answer
Thank you! I will play around with it and let you know how it goes. – Dawn Jun 23 '11 at 17:57

I'll come back and edit this with more suggestions but for now I have two minor performance ones for your to pick up:

  • Cache your jQuery DOM elements! Don't keep using $('#Q2') etc. Store it like so at the beginning of your closure: var $q2 = $('#Q2');.
  • Also dont use :checked").val(). This just seems backwards. Use $("input[value=whatever]").is(":checked");
  • Additionally, to help reduce the quantity of code you're duplicated, consider writing just one function to handle showing and hiding of questions.

Example:

var questions = [$('#Q1'), $('#Q2') ... etc];
function showQuestion(questionNumber) {
    questionNumber -= 1; // so you can pass in '1' and have it zero indexed.
    for (var i = 0; i < questions.length; i++) {
        if (i === questionNumber) questions[i].show();
        else questions[i].hide();
    }
}
  • You are on the right track here asking for ways to reduce code duplication. You are taking a very procedural and 'manual' approach to writing your code though, from the outset try and imagine common repetitive tasks you'll be attempting in your program and abstract them out to functions / methods. It's worth also trying to take a more OO approach to your coding.
  • This is a bit of a self plug, but I recently wrote a framework that might help with this.... http://github.com/skippychalmers/xa.js/ . You could re-write this entire quiz application using this and maintain it quite easily. Any problems at all with it just let me know and I'll fix / support. Alternatively, it might be a good idea to use something a bit more mature like sproutCore, knockout, spine or backbone. Check 'em all out and research your options. It's a learning curve to make the jump from this procedural style of coding to a more sustainable OO approach, but worth it in the long run!
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.