Last active
August 29, 2015 14:09
-
-
Save chrisege/22eef6c82818aa782fb1 to your computer and use it in GitHub Desktop.
Arts Quiz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 Arts & Entertainment 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 the following sitcoms was not set in Chicago?', | |
'image': 'http://lorempixel.com/640/360/?1', | |
'image_alt': '', | |
'options': [ | |
'Family Matters', | |
'Good Times', | |
'The Facts of Life', | |
'The Bob Newhart Show' | |
], | |
'answer': 'The Facts of Life', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'Which TV show was filmed entirely on location in Chicago?', | |
'image': 'http://lorempixel.com/640/360/?2', | |
'image_alt': '', | |
'options': [ | |
'The Good Wife', | |
'Shameless', | |
'ER', | |
'Early Edition' | |
], | |
'answer': 'Early Edition', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'Who was the best man in the 1973 wedding of Chicago blues legend Muddy Waters at Muddy’s home in suburban Westmont?', | |
'image': 'http://lorempixel.com/640/360/?3', | |
'image_alt': '', | |
'options': [ | |
'Buddy Guy', | |
'Eric Clapton', | |
'Mick Jagger', | |
'Ernie Banks' | |
], | |
'answer': 'Eric Clapton', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'The John Cusak film <em>High Fidelity</em> is set in what fictional Chicago record store?', | |
'image': 'http://lorempixel.com/640/360/?4', | |
'image_alt': '', | |
'options': [ | |
'High Fidelity Records', | |
'Championship Vinyl', | |
'Records a Go Go', | |
'Windy City LPs' | |
], | |
'answer': 'Championship Vinyl', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'In 2000, the original members of The Smashing Pumpkins played a farewell show at what Chicago venue?', | |
'image': 'http://lorempixel.com/640/360/?5', | |
'image_alt': '', | |
'options': [ | |
'The Cubby Bear', | |
'United Center', | |
'The Metro', | |
'Auditorium Theatre' | |
], | |
'answer': 'The Metro', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'In the movie <em>While You Were Sleeping</em>, Sandra Bullock’s character: ', | |
'image': 'http://lorempixel.com/640/360/?6', | |
'image_alt': '', | |
'options': [ | |
'Drives a CTA bus', | |
'Collects fares at an “L” station', | |
'Gives Chicago River boat tours', | |
'Works at the Department of Motor Vehicles' | |
], | |
'answer': 'Collects fares at an “L” station', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'These statues at Michigan Avenue and Congress are called “The Spearman” and “The Bowman,” but their weapons are missing. Why?', | |
'image': 'http://lorempixel.com/640/360/?7', | |
'image_alt': '', | |
'options': [ | |
'The weapons were removed the melted down for the war effort in WWII.', | |
'The artist Ivan Mestrovic left them to our imagination.', | |
'City reformers objected to the display of weapons near Grant Park where children play.', | |
'They were stolen by vandals and never replaced.' | |
], | |
'answer': 'The artist Ivan Mestrovic left them to our imagination.', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'Who modeled for the statue of a naked cherub located at the Hilton Chicago hotel on South Michigan Avenue?', | |
'image': 'http://lorempixel.com/640/360/?8', | |
'image_alt': '', | |
'options': [ | |
'The child of hotel guests visiting from Germany', | |
'Future Supreme Court Justice John Paul Stevens', | |
'Future burlesque dancer Sally Rand', | |
'It was modeled on a cherub sculpture at the Vatican.' | |
], | |
'answer': 'Future Supreme Court Justice John Paul Stevens', | |
'explanation': 'The Hilton Chicago was built as the Stevens Hotel in 1927 by the father and grandfather of the future Supreme Court Justice.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'How did the improv comedy theatre Second City get its name?', | |
'image': 'http://lorempixel.com/640/360/?9', | |
'image_alt': '', | |
'options': [ | |
'Because the rapid-fire punchlines come once every second', | |
'Because this was the theatre’s second home. The first was Des Moines, Iowa', | |
'It was an insult by a New Yorker Magazine writer about the dearth of arts and culture in Chicago.', | |
'A reference to the troupe’s lewd motto, “We’re Number Two!”' | |
], | |
'answer': 'It was an insult by a New Yorker Magazine writer about the dearth of arts and culture in Chicago.', | |
'explanation': 'Lorem ipsum dolor sit amet.' | |
}, | |
{ | |
'type': 'multi', | |
'question': 'The opening of Orchestra Hall in 1905 was said to have killed the Chicago Symphony’s fiery conductor Theodore Thomas. How?', | |
'image': 'http://lorempixel.com/640/360/?10', | |
'image_alt': '', | |
'options': [ | |
'He contracted pneumonia after marathon January rehearsals in the frigid, damp, unfinished hall.', | |
'Vibrations from a loud passage of music dislodged plaster that fell on him', | |
'He committed suicide after bad reviews of the hall’s acoustics on opening night.', | |
'He tripped on the conductor’s podium, which was built higher than he expected.' | |
], | |
'answer': 'He contracted pneumonia after marathon January rehearsals in the frigid, damp, unfinished hall.', | |
'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