Skip to content

Instantly share code, notes, and snippets.

@chrisege
Last active August 29, 2015 14:08
Show Gist options
  • Save chrisege/8254ccfd17c8c0bdd8db to your computer and use it in GitHub Desktop.
Save chrisege/8254ccfd17c8c0bdd8db to your computer and use it in GitHub Desktop.
Food Quiz
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' type='text/css' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css'></link>
</head>
<body class="container">
<script type="text/template" id="quizTemplate">
<h1 class="title">
<%= title %>
</h1>
<h2 class="subtitle">
<%= subtitle %>
</h2>
<div class="well" id="questionBox">
<div class="row">
<div class="col-sm-10">
<!--<button class="intro startQuiz btn btn-primary">Start the quiz!</button>-->
</div>
<div class="scores col-sm-2">
<h4>Score: <span id="score"><%= score %></span> / <span id="possibleScore"><%= possibleScore %></span></h4>
</div>
</div>
<div class="question row">
</div>
</div>
</script>
<script type="text/template" id="questionTemplate">
<h3 class="title">
<%= title %>
</h3>
<div class="row">
<div class="col-sm-4 firstColumn">
<ul>
<% _.each( firstColumn, function( item ){ %>
<li><%= item %></li>
<% }); %>
</ul>
</div>
<div class="col-sm-4">
<div class="secondColumn"></div>
<div class="buttons">
<button class="checkResults btn btn-primary">Check Results</button>
<button class="nextQuestion btn btn-primary" style="display:none;">Next Question</button>
</div>
</div>
</div>
</script>
<script type="text/template" id="multiQuestionTemplate">
<h3 class="title">
<%= title %>
</h3>
<div class="col-sm-4">
<%= question %>
<div class="questionCtn">
<% _.each( options, function( option ){ %>
<div class="radio">
<label>
<input type="radio" name="options" value="<%= option %>">
<%= option %>
</label>
</div>
<% }); %>
</div>
<div class="answerCtn" style="display:none;">
<h3 class="status"></h3>
<p><%= explanation %></p>
</div>
<div class="buttons">
<button class="checkResults btn btn-primary">Check Answer</button>
<button class="nextQuestion btn btn-primary" style="display:none;">Next Question</button>
</div>
</div>
<div class="col-sm-4">
<div class="imgCtn"><img src="<%= image %>" alt="<%= image_alt %>" /></div>
</div>
</script>
<script type="text/template" id="answerTemplate">
<% _.each( shuffledItems, function( item ){ %>
<li><%= item %></li>
<% }); %>
</script>
<script type="text/template" id="finalScoreTemplate">
<h3>Your final score is:</h3>
<h1><span id="score"><%= score %></span> / <span id="possibleScore"><%= possibleScore %></span></h1>
<h2><%= quote %></h2>
<p><a href="<%= fb_link %>">Share on Facebook</a></p>
</script>
<div class="row">
<div id="quiz" class="col-sm-12">
</div>
<div id="question" class="col-sm-12">
</div>
</div>
<script src='https://code.jquery.com/jquery-1.11.1.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="quiz.js"></script>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '120005534692936',
xfbml : true,
version : 'v2.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
</body>
</html>
var quizApp = quizApp || {};
quizApp.Quiz = Backbone.Model.extend({
defaults: {
title: '',
subtitle: '',
questions: [],
score: 0,
possibleScore: 0,
currentQuestion: 0
},
incrementScores: function(score){
this.set('score', (this.get('score') + score ));
this.trigger('change');
},
prepFinalScore: function(){
var resultsRange = this.get('resultsRange'),
score = this.get('score'),
result;
_.each( _.keys(resultsRange).map(function(key){return +key}), function(key){
if (score <= key) {
result = key;
return false;
}
});
this.set('quote', resultsRange[result]);
this.setFbLink();
return this;
},
setFbLink: function(){
//https://www.facebook.com/dialog/feed?app_id=692446294161510&display=popup&link=http://www.clickhole.com/quiz/how-many-these-thoughts-have-you-had-1357&name=I got: You’re A Junior Thinker - How Many Of These Thoughts Have You Had?&description=Think you’ve thought all the thoughts? Take this quiz and find out.&image=http://chimg.onionstatic.com/5346/original/600.jpg&redirect_uri=http://www.clickhole.com/shared?s=fb-shared
var quote = this.get('quote'),
title = this.get('subtitle'),
name = "I got "+ quote + " " +title,
link;
link = 'https://www.facebook.com/dialog/feed?app_id=120005534692936&display=popup'+
'&link='+ 'http://interactive.wttw.com/where-in-chicago=' + //document.URL+
'&name='+name+
'&description='+'How well do you know Chicago? Take Geoffrey Baer\'s Where in Chicago quiz and find out!'+
'&redirect_uri='+ 'http://interactive.wttw.com/where-in-chicago/' //document.URL
this.set('fb_link', link);
}
});
quizApp.Question = Backbone.Model.extend({
defaults: {
title: "",
possibleScore: 1
}
});
quizApp.multiQuestion = Backbone.Model.extend({
defaults: {
title: "",
}
});
quizApp.Answer = Backbone.Model.extend({
defaults: {
items: [],
},
initialize: function(){
this.shuffle();
},
shuffle: function(){
this.set('shuffledItems', _.shuffle(this.get('items')));
},
score: function(){
return this.compareArrays(this.get('items'), this.get('shuffledItems'));
},
compareArrays: function(arr1, arr2){
var compared = _.map(arr1, function(value, key){
return arr2[key] == value;
});
var score = _.reduce(compared, function(memo,val){
return val == true ? memo + 1 : memo;
},0);
return {
score: score,
key: compared,
items: this.get('items')
}
},
});
quizApp.QuizView = Backbone.View.extend({
tagName: 'div',
template: $("#quizTemplate").html(),
questionIndex: 0,
questionCount: 0,
events: {
'click .startQuiz': 'startQuiz',
'click .shareFb': 'shareFb'
},
initialize: function(){
// create a question collection.
// get the questions array, and loop through it
// assign the question's array index as its id
// and add it to the collection
this.questions = new quizApp.QuestionCollection();
_.each(this.model.get('questions'), function(question, index){
question.id = index;
this.questions.add(question);
this.questionCount += 1;
}.bind(this));
this.model.set('possibleScore', this.questions.getPossibleScore());
},
render: function(){
var tmpl = _.template(this.template);
this.$el.append(tmpl(this.model.toJSON()));
this.startQuiz();
return this;
},
renderQuestion: function(){
var question = this.questions.get(this.questionIndex);
switch (question.get('type')) {
case 'match':
this.currentQuestion = new quizApp.QuestionView({
model: question,
el: this.$el.find('.question'),
});
break;
case 'multi':
this.currentQuestion = new quizApp.MultiQuestionView({
model: question,
el: this.$el.find('.question'),
});
break;
}
this.currentQuestion.model.set('parentView', this);
this.currentQuestion.model.set('parentModel', this.model);
this.currentQuestion.render();
this.listenTo(this.currentQuestion.model, 'change', this.updateScore);
this.listenTo(this.currentQuestion, 'nextQuestion', this.nextQuestion);
},
renderFinalScore: function(){
this.$el.find('.scores').remove();
this.model.prepFinalScore();
var tmpl = _.template($('#finalScoreTemplate').html());
this.$el.find('.question').html(tmpl(this.model.toJSON()));
},
startQuiz: function(){
this.$el.find('.intro').fadeOut();
this.renderQuestion();
},
updateScore: function(){
this.model.incrementScores(
this.currentQuestion.model.get('score')
);
this.$el.find('#score').html(this.model.get('score'));
this.$el.find('#possibleScore').html(this.model.get('possibleScore'));
},
nextQuestion: function(){
this.questionIndex += 1;
this.currentQuestion.close();
if (this.questionIndex >= this.questionCount) {
this.renderFinalScore();
} else {
this.renderQuestion();
}
}
});
quizApp.QuestionView = Backbone.View.extend({
tagName: 'div',
template: $("#questionTemplate").html(),
initialize: function(){
this.answerModel = new quizApp.Answer({'items': this.model.get('secondColumn')});
this.answerView = new quizApp.AnswerView({model: this.answerModel});
},
events: {
'sortupdate':'updateAnswer',
'click .checkResults': 'checkResults',
'click .nextQuestion': 'nextQuestion'
},
render: function(){
var parent = this;
var tmpl = _.template(this.template);
this.answerView.render();
this.$el.append(tmpl(this.model.toJSON()));
this.$('.secondColumn').append(this.answerView.el);
this.$('.secondColumn ul').sortable();
return this;
},
// method to be run when jQueryUI fires a sortupdate event.
// sets answerModel's shuffledItems array to whatever order
// the user has put them in.
updateAnswer: function(){
var newOrder = [];
this.$el.find('.secondColumn li').each(function(){
newOrder.push($(this).html());
});
this.answerModel.set('shuffledItems', newOrder);
},
checkResults: function(){
//run the answerModel.score() method and store value locally
var score = this.answerModel.score();
// set this.model score and possibleScore values
this.model.set({
score: score.score,
possibleScore: score.key.length
});
// mark the matching responses as true or false,
// if false, add the correct answer here
// TODO: make "correct answer" show left column value instead?
this.$el.find('.secondColumn li').each(function(index, element){
var thisScore = score.key[index].toString();
$(element).removeClass().addClass(thisScore);
if (thisScore === 'false') { $(element).append(' ('+score.items[index]+')'); }
});
// hide the check results button, show the next question button
this.$el.find('.buttons button').each(function(){
$(this).toggle();
});
},
nextQuestion: function(){
this.trigger('nextQuestion');
},
//use instead of remove() because it empties $el instead of removing it.
close: function(){
this.unbind();
this.undelegateEvents();
this.stopListening();
this.$el.empty();
},
});
quizApp.MultiQuestionView = Backbone.View.extend({
tagName: 'div',
template: $("#multiQuestionTemplate").html(),
initialize: function(){
},
events: {
'click .checkResults': 'checkResults',
'click .nextQuestion': 'nextQuestion'
},
render: function(){
var tmpl = _.template(this.template);
this.$el.append(tmpl(this.model.toJSON()));
return this;
},
checkResults: function(){
var selected = this.$el.find('input:radio:checked').val();
var score = (selected === this.model.get('answer') ? 1 : 0);
this.model.set({
score: score,
possibleScore: 1
});
this.$el.find('.questionCtn').remove();
this.$el.find('.status').html(score === 1 ? 'Correct!' : 'Incorrect!');
this.$el.find('.answerCtn').fadeIn();
this.$el.find('.buttons button').each(function(){
$(this).toggle();
});
},
nextQuestion: function(){
this.trigger('nextQuestion');
},
//use instead of remove() because it empties $el instead of removing it.
close: function(){
this.unbind();
this.undelegateEvents();
this.stopListening();
this.$el.empty();
},
});
quizApp.AnswerView = Backbone.View.extend({
tagName: 'ul',
template: $("#answerTemplate").html(),
render: function(){
var tmpl = _.template(this.template);
this.$el.append(tmpl(this.model.toJSON()));
return this;
}
});
quizApp.QuestionCollection = Backbone.Collection.extend({
model: quizApp.Question,
getPossibleScore: function(){
var possibleScore = 0;
this.each(function(model){
possibleScore += model.get('possibleScore');
});
return possibleScore;
}
});
var fullQuizMulti = {
'title': 'Test Your Knowledge',
'subtitle': 'Where in Chicago Food Quiz',
'hideIntro': true,
'resultsRange': {
"0": "Terrible! (zero)",
"3": "Not great. (1-3)",
"5": "Acceptable. (4-5)",
"8": "Pretty good! (6-8)",
"10": "Excellent! (9-10)"
},
'questions': [
{
'type': 'multi',
'question': 'Which of these confections is NOT originally from Chicago?',
'image': 'http://lorempixel.com/640/360/?1',
'image_alt': 'confections picture',
'options': [
'Snickers',
'Hershey’s Kisses',
'Juicy Fruit Gum',
'Milk Duds'
],
'answer': 'Hershey’s Kisses',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'Authentic African-American southern barbecue served in Chicago is traditionally topped with what?',
'image': 'http://lorempixel.com/640/360/?2',
'image_alt': 'BBQ picture',
'options': [
'A slice of white bread',
'Cole Slaw',
'Okra',
'Onion Rings'
],
'answer': 'A slice of white bread',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'Which of these food companies was founded in Chicago?',
'image': 'http://lorempixel.com/640/360/?3',
'image_alt': 'Grocery store shelves',
'options': [
'Quaker Oats',
'Nabisco',
'Kraft',
'All of the above'
],
'answer': 'All of the above',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'Which of these dishes was NOT invented in Chicago?',
'image': 'http://lorempixel.com/640/360/?4',
'image_alt': 'Table setting with no food yet served',
'options': [
'Italian Beef',
'Flaming Saganaki',
'Chicken Vesuvio',
'Chop Suey'
],
'answer': 'Chop Suey',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'What year was the first Taste of Chicago?',
'image': 'http://lorempixel.com/640/360/?5',
'image_alt': 'Taste of Chicago',
'options': [
'1972',
'1980',
'1984',
'1989'
],
'answer': '1980',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'When Prohibition ended, which Chicago restaurant was the first in the city to receive a liquor license?',
'image': 'http://lorempixel.com/640/360/?6',
'image_alt': 'Prohibition',
'options': [
'The Berghoff',
'Edgewater Beach Hotel',
'Tip Top Tap',
'Pizzeria Uno'
],
'answer': 'The Berghoff',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'What year did the Union Stockyards Close?',
'image': 'http://lorempixel.com/640/360/?7',
'image_alt': 'Stockyards',
'options': [
'1953',
'1964',
'1982',
'1971'
],
'answer': '1971',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'In which suburb did Ray Kroc build the first McDonald’s franchise in 1955 (it’s now a museum)?',
'image': 'http://lorempixel.com/640/360/?8',
'image_alt': 'McDonalds',
'options': [
'Des Plaines',
'Oak Brook',
'Romeoville',
'Homewood'
],
'answer': 'Des Plaines',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'Invented in Chicago, the “autodoner” is…',
'image': 'http://lorempixel.com/640/360/?9',
'image_alt': 'Restaurant Kitchen',
'options': [
'A machine that mixes milkshakes',
'A hand-held food processor',
'A device used to cook gyros',
'A machine that stuffs hot dogs into casings'
],
'answer': 'A device used to cook gyros',
'explanation': 'Lorem ipsum dolor sit amet.'
},
{
'type': 'multi',
'question': 'A jibarito sandwich, invented in Chicago, is served on what in place of bread?',
'image': 'http://lorempixel.com/640/360/?10',
'image_alt': 'Borinquen Restaurant',
'options': [
'Romaine lettuce',
'Flattened fried plantains',
'Newspaper',
'Pie crust'
],
'answer': 'Flattened fried plantains',
'explanation': 'Lorem ipsum dolor sit amet.'
},
]
}
var quiz = new quizApp.Quiz(fullQuizMulti);
var quizView = new quizApp.QuizView({model: quiz, el:$('#quiz')});
quizView.render();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment