JSFiddle - React, Tailwind, and code Playground
by Michel Penke
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-sanitize.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chicago Loop Quiz</title>
</head>
<body class="container">
<section ng-app="ngQuiz" ng-controller="ngQuizController" class="quiz">
<image-preload></image-preload>
<div class="progress" ng-if="quizProgress.inProgress && quizProgress.currentQuestion <= quizProgress.lastQuestion">
<span ng-cloak class="counter">Question {{quizProgress.currentQuestionFriendly}} of {{quizProgress.lastQuestion}}</span>
<div class="progress-bar" progress-bar></div>
</div>
<div class="content">
<!-- intro -->
<section ng-cloak class="intro fade-in" ng-if="!quizProgress.loading && !quizProgress.inProgress && !quizProgress.finished">
<div ng-cloak class="row">
<div class="col-xs-6">
<h1>{{::quizMetadata.title}}</h1>
<p>{{::quizMetadata.intro}}</p>
</div>
<div class="col-xs-6">
<img ng-src="{{quizMetadata.introImg}}" />
<aside class="figure-caption text-xs-right" ng-if="quizMetadata.introImgCredit">Photo credit: {{::quizMetadata.introImgCredit}}</aside>
</div>
</div>
<div class="row">
<button class="pull-right btn btn-success" ng-click="startQuiz()">Start Quiz</button>
</div>
</section>
<!-- question list -->
<section ng-cloak class="fade-in question" ng-if="quizProgress.inProgress && quizProgress.currentQuestion...
CSS
/* With keyframe animations from animate.css */
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
body {
padding-top: 1.5em;
font-family: 'Open Sans', sans-serif;
}
.quiz {
margin-top: 1em;
min-height: 60vh;
background: #fff;
box-shadow: -2px 0px 21px -2px rgba(0, 0, 0, 0.4);
}
.text-center {
text-align: center;
}
.quiz .question img {
display: block;
margin: 0 auto;
}
.quiz button {
margin-top: 2em;
user-select: none;
outline: 0!important;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
}
.quiz .btn {
font-size: 1.6rem;
height: 3.2em;
transition: all .25s ease;
}
.quiz .btn-primary,
.quiz .btn-success {
opacity: 0.9;
background: #4c9cff;
border-radius: 0;
border: 0;
padding: 0.5em 1em;
text-align: center;
color: #fff;
}
.quiz .btn-primary:hover {
opacity: 1;
background: #4c9cff;
color: #fff
}
.quiz .btn-success {
background: #51a351;
}
.quiz .btn-success:hover,
.quiz .btn-success:active {
background: #4a9e4a;
}
.quiz .btn-primary:disabled,
.quiz .btn-primary:disabled:hover {
background: #ccc;
}
.quiz .content {
color: #222;
padding: .25em 3em 2em 3em;
margin-bottom: 1em;
}
.quiz .intro {
margin-top: 2em;
}
.quiz .intro p {
font-size: 2rem;
}
.quiz aside {
color: #777;
font-size: 1.5rem;
padding-top: 0.25em;
}
.quiz .question {
margin-top: 2em;
position: relative;
}
.quiz .question img {
box-shadow: -2px 0px 21px -2px rgba(0, 0, 0, 0.4);
}
.quiz .question p,
.quiz .intro p {
font-size: 1.8rem;
line-height: 1.5;
margin: 1em 0;
}
.quiz .intro p:last-of-type {
padding-bottom: 0;
}
.quiz .question-content {
min-height: 50px;
}
.quiz .question-options {
margin-left: 1.5rem;
}
.quiz .feedback {
padding-bottom: .75em;
margin: -.5em 1em 0 2em;
animation: .75s roll-in ease;
}
.quiz .progress {
position: relative;
margin-bottom: 0;
background: rgb(181, 181, 181);
border-radius: 0;
width: 100%;
}
.quiz .progress-bar {
background:...
JavaScript
angular.module('ngQuiz', ['ngSanitize'])
.controller('ngQuizController', function($scope, $timeout, quizProgress, scoreKeeper) {
$scope.quizProgress = quizProgress;
$scope.quizData = {
"quizMetadata": {
"title": "Loop Quiz",
"intro": "Do you know the real scoop on the Loop? It’s time to find out!",
"introImg": "http://interactive.wttw.com/sites/default/files/styles/small-hero/public/B12_b.jpg",
"introImgCredit": "Alan Brunettin"
},
"quizQuestions": [{
"question": "The Chicago Loop got its name from:",
"questionImg": "http://interactive.wttw.com/sites/default/files/styles/hero/public/Q1.jpg",
"feedback": "Before the “L” came to the Loop, steam-powered cable cars circulated downtown, giving the area its name. Later, the elevated tracks and trains of the “L” made the Loop even more accessible to people throughout the Chicago region.",
"options": [{
"name": "The “L” tracks that circle the area.",
"correct": false
}, {
"name": "Cable cars that circulated downtown before the “L” was built.",
"correct": true
}, {
"name": "A turnaround circle for horse-drawn carriages.",
"correct": false
}]
}, {
"question": "What caused the Great Chicago Fire?",
"questionImg": "http://interactive.wttw.com/sites/default/files/styles/hero/public/Q2.jpg",
"feedback": "The fire did start in the vicinity of the O’Leary’s barn, but whether a cow kicked over a lantern, or a cinder came from a neighboring chimney, or a drunken neighbor dropped his pipe onto a pile of hay, or a meteor strike occurred (all theories that have been, ahem, hotly debated), no one knows for sure what happened in that barn, and the fire’s initial spark has never been definitively established.",
"options": [{
"name": "Mrs. O’Leary’s cow.",
"correct": false
}, {
"name": "A meteor strike.",
"correct": false
}, {
...