1 IriSP.Widgets.Quiz = function(player, config) { |
1 import Mustache from "mustache"; |
2 IriSP.Widgets.Widget.call(this, player, config); |
2 import quizStyles from "./Quiz.module.css"; |
3 } |
3 import jQuery from "jquery"; |
4 |
4 |
5 IriSP.Widgets.Quiz.prototype = new IriSP.Widgets.Widget(); |
5 const Quiz = function (ns) { |
6 |
6 return class extends ns.Widgets.Widget { |
7 IriSP.Widgets.Quiz.prototype.defaults = { |
7 constructor(player, config) { |
8 // annotation_type: "at_quiz", |
8 super(player, config); |
9 quiz_activated: true, |
9 } |
10 api_serializer: "ldt_annotate", |
10 |
11 analytics_api: "", |
11 static defaults = { |
12 api_method: "POST", |
12 // annotation_type: "at_quiz", |
13 user: "", |
13 quiz_activated: true, |
14 userid:"" |
14 api_serializer: "ldt_annotate", |
15 } |
15 analytics_api: "", |
16 |
16 api_method: "POST", |
17 IriSP.Widgets.Quiz.prototype.template = '<div class="Ldt-Quiz-Container">' |
17 user: "", |
18 + '<div class="Ldt-Quiz-Header">' |
18 userid: "", |
19 + ' <div class="Ldt-Quiz-Index"></div><div class="Ldt-Quiz-Score"></div>' |
19 }; |
20 + '</div>' |
20 |
21 + '<div class="Ldt-Quiz-Content">' |
21 static template = |
22 + ' <h1 class="Ldt-Quiz-Title">{{question}}</h1>' |
22 '<div class="Ldt-Quiz-Container">' + |
23 + ' <div class="Ldt-Quiz-Questions">' |
23 '<div class="Ldt-Quiz-Header">' + |
24 + ' </div>' |
24 ' <div class="Ldt-Quiz-Index"></div><div class="Ldt-Quiz-Score"></div>' + |
25 + '</div>' |
25 "</div>" + |
26 + '<div class="Ldt-Quiz-Footer">' |
26 '<div class="Ldt-Quiz-Content">' + |
27 + ' <div class="Ldt-Quiz-Votes">' |
27 ' <h1 class="Ldt-Quiz-Title">{{question}}</h1>' + |
28 + ' <span class="Ldt-Quiz-Votes-Question">Avez-vous trouvé cette question utile ?</span>' |
28 ' <div class="Ldt-Quiz-Questions">' + |
29 + ' <div class="Ldt-Quiz-Votes-Buttons">' |
29 " </div>" + |
30 + ' <div class="Ldt-Quiz-Vote-Skip-Block"><a href="#" class="Ldt-Quiz-Vote-Skip">Passer</a></div>' |
30 "</div>" + |
31 + ' <div><input type="button" value="Non" class="Ldt-Quiz-Vote-Useless" /></div>' |
31 '<div class="Ldt-Quiz-Footer">' + |
32 + ' <div><input type="button" value="Oui" class="Ldt-Quiz-Vote-Useful" /></div>' |
32 ' <div class="Ldt-Quiz-Votes">' + |
33 + ' </div>' |
33 ' <span class="Ldt-Quiz-Votes-Question">Avez-vous trouvé cette question utile ?</span>' + |
34 + ' </div>' |
34 ' <div class="Ldt-Quiz-Votes-Buttons">' + |
35 + ' <div class="Ldt-Quiz-Submit">' |
35 ' <div class="Ldt-Quiz-Vote-Skip-Block"><a href="#" class="Ldt-Quiz-Vote-Skip">Passer</a></div>' + |
36 + ' <div class="Ldt-Quiz-Submit-Button"><input type="button" value="Valider" /></div>' |
36 ' <div><input type="button" value="Non" class="Ldt-Quiz-Vote-Useless" /></div>' + |
37 + ' <div class="Ldt-Quiz-Submit-Skip-Link"><a href="#">Passer</a></div><div style="clear:both;"></div>' |
37 ' <div><input type="button" value="Oui" class="Ldt-Quiz-Vote-Useful" /></div>' + |
38 + ' </div>' |
38 " </div>" + |
39 + ' <div class="Ldt-Quiz-Result">Bonne réponse</div>' |
39 " </div>" + |
40 + '</div>' |
40 ' <div class="Ldt-Quiz-Submit">' + |
41 + '</div>'; |
41 ' <div class="Ldt-Quiz-Submit-Button"><input type="button" value="Valider" /></div>' + |
42 |
42 ' <div class="Ldt-Quiz-Submit-Skip-Link"><a href="#">Passer</a></div><div style="clear:both;"></div>' + |
43 IriSP.Widgets.Quiz.prototype.annotationTemplate = ''; |
43 " </div>" + |
44 |
44 ' <div class="Ldt-Quiz-Result">Bonne réponse</div>' + |
45 IriSP.Widgets.Quiz.prototype.update = function(annotation) { |
45 "</div>" + |
46 var _this = this; |
46 "</div>"; |
47 |
47 |
48 if (this.quiz_activated && |
48 static annotationTemplate = ""; |
49 this.correct[annotation.id] != 1 && |
49 |
50 this.correct[annotation.id] != 0) { |
50 update(annotation) { |
51 |
51 var _this = this; |
52 _this.quiz_displayed = true; |
52 |
53 |
53 if ( |
54 //Pause the current video |
54 this.quiz_activated && |
55 this.media.pause(); |
55 this.correct[annotation.id] != 1 && |
56 |
56 this.correct[annotation.id] != 0 |
57 this.annotation = annotation; |
57 ) { |
58 |
58 _this.quiz_displayed = true; |
59 var question = annotation.content.data.question; |
59 |
60 var answers = annotation.content.data.answers; |
60 //Pause the current video |
61 var resource = annotation.content.data.resource; |
61 this.media.pause(); |
62 |
62 |
63 $(".Ldt-Quiz-Votes").hide(); |
63 this.annotation = annotation; |
|
64 |
|
65 var question = annotation.content.data.question; |
|
66 var answers = annotation.content.data.answers; |
|
67 var resource = annotation.content.data.resource; |
|
68 |
|
69 $(".Ldt-Quiz-Votes").hide(); |
64 $(".Ldt-Pause-Add-Question").hide(); |
70 $(".Ldt-Pause-Add-Question").hide(); |
65 $(".Ldt-Quiz-Container .Ldt-Quiz-Title").html(question); |
71 $(".Ldt-Quiz-Container .Ldt-Quiz-Title").html(question); |
66 |
72 |
67 var i = 0; |
73 var i = 0; |
68 |
74 |
69 var score = Mustache.to_html('<span class="Ldt-Quiz-Correct-Answer">{{ correctness.0 }}</span> / <span class="Ldt-Quiz-Incorrect-Answer">{{ correctness.1 }}</span>', { correctness: this.globalScore() }); |
75 var score = Mustache.render( |
70 $(".Ldt-Quiz-Index").html(Mustache.to_html("Q{{index}}/{{total}}", { index: annotation.number + 1, |
76 '<span class="Ldt-Quiz-Correct-Answer">{{ correctness.0 }}</span> / <span class="Ldt-Quiz-Incorrect-Answer">{{ correctness.1 }}</span>', |
71 total: this.totalAmount })); |
77 { correctness: this.globalScore() } |
72 $(".Ldt-Quiz-Score").html(score); |
78 ); |
73 this.question = new IriSP.Widgets.UniqueChoiceQuestion(annotation); |
79 $(".Ldt-Quiz-Index").html( |
74 this.resource = new IriSP.Widgets.UniqueChoiceQuestion(resource); |
80 Mustache.render("Q{{index}}/{{total}}", { |
75 |
81 index: annotation.number + 1, |
76 if (annotation.content.data.type == "multiple_choice") { |
82 total: this.totalAmount, |
77 this.question = new IriSP.Widgets.MultipleChoiceQuestion(annotation); |
83 }) |
78 this.resource = new IriSP.Widgets.MultipleChoiceQuestion(resource); |
84 ); |
79 } |
85 $(".Ldt-Quiz-Score").html(score); |
80 else if (annotation.content.data.type == "unique_choice") { |
86 this.question = new ns.Widgets.UniqueChoiceQuestion(annotation); |
81 this.question = new IriSP.Widgets.UniqueChoiceQuestion(annotation); |
87 this.resource = new ns.Widgets.UniqueChoiceQuestion(resource); |
82 this.resource = new IriSP.Widgets.UniqueChoiceQuestion(resource); |
88 |
83 } |
89 if (annotation.content.data.type == "multiple_choice") { |
84 |
90 this.question = new ns.Widgets.MultipleChoiceQuestion(annotation); |
85 var output = ""; |
91 this.resource = new ns.Widgets.MultipleChoiceQuestion(resource); |
86 for (i = 0; i < answers.length; i++) { |
92 } else if (annotation.content.data.type == "unique_choice") { |
87 output += '<div class="quiz-question-block"><p>' + this.question.renderQuizTemplate(answers[i], i) + '<span class="quiz-question-label">'+ answers[i].content + '</span></p></div>'; |
93 this.question = new ns.Widgets.UniqueChoiceQuestion(annotation); |
88 } |
94 this.resource = new ns.Widgets.UniqueChoiceQuestion(resource); |
89 |
95 } |
90 |
96 |
91 var QR = ''; |
97 var output = ""; |
92 //If there is an attached resource, display it on the resources overlay |
98 for (i = 0; i < answers.length; i++) { |
93 if (resource != null) { |
99 output += |
94 QR = '<div class="quiz-resource-block" id="resource" >' + resource + '</div>'; |
100 '<div class="quiz-question-block"><p>' + |
95 }; |
101 this.question.renderQuizTemplate(answers[i], i) + |
96 $(".Ldt-Quiz-Questions").html(QR + output); |
102 '<span class="quiz-question-label">' + |
97 $(".Ldt-Quiz-Overlay").fadeIn(); |
103 answers[i].content + |
98 |
104 "</span></p></div>"; |
99 $(".Ldt-Quiz-Submit").fadeIn(); |
105 } |
100 |
106 |
101 //Let's automatically check the checkbox/radio if we click on the label |
107 var QR = ""; |
102 $(".quiz-question-label").click(function() { |
108 //If there is an attached resource, display it on the resources overlay |
103 var input = $(this).siblings("input"); |
109 if (resource != null) { |
104 if (input.prop('checked') && input.prop('type') == 'radio') { |
110 QR = |
105 // Already checked. Consider a double click on unique question as a validation. |
111 '<div class="quiz-resource-block" id="resource" >' + |
106 _this.answer(); |
112 resource + |
107 } else { |
113 "</div>"; |
108 input.prop('checked', !input.prop('checked')); |
114 } |
109 } |
115 $(".Ldt-Quiz-Questions").html(QR + output); |
110 }); |
116 $(".Ldt-Quiz-Overlay").fadeIn(); |
111 |
117 |
112 //In case we click on the first "Skip" link |
118 $(".Ldt-Quiz-Submit").fadeIn(); |
113 $(".Ldt-Quiz-Submit-Skip-Link").click({media: this.media}, function(event) { |
119 |
114 _this.hide(); |
120 //Let's automatically check the checkbox/radio if we click on the label |
115 _this.player.trigger("QuizCreator.skip"); |
121 $(".quiz-question-label").click(function () { |
116 event.data.media.play(); |
122 var input = $(this).siblings("input"); |
117 }); |
123 if (input.prop("checked") && input.prop("type") == "radio") { |
118 } |
124 // Already checked. Consider a double click on unique question as a validation. |
119 }; |
125 _this.answer(); |
120 |
126 } else { |
121 IriSP.Widgets.Quiz.prototype.hide = function() { |
127 input.prop("checked", !input.prop("checked")); |
122 var _this = this; |
128 } |
123 |
129 }); |
124 $(".Ldt-Quiz-Votes").hide(); |
130 |
125 $(".Ldt-Quiz-Overlay").hide(); |
131 //In case we click on the first "Skip" link |
126 $(".Ldt-Pause-Add-Question").hide(); |
132 $(".Ldt-Quiz-Submit-Skip-Link").click( |
127 _this.quiz_displayed = false; |
133 { media: this.media }, |
128 } |
134 function (event) { |
129 |
135 _this.hide(); |
130 IriSP.Widgets.Quiz.prototype.answer = function() { |
136 _this.player.trigger("QuizCreator.skip"); |
131 var _this = this; |
137 event.data.media.play(); |
132 |
138 } |
133 function insert_timecode_links (s) { |
139 ); |
|
140 } |
|
141 } |
|
142 |
|
143 hide() { |
|
144 var _this = this; |
|
145 |
|
146 $(".Ldt-Quiz-Votes").hide(); |
|
147 $(".Ldt-Quiz-Overlay").hide(); |
|
148 $(".Ldt-Pause-Add-Question").hide(); |
|
149 _this.quiz_displayed = false; |
|
150 } |
|
151 |
|
152 answer() { |
|
153 var _this = this; |
|
154 |
|
155 function insert_timecode_links(s) { |
134 return (s || "").replace(/\s(\d+:\d+)/, function (match, timecode) { |
156 return (s || "").replace(/\s(\d+:\d+)/, function (match, timecode) { |
135 return ' <a href="#t=' + (IriSP.timestamp2ms(timecode) / 1000) + '">' + timecode + '</a>'; |
157 return ( |
|
158 ' <a href="#t=' + |
|
159 ns.timestamp2ms(timecode) / 1000 + |
|
160 '">' + |
|
161 timecode + |
|
162 "</a>" |
|
163 ); |
136 }); |
164 }); |
137 }; |
165 } |
138 |
166 |
139 var answers = _this.annotation.content.data.answers; |
167 var answers = _this.annotation.content.data.answers; |
140 |
168 |
141 // Augment answers with the correct feedback |
169 // Augment answers with the correct feedback |
142 var i = 0; |
170 var i = 0; |
143 var wrong = 0; |
171 var wrong = 0; |
144 // Signature is an array giving the answers signature: 1 for checked, 0 for unchecked |
172 // Signature is an array giving the answers signature: 1 for checked, 0 for unchecked |
145 // We cannot simply store the right answer index, since there may be multiple-choice questions |
173 // We cannot simply store the right answer index, since there may be multiple-choice questions |
146 var signature = []; |
174 var signature = []; |
147 _this.$.find(".Ldt-Quiz-Question-Check").each( function (code) { |
175 _this.$.find(".Ldt-Quiz-Question-Check").each(function (code) { |
148 var checked = $(this).is(":checked"); |
176 var checked = $(this).is(":checked"); |
149 signature.push(checked ? 1 : 0); |
177 signature.push(checked ? 1 : 0); |
150 var ans = answers[i]; |
178 var ans = answers[i]; |
151 if ((ans.correct && !checked) |
179 if ((ans.correct && !checked) || (!ans.correct && checked)) { |
152 || (!ans.correct && checked)) { |
180 wrong += 1; |
153 wrong += 1; |
181 jQuery(this) |
154 IriSP.jQuery(this).parents(".quiz-question-block").append('<div class="quiz-question-feedback quiz-question-incorrect-feedback">'+ insert_timecode_links(ans.feedback) +'</div>'); |
182 .parents(".quiz-question-block") |
|
183 .append( |
|
184 '<div class="quiz-question-feedback quiz-question-incorrect-feedback">' + |
|
185 insert_timecode_links(ans.feedback) + |
|
186 "</div>" |
|
187 ); |
155 } else { |
188 } else { |
156 IriSP.jQuery(this).parents(".quiz-question-block").append('<div class="quiz-question-feedback quiz-question-correct-feedback">'+ insert_timecode_links(ans.feedback) +'</div>'); |
189 jQuery(this) |
|
190 .parents(".quiz-question-block") |
|
191 .append( |
|
192 '<div class="quiz-question-feedback quiz-question-correct-feedback">' + |
|
193 insert_timecode_links(ans.feedback) + |
|
194 "</div>" |
|
195 ); |
157 } |
196 } |
158 i++; |
197 i++; |
159 }); |
198 }); |
160 |
199 |
161 if (wrong) { |
200 if (wrong) { |
162 $(".Ldt-Quiz-Result").html("Mauvaise réponse"); |
201 $(".Ldt-Quiz-Result").html("Mauvaise réponse"); |
163 $(".Ldt-Quiz-Result").css({"background-color" : "red"}); |
202 $(".Ldt-Quiz-Result").css({ "background-color": "red" }); |
164 this.correct[this.annotation.id] = 0; |
203 this.correct[this.annotation.id] = 0; |
165 } else { |
204 } else { |
166 $(".Ldt-Quiz-Result").html("Bonne réponse !"); |
205 $(".Ldt-Quiz-Result").html("Bonne réponse !"); |
167 $(".Ldt-Quiz-Result").css({"background-color" : "green"}); |
206 $(".Ldt-Quiz-Result").css({ "background-color": "green" }); |
168 this.correct[this.annotation.id] = 1; |
207 this.correct[this.annotation.id] = 1; |
169 } |
208 } |
170 |
209 |
171 $(".Ldt-Quiz-Result").animate({height:"100%"},500, "linear", function() { |
210 $(".Ldt-Quiz-Result").animate( |
172 $(".Ldt-Quiz-Result").delay(2000).animate({ height:"0%" }, 500); |
211 { height: "100%" }, |
173 }); |
212 500, |
174 |
213 "linear", |
175 var question_number = this.annotation.number + 1; |
214 function () { |
176 var correctness = this.globalScore(); |
215 $(".Ldt-Quiz-Result").delay(2000).animate({ height: "0%" }, 500); |
177 var score = ""; |
216 } |
178 score += '<span class="Ldt-Quiz-Correct-Answer">' + correctness[0] +'</span> / <span class="Ldt-Quiz-Incorrect-Answer">' + correctness[1] + '</span>'; |
217 ); |
179 $(".Ldt-Quiz-Index").html("Q"+ question_number + "/" + this.totalAmount); |
218 |
180 $(".Ldt-Quiz-Score").html(score); |
219 var question_number = this.annotation.number + 1; |
181 |
220 var correctness = this.globalScore(); |
182 this.submit(this.user, this.userid, this.annotation.id, wrong ? 'wrong_answer' : 'right_answer', signature.join("")); |
221 var score = ""; |
183 |
222 score += |
184 //Hide the "Validate" button and display the UI dedicated to votes |
223 '<span class="Ldt-Quiz-Correct-Answer">' + |
185 $(".Ldt-Quiz-Submit").fadeOut(400, function () { |
224 correctness[0] + |
186 $(".Ldt-Quiz-Votes").show(); |
225 '</span> / <span class="Ldt-Quiz-Incorrect-Answer">' + |
187 }); |
226 correctness[1] + |
|
227 "</span>"; |
|
228 $(".Ldt-Quiz-Index").html("Q" + question_number + "/" + this.totalAmount); |
|
229 $(".Ldt-Quiz-Score").html(score); |
|
230 |
|
231 this.submit( |
|
232 this.user, |
|
233 this.userid, |
|
234 this.annotation.id, |
|
235 wrong ? "wrong_answer" : "right_answer", |
|
236 signature.join("") |
|
237 ); |
|
238 |
|
239 //Hide the "Validate" button and display the UI dedicated to votes |
|
240 $(".Ldt-Quiz-Submit").fadeOut(400, function () { |
|
241 $(".Ldt-Quiz-Votes").show(); |
|
242 }); |
|
243 } |
|
244 |
|
245 globalScore() { |
|
246 // Return 2 variables to know how many right and wrong answers there are |
|
247 var values = _.values(this.correct); |
|
248 var ok = values.filter(function (s) { |
|
249 return s == 1; |
|
250 }).length; |
|
251 var not_ok = values.filter(function (s) { |
|
252 return s == 0; |
|
253 }).length; |
|
254 return [ok, not_ok]; |
|
255 } |
|
256 |
|
257 refresh() { |
|
258 var _annotations = this.getWidgetAnnotations().sortBy(function ( |
|
259 _annotation |
|
260 ) { |
|
261 return _annotation.begin; |
|
262 }); |
|
263 |
|
264 var _this = this; |
|
265 |
|
266 _this.totalAmount = _annotations.length; |
|
267 _this.number = 0; |
|
268 _this.correct = {}; |
|
269 _this.keys = {}; |
|
270 |
|
271 _annotations.forEach(function (_a) { |
|
272 //Fix each annotation as "non-answered yet" |
|
273 _this.correct[_a.id] = -1; |
|
274 _this.keys[_this.number] = _a.id; |
|
275 _a.number = _this.number++; |
|
276 }); |
|
277 } |
|
278 |
|
279 draw() { |
|
280 var _this = this; |
|
281 _this.quiz_displayed = false; |
|
282 this.onMediaEvent("enter-annotation", function (annotation) { |
|
283 var an = _this.getWidgetAnnotations().filter(function (a) { |
|
284 return a === annotation; |
|
285 }); |
|
286 if (an.number === undefined) { |
|
287 _this.refresh(); |
|
288 } |
|
289 if (an.length) { |
|
290 _this.update(an[0]); |
|
291 } |
|
292 }); |
|
293 this.onMdpEvent("Quiz.activate", function () { |
|
294 _this.quiz_activated = true; |
|
295 }); |
|
296 |
|
297 this.onMdpEvent("Quiz.deactivate", function () { |
|
298 _this.quiz_activated = false; |
|
299 _this.hide(); |
|
300 }); |
|
301 |
|
302 this.onMdpEvent("Quiz.hide", function () { |
|
303 _this.hide(); |
|
304 }); |
|
305 |
|
306 this.onMdpEvent("Quiz.refresh", function () { |
|
307 _this.refresh(); |
|
308 }); |
|
309 |
|
310 this.onMediaEvent("pause", function () { |
|
311 if (!_this.quiz_displayed) { |
|
312 $(".Ldt-Pause-Add-Question").show(); |
|
313 } |
|
314 }); |
|
315 |
|
316 this.onMediaEvent("play", function () { |
|
317 $(".Ldt-Pause-Add-Question").hide(); |
|
318 }); |
|
319 |
|
320 // Add Ldt-Quiz-Overlay widget on top of video player |
|
321 _this.overlay = $("<div class='Ldt-Quiz-Overlay'></div>").appendTo( |
|
322 $("#" + _this.container) |
|
323 ); |
|
324 _this.PauseAddQuestion = $( |
|
325 "<div class='Ldt-Pause-Add-Question' title='Ajoutez une question !'>" |
|
326 ) |
|
327 .on("click", function () { |
|
328 _this.player.trigger("QuizCreator.create"); |
|
329 }) |
|
330 .appendTo($("#" + _this.container)); |
|
331 _this.overlay.html(this.template); |
|
332 |
|
333 $(".Ldt-Quiz-Overlay").hide(); |
|
334 |
|
335 $(".Ldt-Quiz-Submit input").click(function () { |
|
336 _this.answer(); |
|
337 }); |
|
338 |
|
339 //In case we click on the first "Skip" link |
|
340 $(".Ldt-Quiz-Submit-Skip-Link").click( |
|
341 { media: this.media }, |
|
342 function (event) { |
|
343 _this.submit( |
|
344 _this.user, |
|
345 _this.userid, |
|
346 _this.annotation.id, |
|
347 "skipped_answer", |
|
348 0 |
|
349 ); |
|
350 _this.hide(); |
|
351 _this.player.trigger("QuizCreator.skip"); |
|
352 event.data.media.play(); |
|
353 } |
|
354 ); |
|
355 |
|
356 $( |
|
357 '.Ldt-Quiz-Votes-Buttons input[type="button"], .Ldt-Quiz-Votes-Buttons a' |
|
358 ).click({ media: this.media }, function (event) { |
|
359 var vote_prop, vote_val; |
|
360 |
|
361 if ($(this).hasClass("Ldt-Quiz-Vote-Useful")) { |
|
362 vote_prop = "useful"; |
|
363 vote_val = 1; |
|
364 } else if ($(this).hasClass("Ldt-Quiz-Vote-Useless")) { |
|
365 vote_prop = "useless"; |
|
366 vote_val = -1; |
|
367 |
|
368 $(".Ldt-Ctrl-Quiz-Create") |
|
369 .addClass("button_highlight") |
|
370 .delay(5000) |
|
371 .queue(function () { |
|
372 $(this).removeClass("button_highlight").dequeue(); |
|
373 }); |
|
374 } else { |
|
375 vote_prop = "skipped_vote"; |
|
376 vote_val = 0; |
|
377 } |
|
378 |
|
379 _this.submit( |
|
380 _this.user, |
|
381 _this.userid, |
|
382 _this.annotation.id, |
|
383 vote_prop, |
|
384 vote_val |
|
385 ); |
|
386 |
|
387 //Resume the current video |
|
388 event.data.media.play(); |
|
389 |
|
390 _this.hide(); |
|
391 $(".Ldt-Pause-Add-Question").hide(); |
|
392 |
|
393 _this.player.trigger("QuizCreator.skip"); |
|
394 }); |
|
395 |
|
396 _this.refresh(); |
|
397 } |
|
398 }; |
188 }; |
399 }; |
189 |
400 |
190 IriSP.Widgets.Quiz.prototype.globalScore = function() { |
401 const UniqueChoiceQuestion = function (ns) { |
191 // Return 2 variables to know how many right and wrong answers there are |
402 return class extends ns.Widgets.Widget { |
192 var values = _.values(this.correct); |
403 constructor(annotation) { |
193 var ok = values.filter( function (s) { return s == 1; }).length; |
404 this.annotation = annotation; |
194 var not_ok = values.filter( function (s) { return s == 0; }).length; |
405 } |
195 return [ok, not_ok]; |
406 |
|
407 renderQuizTemplate(answer, identifier) { |
|
408 return ( |
|
409 '<input type="radio" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + |
|
410 identifier + |
|
411 '" name="question" data-question="' + |
|
412 identifier + |
|
413 '" value="' + |
|
414 identifier + |
|
415 '" />' |
|
416 ); |
|
417 } |
|
418 |
|
419 renderTemplate(answer, identifier) { |
|
420 var id = this.generateUid(); |
|
421 return ( |
|
422 '<input type="radio" id="' + |
|
423 id + |
|
424 '" class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + |
|
425 identifier + |
|
426 '" name="question" data-question="' + |
|
427 identifier + |
|
428 '" value="' + |
|
429 identifier + |
|
430 '" /><label for="' + |
|
431 id + |
|
432 '" title="Veuillez sélectionner la réponse correcte"></label>' |
|
433 ); |
|
434 } |
|
435 |
|
436 renderFullTemplate(answer, identifier) { |
|
437 var correct = answer && answer.correct ? "checked" : ""; |
|
438 var id = this.generateUid(); |
|
439 return ( |
|
440 '<input type="radio" id="' + |
|
441 id + |
|
442 '" ' + |
|
443 correct + |
|
444 ' class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + |
|
445 identifier + |
|
446 '" name="question" data-question="' + |
|
447 identifier + |
|
448 '" value="' + |
|
449 identifier + |
|
450 '" /><label for="' + |
|
451 id + |
|
452 '"></label>' |
|
453 ); |
|
454 } |
|
455 }; |
196 }; |
456 }; |
197 |
457 |
198 IriSP.Widgets.Quiz.prototype.refresh = function() { |
458 const MultipleChoiceQuestion = function (ns) { |
199 var _annotations = this.getWidgetAnnotations().sortBy(function(_annotation) { |
459 return class extends ns.Widgets.Widget { |
200 return _annotation.begin; |
460 constructor(annotation) { |
201 }); |
461 this.annotation = annotation; |
202 |
462 } |
203 var _this = this; |
463 |
204 |
464 renderQuizTemplate(answer, identifier) { |
205 _this.totalAmount = _annotations.length; |
465 return ( |
206 _this.number = 0; |
466 '<input type="checkbox" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + |
207 _this.correct = {}; |
467 identifier + |
208 _this.keys = {}; |
468 '" name="question[' + |
209 |
469 identifier + |
210 _annotations.forEach(function(_a) { |
470 ']" data-question="' + |
211 //Fix each annotation as "non-answered yet" |
471 identifier + |
212 _this.correct[_a.id] = -1; |
472 '" value="' + |
213 _this.keys[_this.number] = _a.id; |
473 identifier + |
214 _a.number = _this.number++; |
474 '" /> ' |
215 }); |
475 ); |
216 |
476 } |
217 } |
477 |
218 |
478 renderTemplate(answer, identifier) { |
219 IriSP.Widgets.Quiz.prototype.draw = function() { |
479 var id = this.generateUid(); |
220 var _this = this; |
480 return ( |
221 _this.quiz_displayed = false; |
481 '<input type="checkbox" id="' + |
222 this.onMediaEvent("enter-annotation", function (annotation) { |
482 id + |
223 var an = _this.getWidgetAnnotations().filter( function (a) { return a === annotation; }); |
483 '" class="quiz-question-edition Ldt-Quiz-Question-Check" name="question[' + |
224 if (an.number === undefined) { |
484 identifier + |
225 _this.refresh(); |
485 ']" data-question="' + |
226 } |
486 identifier + |
227 if (an.length) { |
487 '" value="' + |
228 _this.update(an[0]); |
488 identifier + |
|
489 '" /><label for="' + |
|
490 id + |
|
491 '" title="Veuillez sélectionner la ou les réponses correctes"></label>' |
|
492 ); |
|
493 } |
|
494 |
|
495 renderFullTemplate(answer, identifier) { |
|
496 var correct = answer && answer.correct ? "checked" : ""; |
|
497 var id = this.generateUid(); |
|
498 return ( |
|
499 '<input type="checkbox" id="' + |
|
500 id + |
|
501 '" ' + |
|
502 correct + |
|
503 ' class="quiz-question-edition Ldt-Quiz-Question-Check" name="question[' + |
|
504 identifier + |
|
505 ']" data-question="' + |
|
506 identifier + |
|
507 '" value="' + |
|
508 identifier + |
|
509 '" /><label for="' + |
|
510 id + |
|
511 '"></label> ' |
|
512 ); |
|
513 } |
|
514 |
|
515 submit(user, user_id, question, prop, val) { |
|
516 var _this = this; |
|
517 var _url = Mustache.render(this.analytics_api, { |
|
518 id: this.source.projectId, |
|
519 }), |
|
520 donnees = { |
|
521 username: user, |
|
522 useruuid: user_id, |
|
523 subject: question, |
|
524 property: prop, |
|
525 value: val, |
|
526 session: _this.session_id, |
229 }; |
527 }; |
230 }); |
528 |
231 this.onMdpEvent("Quiz.activate", function() { |
529 jQuery.ajax({ |
232 _this.quiz_activated = true; |
|
233 }); |
|
234 |
|
235 this.onMdpEvent("Quiz.deactivate", function() { |
|
236 _this.quiz_activated = false; |
|
237 _this.hide(); |
|
238 }); |
|
239 |
|
240 this.onMdpEvent("Quiz.hide", function() { |
|
241 _this.hide(); |
|
242 }); |
|
243 |
|
244 this.onMdpEvent("Quiz.refresh", function() { |
|
245 _this.refresh(); |
|
246 }); |
|
247 |
|
248 this.onMediaEvent("pause", function() { |
|
249 if (! _this.quiz_displayed) { |
|
250 $(".Ldt-Pause-Add-Question").show(); |
|
251 } |
|
252 }); |
|
253 |
|
254 this.onMediaEvent("play", function() { |
|
255 $(".Ldt-Pause-Add-Question").hide(); |
|
256 }); |
|
257 |
|
258 // Add Ldt-Quiz-Overlay widget on top of video player |
|
259 _this.overlay = $("<div class='Ldt-Quiz-Overlay'></div>").appendTo($('#' + _this.container)); |
|
260 _this.PauseAddQuestion = $("<div class='Ldt-Pause-Add-Question' title='Ajoutez une question !'>") |
|
261 .on("click", function() { _this.player.trigger("QuizCreator.create"); }) |
|
262 .appendTo($('#' + _this.container)); |
|
263 _this.overlay.html(this.template); |
|
264 |
|
265 $(".Ldt-Quiz-Overlay").hide(); |
|
266 |
|
267 $(".Ldt-Quiz-Submit input").click(function() { |
|
268 _this.answer(); |
|
269 }); |
|
270 |
|
271 //In case we click on the first "Skip" link |
|
272 $(".Ldt-Quiz-Submit-Skip-Link").click({ media: this.media }, function(event) { |
|
273 _this.submit(_this.user, _this.userid, _this.annotation.id, "skipped_answer", 0); |
|
274 _this.hide(); |
|
275 _this.player.trigger("QuizCreator.skip"); |
|
276 event.data.media.play(); |
|
277 }); |
|
278 |
|
279 $(".Ldt-Quiz-Votes-Buttons input[type=\"button\"], .Ldt-Quiz-Votes-Buttons a").click({media: this.media}, function(event) { |
|
280 var vote_prop, vote_val; |
|
281 |
|
282 if ($(this).hasClass("Ldt-Quiz-Vote-Useful")) { |
|
283 vote_prop = "useful"; |
|
284 vote_val = 1; |
|
285 } else if ($(this).hasClass("Ldt-Quiz-Vote-Useless")) { |
|
286 vote_prop = "useless"; |
|
287 vote_val = -1; |
|
288 |
|
289 $(".Ldt-Ctrl-Quiz-Create").addClass("button_highlight").delay(5000).queue(function() { |
|
290 $(this).removeClass("button_highlight").dequeue(); |
|
291 }); |
|
292 }else{ |
|
293 vote_prop = "skipped_vote"; |
|
294 vote_val = 0; |
|
295 } |
|
296 |
|
297 _this.submit(_this.user, _this.userid, _this.annotation.id, vote_prop, vote_val); |
|
298 |
|
299 //Resume the current video |
|
300 event.data.media.play(); |
|
301 |
|
302 _this.hide(); |
|
303 $(".Ldt-Pause-Add-Question").hide(); |
|
304 |
|
305 _this.player.trigger("QuizCreator.skip"); |
|
306 }); |
|
307 |
|
308 _this.refresh(); |
|
309 }; |
|
310 |
|
311 //Generates uid |
|
312 //source : http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript |
|
313 IriSP.Widgets.Widget.prototype.generateUid = function () { |
|
314 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { |
|
315 var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8); |
|
316 return v.toString(16); |
|
317 }); |
|
318 } |
|
319 |
|
320 //UniqueChoice Question |
|
321 IriSP.Widgets.UniqueChoiceQuestion = function(annotation) { |
|
322 this.annotation = annotation; |
|
323 } |
|
324 |
|
325 IriSP.Widgets.UniqueChoiceQuestion.prototype = new IriSP.Widgets.Widget(); |
|
326 |
|
327 IriSP.Widgets.UniqueChoiceQuestion.prototype.renderQuizTemplate = function(answer, identifier) { |
|
328 return '<input type="radio" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + identifier + '" name="question" data-question="' + identifier + '" value="' + identifier + '" />'; |
|
329 } |
|
330 |
|
331 IriSP.Widgets.UniqueChoiceQuestion.prototype.renderTemplate = function(answer, identifier) { |
|
332 var id = this.generateUid(); |
|
333 return '<input type="radio" id="' + id + '" class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier +'" name="question" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'" title="Veuillez sélectionner la réponse correcte"></label>'; |
|
334 } |
|
335 |
|
336 IriSP.Widgets.UniqueChoiceQuestion.prototype.renderFullTemplate = function(answer, identifier) { |
|
337 var correct = (answer && answer.correct) ? "checked" : ""; |
|
338 var id = this.generateUid(); |
|
339 return '<input type="radio" id="'+ id +'" '+ correct +' class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier +'" name="question" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'"></label>'; |
|
340 } |
|
341 |
|
342 |
|
343 //MultipleChoice Question |
|
344 IriSP.Widgets.MultipleChoiceQuestion = function(annotation) { |
|
345 this.annotation = annotation; |
|
346 } |
|
347 |
|
348 IriSP.Widgets.MultipleChoiceQuestion.prototype = new IriSP.Widgets.Widget(); |
|
349 |
|
350 IriSP.Widgets.MultipleChoiceQuestion.prototype.renderQuizTemplate = function(answer, identifier) { |
|
351 return '<input type="checkbox" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier + '" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /> '; |
|
352 } |
|
353 |
|
354 IriSP.Widgets.MultipleChoiceQuestion.prototype.renderTemplate = function(answer, identifier) { |
|
355 var id = this.generateUid(); |
|
356 return '<input type="checkbox" id="'+ id +'" class="quiz-question-edition Ldt-Quiz-Question-Check" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'" title="Veuillez sélectionner la ou les réponses correctes"></label>'; |
|
357 } |
|
358 |
|
359 IriSP.Widgets.MultipleChoiceQuestion.prototype.renderFullTemplate = function(answer, identifier) { |
|
360 var correct = (answer && answer.correct) ? "checked" : ""; |
|
361 var id = this.generateUid(); |
|
362 return '<input type="checkbox" id="'+ id +'" '+ correct +' class="quiz-question-edition Ldt-Quiz-Question-Check" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'"></label> '; |
|
363 } |
|
364 |
|
365 IriSP.Widgets.Quiz.prototype.submit = function(user,user_id,question,prop,val) { |
|
366 var _this = this; |
|
367 var _url = Mustache.to_html(this.analytics_api, {id: this.source.projectId}), |
|
368 donnees = { |
|
369 "username": user, |
|
370 "useruuid": user_id, |
|
371 "subject": question, |
|
372 "property": prop, |
|
373 "value": val, |
|
374 "session": _this.session_id |
|
375 }; |
|
376 |
|
377 IriSP.jQuery.ajax({ |
|
378 url: _url, |
530 url: _url, |
379 type: this.api_method, |
531 type: this.api_method, |
380 contentType: 'application/json', |
532 contentType: "application/json", |
381 data: JSON.stringify(donnees), |
533 data: JSON.stringify(donnees), |
382 success: function(_data) { |
534 success: function (_data) {}, |
|
535 error: function (_xhr, _error, _thrown) { |
|
536 ns.log("Error when sending annotation", _thrown); |
383 }, |
537 }, |
384 error: function(_xhr, _error, _thrown) { |
538 }); |
385 IriSP.log("Error when sending annotation", _thrown); |
539 } |
386 } |
540 }; |
387 }); |
541 }; |
388 } |
542 |
|
543 export { Quiz, UniqueChoiceQuestion, MultipleChoiceQuestion, quizStyles }; |