Question

I'm following javascriptissexy and learning how to make a dynamic quiz. I found someone's own version of the quiz and looked at the source code to learn how they approached the problem; after I took a crack at it. I understand the html/css and some of the javascript code but need some questions answered. I was hoping someone can answer some questions I have about their source code. My questions are at the bottom.

Here's the link to the full app http://codepen.io/gcarino/pen/LDgtn/

And here's the full javascript code:

(function() {
  var questions = [{
    question: "What is 2*5?",
    choices: [2, 5, 10, 15, 20],
    correctAnswer: 2
  }, {
    question: "What is 3*6?",
    choices: [3, 6, 9, 12, 18],
    correctAnswer: 4
  }, {
    question: "What is 8*9?",
    choices: [72, 99, 108, 134, 156],
    correctAnswer: 0
  }, {
    question: "What is 1*7?",
    choices: [4, 5, 6, 7, 8],
    correctAnswer: 3
  }, {
    question: "What is 8*8?",
    choices: [20, 30, 40, 50, 64],
    correctAnswer: 4
  }];

  var questionCounter = 0; //Tracks question number
  var selections = []; //Array containing user choices
  var quiz = $('#quiz'); //Quiz div object

  // Display initial question
  displayNext();

  // Click handler for the 'next' button
  $('#next').on('click', function (e) {
    e.preventDefault();

    // Suspend click listener during fade animation
    if(quiz.is(':animated')) {        
      return false;
    }
    choose();

    // If no user selection, progress is stopped
    if (isNaN(selections[questionCounter])) {
      alert('Please make a selection!');
    } else {
      questionCounter++;
      displayNext();
    }
  });

  // Click handler for the 'prev' button
  $('#prev').on('click', function (e) {
    e.preventDefault();

    if(quiz.is(':animated')) {
      return false;
    }
    choose();
    questionCounter--;
    displayNext();
  });

  // Click handler for the 'Start Over' button
  $('#start').on('click', function (e) {
    e.preventDefault();

    if(quiz.is(':animated')) {
      return false;
    }
    questionCounter = 0;
    selections = [];
    displayNext();
    $('#start').hide();
  });

  // Animates buttons on hover
  $('.button').on('mouseenter', function () {
    $(this).addClass('active');
  });
  $('.button').on('mouseleave', function () {
    $(this).removeClass('active');
  });

  // Creates and returns the div that contains the questions and 
  // the answer selections
  function createQuestionElement(index) {
    var qElement = $('<div>', {
      id: 'question'
    });

    var header = $('<h2>Question ' + (index + 1) + ':</h2>');
    qElement.append(header);

    var question = $('<p>').append(questions[index].question);
    qElement.append(question);

    var radioButtons = createRadios(index);
    qElement.append(radioButtons);

    return qElement;
  }

  // Creates a list of the answer choices as radio inputs
  function createRadios(index) {
    var radioList = $('<ul>');
    var item;
    var input = '';
    for (var i = 0; i < questions[index].choices.length; i++) {
      item = $('<li>');
      input = '<input type="radio" name="answer" value=' + i + ' />';
      input += questions[index].choices[i];
      item.append(input);
      radioList.append(item);
    }
    return radioList;
  }

  // Reads the user selection and pushes the value to an array
  function choose() {
    selections[questionCounter] = +$('input[name="answer"]:checked').val();
  }

  // Displays next requested element
  function displayNext() {
    quiz.fadeOut(function() {
      $('#question').remove();

      if(questionCounter < questions.length){
        var nextQuestion = createQuestionElement(questionCounter);
        quiz.append(nextQuestion).fadeIn();
        if (!(isNaN(selections[questionCounter]))) {
          $('input[value='+selections[questionCounter]+']').prop('checked', true);
        }

        // Controls display of 'prev' button
        if(questionCounter === 1){
          $('#prev').show();
        } else if(questionCounter === 0){

          $('#prev').hide();
          $('#next').show();
        }
      }else {
        var scoreElem = displayScore();
        quiz.append(scoreElem).fadeIn();
        $('#next').hide();
        $('#prev').hide();
        $('#start').show();
      }
    });
  }

  // Computes score and returns a paragraph element to be displayed
  function displayScore() {
    var score = $('<p>',{id: 'question'});

    var numCorrect = 0;
    for (var i = 0; i < selections.length; i++) {
      if (selections[i] === questions[i].correctAnswer) {
        numCorrect++;
      }
    }

    score.append('You got ' + numCorrect + ' questions out of ' +
                 questions.length + ' right!!!');
    return score;
  }
})();

My questions:

1) in regard to this block of code

 // Click handler for the 'next' button
  $('#next').on('click', function (e) {
    e.preventDefault();

    // Suspend click listener during fade animation
    if(quiz.is(':animated')) {        
      return false;
    }

1.a What is e or (e) in the function parameter and what does e.preventDefault() do?

1.b How does return false suspend the click listener during the fade animation?

2) In regards to this block of code:

function createQuestionElement(index) {
    var qElement = $('<div>', {
      id: 'question'
    });

    var header = $('<h2>Question ' + (index + 1) + ':</h2>');
    qElement.append(header);

    var question = $('<p>').append(questions[index].question);
    qElement.append(question);

    var radioButtons = createRadios(index);
    qElement.append(radioButtons);

    return qElement;
  }

1.a What is (index) in the function parameter? I see is used in the function body but don't know what it is referenced to in the html or js code.

I think that's it for now. Thanks for any help.

Was it helpful?

Solution

1a - e is a variable referencing the event arguments. e.preventDefault() will prevent the default event action from completing - in this case, it will prevent the click action from firing off.

1b - Returning false from a jQuery event handler prevents the event from firing and prevents the event from bubbling up. (see this SO post for more info)

2 If you look in the displayNext function, the questionCounter appears to be tracking the total number of questions. So when createQuestionElement is called, it is passed this questionCounter as a parameter (which is the number of the next question being created)

OTHER TIPS

1.a) e is the eventObject , and e.preventDefault() method stops the default action of an element from happening, in this case, the click.

1.b) return false in a click event also stops click from doing default action, which may be opening an url

2) index is a parameter sent from another block of code, in this case if you check whole code, it says: var nextQuestion = createQuestionElement(questionCounter); so index in this case is the number of next question to show

1.a) Using e is just a short for event. You can pass any variable name you desire. e.preventDefault(); will stop the default action of the event. In this case, its click.

1.b) By returning false, you are preventing the remaining part of the code from firing. Once the browser comes across return false, it won't execute the remaining part of the code below it.

2) Index is an argument to the function. You will pass the argument while calling the function.

In this case:

var radioButtons = createRadios(index);

Calls the function by passing questions index.

As you can see,

var questions = [{
    question: "What is 2*5?",
    choices: [2, 5, 10, 15, 20],
    correctAnswer: 2
  },  {
    question: "What is 3*6?",
    choices: [3, 6, 9, 12, 18],
    correctAnswer: 4
  }]

Questions is an array, so you are passing the index to createRadio method to refer the same question there to construct the radio buttons as per the choices provided.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top