├── README.md
├── css
├── form.css
└── print.css
├── index.html
├── js
├── Option.js
├── Question.js
├── Quiz.js
└── Result.js
└── questions.js
/README.md:
--------------------------------------------------------------------------------
1 | # javascript-quiz-library
2 | Very simple JS library for quiz creation
3 |
4 | ## Usage
5 |
6 | `git clone` and edit `questions.js`. See `index.html` to change the quiz name.
7 |
8 | ## Demo
9 |
10 | [See demo here.](https://zimmicz.github.io/javascript-quiz-library/)
--------------------------------------------------------------------------------
/css/form.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #36393D;
3 | font-family: "Open Sans", Arial, sans-serif;
4 | font-size: 90%;
5 | margin: 1em auto;
6 | width: 750px;
7 | }
8 |
9 | fieldset {
10 | border-color: #356AA0;
11 | margin-bottom: 1em;
12 |
13 | }
14 |
15 | legend {
16 | font-size: 105%;
17 | font-weight: 600;
18 | padding-left: 15px;
19 | padding-right: 15px;
20 | padding-top: 15px;
21 | }
22 |
23 | label {
24 | display: block;
25 | line-height: 1.75em;
26 | }
27 |
28 | input[type="radio"] {
29 | margin-right: 10px;
30 | }
31 |
32 | input[type="submit"] {
33 | background: #689DD3;
34 | border: 1px solid #356AA0;
35 | color: white;
36 | display: block;
37 | font-size: 120%;
38 | font-weight: 600;
39 | height: 2.5em;
40 | margin-top: 2em;
41 | text-transform: uppercase;
42 | width: 100%;
43 | }
44 |
45 | table {
46 | color: white;
47 | font-weight: bold;
48 | margin: 1em auto 2em auto;
49 | width: 360px;
50 | }
51 |
52 | td {
53 | padding: 5px 15px;
54 | text-align: left;
55 | width: 60px;
56 | }
57 |
58 | td.missing-label,
59 | td.right-label,
60 | td.wrong-label {
61 | border-bottom: 1px solid;
62 | border-left: 1px solid;
63 | border-top: 1px solid;
64 | }
65 |
66 | td.missing-score,
67 | td.right-score,
68 | td.wrong-score {
69 | border-bottom: 1px solid;
70 | border-right: 1px solid;
71 | border-top: 1px solid;
72 | text-align: right;
73 | }
74 |
75 | td.missing-label,
76 | td.missing-score {
77 | background: #C79810;
78 | border-bottom-color: #946500;
79 | border-left-color: #946500;
80 | border-top-color: #946500;
81 | }
82 |
83 | td.right-label,
84 | td.right-score {
85 | background: #6BBA70;
86 | border-bottom-color: #38873D;
87 | border-top-color: #38873D;
88 | }
89 |
90 | td.wrong-label,
91 | td.wrong-score {
92 | background: #D01F3C;
93 | border-bottom-color: #9D0009;
94 | border-right-color: #9D0009;
95 | border-top-color: #9D0009;
96 | }
97 |
--------------------------------------------------------------------------------
/css/print.css:
--------------------------------------------------------------------------------
1 | * {
2 | border-color: black;
3 | color: black;
4 | }
5 |
6 | fieldset {
7 | border-color: black;
8 | }
9 |
10 | input[type="radio"] {
11 | page-break-after: avoid;
12 | page-break-before: avoid;
13 | }
14 |
15 | input[type="submit"] {
16 | display: none;
17 | }
18 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JavaScript Quiz Library
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/js/Option.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * @param {string} option value
5 | * @param {string} Question uid
6 | */
7 | function Option(value, uid) {
8 | this.value = value;
9 | this.uid = uid;
10 | this.checked = false;
11 | }
12 |
13 |
14 | /**
15 | * Renders HTML.
16 | * @return {DOM Element}
17 | */
18 | Option.prototype.render = function() {
19 | var label = document.createElement("label"),
20 | option = document.createElement("input"),
21 | self = this;
22 |
23 | option.value = this.value;
24 | option.type = "radio";
25 | option.name = this.uid;
26 |
27 | option.addEventListener("change", function(e) {
28 | self.checked = this.checked;
29 | });
30 |
31 | label.appendChild(option);
32 | label.appendChild(document.createTextNode(option.value));
33 |
34 | return label;
35 | };
36 |
37 |
38 | /**
39 | * @return {string}
40 | */
41 | Option.prototype.getValue = function() {
42 | return this.value;
43 | };
44 |
45 |
46 | /**
47 | * @return {boolean}
48 | * ugly
49 | */
50 | Option.prototype.isSelected = function() {
51 | var choice = document.querySelector("input[name='" + this.uid + "']:checked");
52 |
53 | return choice ? choice.value == this.value : false;
54 | };
55 |
--------------------------------------------------------------------------------
/js/Question.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * @param {string} question to ask
5 | * @param {array} options to choose from
6 | * @param {integer} right option array index
7 | */
8 | function Question(question, options, rightOption) {
9 | this.question = question;
10 | this.rightOption = rightOption;
11 | this.uid = this._uid();
12 | this.options = this._createOptions(options);
13 |
14 | this.RNDR_RIGHT = "#6BBA70",
15 | this.RNDR_WRONG = "#D01F3C",
16 | this.RNDR_MISSING = "#C79810";
17 | }
18 |
19 |
20 | /**
21 | * @return {string} question id
22 | */
23 | Question.prototype._uid = function() {
24 | // https://stackoverflow.com/questions/3242324/javascript-dateobj-gettime-for-a-uid-is-the-length-not-fixed
25 | return "q" + Math.random().toString(36).substr(2,9);
26 | };
27 |
28 |
29 | /**
30 | * @param {array} options
31 | * @return {array} of Option objects
32 | */
33 | Question.prototype._createOptions = function(_options) {
34 | var options = [];
35 |
36 | for (var i = 0; i < _options.length; i += 1) {
37 | options[i] = new Option(_options[i], this.uid);
38 | }
39 |
40 | return options;
41 | }
42 |
43 |
44 | /**
45 | * @return {array}
46 | */
47 | Question.prototype.getOptions = function() {
48 | return this.options;
49 | };
50 |
51 |
52 | /**
53 | * @return {DOM Element}
54 | */
55 | Question.prototype.render = function(shuffle) {
56 | var fieldset = document.createElement("fieldset"),
57 | legend = document.createElement("legend"),
58 | self = this;
59 |
60 | fieldset.id = this.uid;
61 |
62 | if (shuffle) {
63 | this._shuffleOptions();
64 | }
65 |
66 | legend.innerHTML = this.question;
67 |
68 | fieldset.appendChild(legend);
69 |
70 | for (var i = 0; i < this.options.length; i += 1) {
71 | fieldset.appendChild(this.options[i].render());
72 | }
73 |
74 | return fieldset;
75 | };
76 |
77 |
78 | Question.prototype.renderMissing = function() {
79 | document.getElementById(this.uid).style.borderColor = this.RNDR_MISSING;
80 | };
81 |
82 |
83 | Question.prototype.renderRight = function(first_argument) {
84 | document.getElementById(this.uid).style.borderColor = this.RNDR_RIGHT;
85 | };
86 |
87 |
88 | Question.prototype.renderWrong = function() {
89 | document.getElementById(this.uid).style.borderColor = this.RNDR_WRONG;
90 | };
91 |
92 | /**
93 | * @param {Option}
94 | * @return {boolean}
95 | */
96 | Question.prototype.isRight = function(option) {
97 | return option.getValue() == this.options[this.rightOption].value;
98 | };
99 |
100 |
101 | /**
102 | * Shuffles the options.
103 | */
104 | Question.prototype._shuffleOptions = function() {
105 | var result = [],
106 | rightOption = this.options[this.rightOption].value; // obtain right option
107 |
108 | while (this.options.length) {
109 | var len = this.options.length,
110 | idx = parseInt(Math.random() * len); // find an index
111 |
112 | result.push(this.options.splice(idx, 1)[0]); // remove that item from array
113 |
114 | if (result[result.length - 1].value == rightOption) {
115 | this.rightOption = result.length - 1; //
116 | }
117 | }
118 |
119 | this.options = result; // switch arrays
120 | }
121 |
--------------------------------------------------------------------------------
/js/Quiz.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
4 | /**
5 | * Quiz
6 | * @param {string} name
7 | * @param {array} questions
8 | * @param {object} options
9 | *
10 | * options object supports these keys:
11 | * shuffle {boolean} should the questions be shuffled before rendered?
12 | */
13 | function Quiz(name, questions, options) {
14 | this.name = name;
15 | this.questions = questions;
16 | this.options = options || {};
17 | this.create();
18 | }
19 |
20 |
21 | Quiz.prototype.getName = function() {
22 | return this.name;
23 | }
24 |
25 |
26 | Quiz.prototype.setName = function(name) {
27 | this.name = name;
28 | return this.name;
29 | };
30 |
31 |
32 | Quiz.prototype.getQuestions = function() {
33 | return this.questions
34 | };
35 |
36 |
37 | Quiz.prototype.setQuestions = function(questions) {
38 | this.questions = questions;
39 | return this.questions;
40 | };
41 |
42 |
43 | Quiz.prototype.addQuestion = function(question) {
44 | return this.questions.push(question);
45 | };
46 |
47 |
48 | Quiz.prototype.removeQuestion = function(question) {
49 | console.info("Remove question from the quiz");
50 | return this.questions;
51 | };
52 |
53 |
54 | Quiz.prototype.create = function() {
55 | var form = document.createElement("form"),
56 | submit = document.createElement("input"),
57 | self = this;
58 |
59 | document.title = this.name;
60 | document.write("" + this.name + "
");
61 |
62 | submit.type = "submit";
63 | submit.value = "Submit quiz";
64 |
65 | form.addEventListener("submit", function(e) {
66 | e.preventDefault();
67 | self.submit();
68 | })
69 |
70 | for (var i in this.questions) {
71 | form.appendChild(this.questions[i].render(this.options.shuffle || false));
72 | }
73 |
74 | form.appendChild(submit);
75 | document.body.appendChild(form);
76 | };
77 |
78 |
79 | Quiz.prototype.submit = function() {
80 | var missing = 0,
81 | right = 0,
82 | wrong = 0;
83 |
84 | for (var q of this.getQuestions()) {
85 | var choice = null;
86 |
87 | // validate
88 | for (var o of q.getOptions()) {
89 | if (o.isSelected()) {
90 | choice = o;
91 | }
92 | }
93 |
94 | // evaluate
95 | if (!choice) { // skip evaluation
96 | q.renderMissing();
97 | missing += 1;
98 | continue;
99 | }
100 |
101 | if (!q.isRight(choice)) {
102 | q.renderWrong();
103 | wrong += 1;
104 | } else {
105 | q.renderRight();
106 | right += 1;
107 | }
108 | }
109 |
110 | // show result
111 | var result = new Result(missing, right, wrong).render();
112 | };
113 |
--------------------------------------------------------------------------------
/js/Result.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
4 | /**
5 | * @param {integer} missing
6 | * @param {integer} right
7 | * @param {integer} wrong
8 | */
9 | function Result(missing, right, wrong) {
10 | this.html = document.createElement("table");
11 |
12 | var labels = ["Missing", "Right", "Wrong"],
13 | tr = document.createElement("tr");
14 |
15 | for (var i = 0; i < arguments.length; i += 1) {
16 | var label = document.createElement("td"),
17 | score = document.createElement("td");
18 |
19 | label.className = labels[i].toLowerCase() + "-label";
20 | score.className = labels[i].toLowerCase() + "-score";
21 |
22 | label.innerHTML = labels[i];
23 | score.innerHTML = arguments[i];
24 |
25 | tr.appendChild(label);
26 | tr.appendChild(score);
27 | }
28 |
29 | this.html.appendChild(tr);
30 | }
31 |
32 |
33 | Result.prototype.render = function() {
34 | var old = document.getElementsByTagName("table")[0];
35 | if (old) {
36 | document.body.removeChild(old);
37 | }
38 |
39 | document.body.appendChild(this.html);
40 |
41 | return this;
42 | };
43 |
--------------------------------------------------------------------------------
/questions.js:
--------------------------------------------------------------------------------
1 | var questions = [
2 | new Question("What is the capital of the Great Britain?", ["Bristol", "London", "Newcastle"], 1),
3 | new Question("What is the capital of the Czech Republic?", ["Prague", "Bratislava", "Vienna", "Wroclaw"], 0),
4 | new Question("What is the capital of Germany?", ["Berlin", "Budapest", "Bonn", "Hamburg"], 0),
5 | new Question("What is the biggest state in the USA?", ["Alaska", "Texas", "California", "Montana"], 0)
6 | ];
7 |
--------------------------------------------------------------------------------