A Quiz App With a Summer Theme

I started this project by creating all the html forms and buttons for the quiz. Each question would have markup similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="question-1">
  <h2>Where does the phrase 'dog days of summer' come from ?</h2>
  <form>
    <input type="radio" name="q1" id="q1-a" value="dogs" /> Lazy Dogs
    <br>
    <input type="radio" name="q1" id="q1-b" value="movie" /> Reference from a movie
    <br>
    <input type="radio" name="q1" id="q1-c" value="novel" /> A term coined from a famous novel
    <br>
    <input type="radio" name="q1" id="q1-d" value="star" /> A star
    <br><br>
    <input type="submit" value="Final answer">
  </form>
</div>

The other important html markup involved elements that are initially hidden using the css property display. They’re shown depending on which answer is chosen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<aside id="wrong">
  <img src="images/Awesome-Icons_angry.png" alt="lose icon" height="300px"/>
  <button id="w-next">Next Question</button>
</aside>

<aside id="correct">
  <img src="images/Awesome-Icons_winner.png" alt="win icon" height="300px"/>
  <button id="c-next">Next Question</button>
</aside>

<ul>
  <li><img src="images/summer-16.png" alt="flip-flops" id="q1-icon"/></li>
  <li><img src="images/summer-12.png" alt="sand castle" id="q2-icon"/></li>
  <li><img src="images/summer-25.png" alt="beachball" id="q3-icon"/></li>
  <li><img src="images/summer-22.png" alt="ice cream" id="q4-icon"/></li>
  <li><img src="images/summer-21.png" alt="sailboat" id="q5-icon"/></li>
</ul>

I first used jQuery to create a submit handler for each question and show the separate styles.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$( " #question-1 form" ).submit(function( event ) {
  event.preventDefault();
  var input = $('input[name=q1]:checked', '#question-1').val();
  $("#question-1").css("display", "none");
  if (input == question1.answer) {
    $("#correct").css("display", "block");
    $("img#q1-icon").css("opacity", "1.0");
    score +=1;
    correctNext("question-2");
  } else {
    $("#wrong").css("display", "block");
    wrongNext("question-2");
  }
});

Once the app worked, I migrated the questions into Javascript objects and worked towards making the functions reusable. I created each question by calling the createQuestion function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var question1 = new createQuestion("1","Where does the phrase 'dog days of summer' come from ?",
                                    "Lazy dogs", "A reference", "A term coined from a famous novel", "A star",
"A star");

function createQuestion(id, question, a, b, c, d, answer) {
  this.id = id;
  this.question = question;
  this.a = a;
  this.b = b;
  this.c = c;
  this.d = d;
  this.answer = answer;
  return this;
}

Afterwards, I added them to an array and looped through it to create the forms. The previous css still worked and the questions are hidden until the corresponding submit handler is called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var questionList = [question1, question2, question3, question4, question5 ];
for (var i = 0, l = questionList.length; i < l; i ++) {
  var v = questionList[i];
  var result = createQuestionform(questionList[i]);
  $('section').append(result);
}

function createQuestionform(obj) {
  var result = $("<div id='question-"+obj.id+"'>"+
                  "<h2>"+obj.question+"</h2>"+
                  "<form>"+
                  "<input type='radio' name='q"+obj.id+"' value='"+obj.a+"'/>"+obj.a+"<br>"+
                  "<input type='radio' name='q"+obj.id+"' value='"+obj.b+"'/>"+obj.b+"<br>"+
                  "<input type='radio' name='q"+obj.id+"' value='"+obj.c+"'/>"+obj.c+"<br>"+
                  "<input type='radio' name='q"+obj.id+"' value='"+obj.d+"'/>"+obj.d+"<br><br>"+
                  "<input type='submit' value='Final answer'>"+
                  "</form>"+
                  "</div>");
  return result;
}

I also used Pixlr to shrink the images from Unsplash so that they would be more web friendly.

Hot or Cold Number Guessing Game

The number guessing game project design and the initial html was provided to allow students to focus solely on the logic behind the game.

I’ve created a similar game through Sinatra before and the logic I used was very similar to that. Instead of a post request to the server, a submit function captures the input and calls several functions to check which feedback to use. The event.preventDefault was not placed in the end because the next if statement checks if an input is valid and could subsequently exit out of the function before the rest of the methods are called.

1
2
3
4
5
6
7
8
9
10
$( "#guess" ).submit(function( event ) {
  var input = +$("input").val();
  event.preventDefault();
  if (input > 100 || input <= 0) {
    return invalid();
  }
  increaseCount(input);
  var feedback = checkGuess(input);
  $('#feedback').text(feedback);
});

The invalid function sets the feedback message to tell the user to enter a valid guess.

1
2
3
function invalid() {
  $('#feedback').text('Please make a guess between 1 and 100');
}

A new game button restarts the process when clicked or when the maximum allowed guesses is reached. This function is also responsible for setting the new secretNumber and resetting the count to 0. This function also tells the user that the count has been reset and removes all of the old guesses.

1
2
3
4
5
6
function newGame() {
  secretNumber = Math.floor(Math.random() * 100) + 1;
  count = 0;
  $('#count').text(count);
  $('#guessList li').remove();
}

The increaseCount function raises the count variable by 1 and appends the previous guess to the page. This function is always called by the submit button unless the user inputs an invalid number.

1
2
3
4
5
function increaseCount(guess) {
  count += 1;
  $('#count').text(count);
  $('#guessList').append('<li>'+guess+'</li>');
}

The checkGuess function handles the game logic by giving a specific feedback based on how far the guess is from the secretNumber.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function checkGuess(guess) {
  if (Math.abs(guess-secretNumber) >= 50) {
    return 'Ice cold';
  } else if (Math.abs(guess-secretNumber) > 30) {
    return 'cold';
  } else if (Math.abs(guess-secretNumber) > 20) {
    return 'warm';
  } else if (Math.abs(guess-secretNumber) > 10) {
    return 'hot';
  } else if (Math.abs(guess-secretNumber) > 1 ) {
    return 'very hot';
  } else {
    newGame();
    return 'You got it right!';
  }
}

In the future, I would like to further refactor the game so that there are less responsibilities in the submit handler. Also, instead of Math.abs(), the game should be able to say if the guess us too high or too low.

Creating a Shopping List With jQuery

This shopping list project is an example of creating a basic todo list. I used materialpalette to pick out the color combinations I included and the process involved appending and removing nodes in the app for the list.

I was creating the list items dynamically and I created variables to hold the string for the three types of button; to delete the item, to mark the item as acquired, and to undo that mark.

1
2
3
  var del_btn = "<button class='fa fa-trash-o'></button>";
  var check_btn = "<button class='fa fa-check-circle-o'></button>";
  var times_btn = "<button class='fa fa-times'></button>";

The next part of the script was the submit event handler appends a new item to the list unordered list.

1
2
3
4
5
$( "#item" ).submit(function( event ) {
  var x = $("input").val();
  $('.list').append("<li>"+x+del_btn+check_btn+"</li>");
  event.preventDefault();
});

The next three statements were created using the on event handler and attaching them to the three variable buttons created. I used on instead of click because the latter would only attach the click function if the button exists when the page is first loaded.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$('.list').on('click', '.fa-trash-o', function(){
  $(this).parent().remove();
});

$('.list').on('click', '.fa-check-circle-o', function(){
  var item = $(this).parent().text();
  $(this).parent().remove();
  $('.complete-list').append("<li class='complete'>"+item+del_btn+times_btn+"</li>");
});

$('.complete-list').on('click', '.fa-times', function(){
  var item = $(this).parent().text();
  $(this).parent().remove();
  $('.list').append("<li>"+item+del_btn+check_btn+"</li>");
});

The last on click handler removes the whole list and basically restarts the whole app.

1
2
3
$('.complete-list').on('click', '.fa-trash-o', function(){
  $(this).parent().remove();
});

A Little Bit of jQuery Animation

The third project introduced the idea behind click handlers in jQuery and using the animate method. The process involved learning how images are loaded along with how styles can be included and hidden until Javascript includes the images.

The whole script was relative small and involved six actions; mouseenter, mouseleave, mousedown, mouseup, keydown, and keyup. The first one would hide the still Ryu image and replace it with a looping gif of Ryu swaying in place.

1
2
3
4
$('.ryu').mouseenter(function() {
  $('.ryu-still').hide();
  $('.ryu-ready').show();
})

mouseleave would do the opposite and change the gif back to a still Ryu.

1
2
3
4
.mouseleave(function() {
  $('.ryu-ready').hide();
  $('.ryu-still').show();
})

mousedown animates the hadouken image, swap the ready image to Ryu throwing, and plays the sound script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.mousedown(function() {
  playHadouken();
  $('.ryu-ready').hide();
  $('.ryu-throwing').show();
  $('.hadouken').show();
  $('.hadouken').finish().show()
  .animate(
    {'left': '1020px'},
    500,
    function() {
      $(this).hide();
      $(this).css('left', '520px');
    }
  );
})

mouseup swaps the throwing Ryu image with the ready image/

1
2
3
4
.mouseup(function() {
  $('.ryu-throwing').hide();
  $('.ryu-ready').show();
});

keydown checks if the x key was pressed first and goes through if else statements to show which image to hide then show Ryu striking a pose

1
2
3
4
5
6
7
8
9
10
11
12
$(document).keydown(function(e) {
  if (88 == e.which) {
    if ($('.ryu-ready').is(':visible')){
      $('.ryu-ready').hide();
    } else if ( $($('.ryu-throwing').is(':visible')) ) {
      $('.ryu-throwing').hide();
    } else {
      $('.ryu-still').hide();
    }
    $('.ryu-cool').show();
  }
})

keyup does the opposite and hide Ryu striking a pose.

1
2
3
4
5
6
7
8
9
10
.keyup(function(e) {
  if (88 == e.which) {
    if ($('.ryu').mouseenter()) {
      $('.ryu-ready').show();
    } else {
      $('.ryu-still').show();
    }
    $('.ryu-cool').hide();
  }
});

During my first implementation of the project, I didn’t differentiate between the different images during the keydown event and it would produce multiple images when it was called. I’m not quite sure what was happening so I added the if else statements to check what state Ryu was in before continuing.

Using the Chrome Developer Tools

Chrome Developer Tools involved the next Thinkful project I added and it was a brief introduction to what was available to a developer. There’s a lot of tools available from there, and I know I’ve only scratched the surface, but it’s great how useful that little bit of knowledge has been.

I spent most of my time using the elements tab to view how the html tags were structure and to view the styles implemented there. Changing the styles also allowed me to get a glimpse on how the rest of the page was marked up and it was a great way to figure out the right positions without editing the stylesheets over and over again.

The console tab was the second most panel that I spend my time with because it’s great for debugging and allows anyone to run a snippet of Javascript code to see how it works. I’m getting into the habit of adding multiple console logs in my Javascript script to see how a variable changes when it’s called. This allows me a window to see if the functions I write are behaving the way I expect them to.

Other than those two, I’ve also been using the resource tab to check if the assets are being loaded correctly and the sources tab to see the exact scripts being loaded. I’m looking into another add on to Chrome called RailsPanel to see how much it could help me when I write Rails applications.

Writing Html and Css From a Specific Design

The first project I went through in Thinkful was creating a landing page from a design they gave me. I’ve been accustomed to using bootstrap to setup navigation and positioning elements throughout the page so this excercise was relatively simple and also extremely useful.

I did not realize how much of the basics of html and css I had forgotten until I was unable to use concepts like padding and nested elements. The box model is the basis for a lot of styles and selectors are just as important since you would not be able to apply those styles without knowing which one to declare. Being reintroduced to those two details alone made the project worth it.

Also, I found tools like FontFaceNinja and ColorZilla very useful. I knew how to use the Chrome Developer tools to check the html markup and styles for the page but that felt like I would be cheating myself from learning.

The next step would be learning more about how to organize those styles. After including so many to each individual element, I kept on feeling like there should be a better way to go about it. Even after one day away from that stylesheet, it was very difficult to come back and add more styles without declaring new statements at the bottom. I know that overriding styles is the main idea behind CSS, but I always thought that it should be for inherited styles instead of multiple selectors for the same element.

Another step after that would be learning a preproccessor like Sass along with libraries such as Compass and Bourbon.