Exercises: retry implied on move; add handlers to sortable
[edumed.git] / catalogue / static / catalogue / js / edumed.js
1 // Generated by CoffeeScript 1.3.3
2 (function() {
3   var $, Binding, EduModule, Exercise, Luki, PrawdaFalsz, Przyporzadkuj, Uporzadkuj, Wybor, Zastap, exercise,
4     __hasProp = {}.hasOwnProperty,
5     __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
6
7   $ = jQuery;
8
9   Binding = (function() {
10
11     function Binding(handler, element) {
12       this.handler = handler;
13       this.element = element;
14       $(this.element).data(this.handler, this);
15     }
16
17     return Binding;
18
19   })();
20
21   EduModule = (function(_super) {
22
23     __extends(EduModule, _super);
24
25     function EduModule(element) {
26       EduModule.__super__.constructor.call(this, 'edumodule', element);
27     }
28
29     return EduModule;
30
31   })(Binding);
32
33   Exercise = (function(_super) {
34
35     __extends(Exercise, _super);
36
37     function Exercise(element) {
38       var _this = this;
39       Exercise.__super__.constructor.call(this, 'exercise', element);
40       $(this.element).data("exercise-html", $(this.element).html());
41       $(".check", this.element).click(function(ev) {
42         _this.check();
43         $(ev.target).next(".retry").show();
44         return $(ev.target).hide();
45       });
46       $(".retry", this.element).click(function(ev) {
47         return _this.retry();
48       });
49       $('.solutions', this.element).click(function() {
50         _this.show_solutions();
51         return $(".comment", _this.element).show();
52       });
53       $('.reset', this.element).click(function() {
54         return _this.reset();
55       });
56     }
57
58     Exercise.prototype.retry = function() {
59       $(".correct, .incorrect", this.element).removeClass("correct incorrect");
60       $(".check", this.element).show();
61       return $(".retry", this.element).hide();
62     };
63
64     Exercise.prototype.reset = function() {
65       $(this.element).html($(this.element).data('exercise-html'));
66       return exercise(this.element);
67     };
68
69     Exercise.prototype.piece_correct = function(qpiece) {
70       return $(qpiece).removeClass('incorrect').addClass('correct');
71     };
72
73     Exercise.prototype.piece_incorrect = function(qpiece) {
74       return $(qpiece).removeClass('correct').addClass('incorrect');
75     };
76
77     Exercise.prototype.check = function() {
78       var score, scores,
79         _this = this;
80       scores = [];
81       $(".question", this.element).each(function(i, question) {
82         return scores.push(_this.check_question(question));
83       });
84       score = [0, 0];
85       $.each(scores, function(i, s) {
86         score[0] += s[0];
87         return score[1] += s[1];
88       });
89       return this.show_score(score);
90     };
91
92     Exercise.prototype.show_solutions = function() {
93       var _this = this;
94       this.reset();
95       return $(".question", this.element).each(function(i, question) {
96         return _this.solve_question(question);
97       });
98     };
99
100     Exercise.prototype.get_value_list = function(elem, data_key, numbers) {
101       var vl;
102       vl = $(elem).attr("data-" + data_key).split(/[ ,]+/).map($.trim);
103       if (numbers) {
104         vl = vl.map(function(x) {
105           return parseInt(x);
106         });
107       }
108       return vl;
109     };
110
111     Exercise.prototype.get_value_optional_list = function(elem, data_key) {
112       var mandat, opt, v, vals, _i, _len;
113       vals = this.get_value_list(elem, data_key);
114       mandat = [];
115       opt = [];
116       for (_i = 0, _len = vals.length; _i < _len; _i++) {
117         v = vals[_i];
118         if (v.slice(-1) === "?") {
119           opt.push(v.slice(0, -1));
120         } else {
121           mandat.push(v);
122         }
123       }
124       return [mandat, opt];
125     };
126
127     Exercise.prototype.show_score = function(score) {
128       return $(".message", this.element).text("Wynik: " + score[0] + " / " + score[1]);
129     };
130
131     Exercise.prototype.draggable_equal = function($draggable1, $draggable2) {
132       return false;
133     };
134
135     Exercise.prototype.draggable_accept = function($draggable, $droppable) {
136       var d, dropped, _i, _len;
137       dropped = $droppable.closest("ul, ol").find(".draggable");
138       for (_i = 0, _len = dropped.length; _i < _len; _i++) {
139         d = dropped[_i];
140         if (this.draggable_equal($draggable, $(d))) {
141           return false;
142         }
143       }
144       return true;
145     };
146
147     Exercise.prototype.draggable_move = function($draggable, $placeholder, ismultiple) {
148       var $added,
149         _this = this;
150       $added = $draggable.clone();
151       $added.data("original", $draggable.get(0));
152       if (!ismultiple) {
153         $draggable.addClass('disabled').draggable('disable');
154       }
155       $placeholder.after($added);
156       if (!$placeholder.hasClass('multiple')) {
157         $placeholder.hide();
158       }
159       if ($added.is(".add-li")) {
160         $added.wrap("<li/>");
161       }
162       $added.append('<span class="remove">x</span><div class="clr"></div>');
163       return $('.remove', $added).click(function(ev) {
164         if (!ismultiple) {
165           $($added.data('original')).removeClass('disabled').draggable('enable');
166         }
167         if ($added.is(".add-li")) {
168           $added = $added.closest('li');
169         }
170         $added.prev(".placeholder:not(.multiple)").show();
171         return $added.remove();
172       });
173     };
174
175     Exercise.prototype.dragging = function(ismultiple, issortable) {
176       var _this = this;
177       return $(".question", this.element).each(function(i, question) {
178         var draggable_opts, self;
179         draggable_opts = {
180           revert: 'invalid',
181           helper: 'clone',
182           start: _this.retry
183         };
184         $(".draggable", question).draggable(draggable_opts);
185         self = _this;
186         return $(".placeholder", question).droppable({
187           accept: function(draggable) {
188             var $draggable, is_accepted;
189             $draggable = $(draggable);
190             is_accepted = true;
191             if (!$draggable.is(".draggable")) {
192               is_accepted = false;
193             }
194             if (is_accepted) {
195               is_accepted = self.draggable_accept($draggable, $(this));
196             }
197             if (is_accepted) {
198               $(this).addClass('accepting');
199             } else {
200               $(this).removeClass('accepting');
201             }
202             return is_accepted;
203           },
204           drop: function(ev, ui) {
205             $(ev.target).removeClass('accepting dragover');
206             return _this.draggable_move($(ui.draggable), $(ev.target), ismultiple);
207           },
208           over: function(ev, ui) {
209             return $(ev.target).addClass('dragover');
210           },
211           out: function(ev, ui) {
212             return $(ev.target).removeClass('dragover');
213           }
214         });
215       });
216     };
217
218     return Exercise;
219
220   })(Binding);
221
222   Wybor = (function(_super) {
223
224     __extends(Wybor, _super);
225
226     function Wybor(element) {
227       Wybor.__super__.constructor.call(this, element);
228       $(".question-piece input", element).change(this.retry);
229     }
230
231     Wybor.prototype.check_question = function(question) {
232       var all, good, solution,
233         _this = this;
234       all = 0;
235       good = 0;
236       solution = this.get_value_list(question, 'solution');
237       $(".question-piece", question).each(function(i, qpiece) {
238         var is_checked, piece_name, piece_no, should_be_checked;
239         piece_no = $(qpiece).attr('data-no');
240         piece_name = $(qpiece).attr('data-name');
241         if (piece_name) {
242           should_be_checked = solution.indexOf(piece_name) >= 0;
243         } else {
244           should_be_checked = solution.indexOf(piece_no) >= 0;
245         }
246         is_checked = $("input", qpiece).is(":checked");
247         if (should_be_checked) {
248           all += 1;
249         }
250         if (is_checked) {
251           if (should_be_checked) {
252             good += 1;
253             return _this.piece_correct(qpiece);
254           } else {
255             return _this.piece_incorrect(qpiece);
256           }
257         } else {
258           return $(qpiece).removeClass("correct,incorrect");
259         }
260       });
261       return [good, all];
262     };
263
264     Wybor.prototype.solve_question = function(question) {
265       var solution,
266         _this = this;
267       solution = this.get_value_list(question, 'solution');
268       return $(".question-piece", question).each(function(i, qpiece) {
269         var piece_name, piece_no, should_be_checked;
270         piece_no = $(qpiece).attr('data-no');
271         piece_name = $(qpiece).attr('data-name');
272         if (piece_name) {
273           should_be_checked = solution.indexOf(piece_name) >= 0;
274         } else {
275           should_be_checked = solution.indexOf(piece_no) >= 0;
276         }
277         console.log("check " + $("input[type=checkbox]", qpiece).attr("id") + " -> " + should_be_checked);
278         return $("input[type=checkbox],input[type=radio]", qpiece).prop('checked', should_be_checked);
279       });
280     };
281
282     return Wybor;
283
284   })(Exercise);
285
286   Uporzadkuj = (function(_super) {
287
288     __extends(Uporzadkuj, _super);
289
290     function Uporzadkuj(element) {
291       Uporzadkuj.__super__.constructor.call(this, element);
292       $('ol, ul', this.element).sortable({
293         items: "> li",
294         start: this.retry
295       });
296     }
297
298     Uporzadkuj.prototype.check_question = function(question) {
299       var all, correct, pkt, pkts, positions, sorted, _i, _ref;
300       positions = this.get_value_list(question, 'original', true);
301       sorted = positions.sort();
302       pkts = $('.question-piece', question);
303       correct = 0;
304       all = 0;
305       for (pkt = _i = 0, _ref = pkts.length; 0 <= _ref ? _i < _ref : _i > _ref; pkt = 0 <= _ref ? ++_i : --_i) {
306         all += 1;
307         if (pkts.eq(pkt).data('pos') === sorted[pkt]) {
308           correct += 1;
309           this.piece_correct(pkts.eq(pkt));
310         } else {
311           this.piece_incorrect(pkts.eq(pkt));
312         }
313       }
314       return [correct, all];
315     };
316
317     Uporzadkuj.prototype.solve_question = function(question) {
318       var p, parent, pkts, positions, sorted, _i, _len, _results;
319       positions = this.get_value_list(question, 'original', true);
320       sorted = positions.sort();
321       pkts = $('.question-piece', question);
322       pkts.sort(function(a, b) {
323         var q, w;
324         q = $(a).data('pos');
325         w = $(b).data('pos');
326         if (q < w) {
327           return 1;
328         }
329         if (q > w) {
330           return -1;
331         }
332         return 0;
333       });
334       parent = pkts.eq(0).parent();
335       _results = [];
336       for (_i = 0, _len = pkts.length; _i < _len; _i++) {
337         p = pkts[_i];
338         _results.push(parent.prepend(p));
339       }
340       return _results;
341     };
342
343     return Uporzadkuj;
344
345   })(Exercise);
346
347   Luki = (function(_super) {
348
349     __extends(Luki, _super);
350
351     function Luki(element) {
352       Luki.__super__.constructor.call(this, element);
353       this.dragging(false, false);
354     }
355
356     Luki.prototype.check = function() {
357       var all, correct,
358         _this = this;
359       all = 0;
360       correct = 0;
361       $(".placeholder + .question-piece", this.element).each(function(i, qpiece) {
362         var $placeholder;
363         $placeholder = $(qpiece).prev(".placeholder");
364         if ($placeholder.data('solution') === $(qpiece).data('no')) {
365           _this.piece_correct(qpiece);
366           correct += 1;
367         } else {
368           _this.piece_incorrect(qpiece);
369         }
370         return all += 1;
371       });
372       return this.show_score([correct, all]);
373     };
374
375     Luki.prototype.solve_question = function(question) {
376       var _this = this;
377       return $(".placeholder", question).each(function(i, placeholder) {
378         var $qp;
379         $qp = $(".question-piece[data-no=" + $(placeholder).data('solution') + "]", question);
380         return _this.draggable_move($qp, $(placeholder), false);
381       });
382     };
383
384     return Luki;
385
386   })(Exercise);
387
388   Zastap = (function(_super) {
389
390     __extends(Zastap, _super);
391
392     function Zastap(element) {
393       var _this = this;
394       Zastap.__super__.constructor.call(this, element);
395       $(".paragraph", this.element).each(function(i, par) {
396         return _this.wrap_words($(par), $('<span class="placeholder zastap"/>'));
397       });
398       this.dragging(false, false);
399     }
400
401     Zastap.prototype.check = function() {
402       var all, correct,
403         _this = this;
404       all = 0;
405       correct = 0;
406       $(".paragraph", this.element).each(function(i, par) {
407         return $(".placeholder", par).each(function(j, qpiece) {
408           var $dragged, $qp;
409           $qp = $(qpiece);
410           $dragged = $qp.next(".draggable");
411           if ($qp.data("solution")) {
412             if ($dragged && $qp.data("solution") === $dragged.data("no")) {
413               _this.piece_correct($dragged);
414               correct += 1;
415             }
416             return all += 1;
417           }
418         });
419       });
420       return this.show_score([correct, all]);
421     };
422
423     Zastap.prototype.show_solutions = function() {
424       var _this = this;
425       this.reset();
426       return $(".paragraph", this.element).each(function(i, par) {
427         return $(".placeholder[data-solution]", par).each(function(j, qpiece) {
428           var $dr, $qp;
429           $qp = $(qpiece);
430           $dr = $(".draggable[data-no=" + $qp.data('solution') + "]", _this.element);
431           return _this.draggable_move($dr, $qp, false);
432         });
433       });
434     };
435
436     Zastap.prototype.wrap_words = function(element, wrapper) {
437       var chld, i, ignore, insertWrapped, j, len, space, wordb, _i, _ref, _results;
438       ignore = /^[ \t.,:;()]+/;
439       insertWrapped = function(txt, elem) {
440         var nw;
441         nw = wrapper.clone();
442         return $(document.createTextNode(txt)).wrap(nw).parent().attr("data-original", txt).insertBefore(elem);
443       };
444       _results = [];
445       for (j = _i = _ref = element.get(0).childNodes.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; j = _ref <= 0 ? ++_i : --_i) {
446         chld = element.get(0).childNodes[j];
447         if (chld.nodeType === document.TEXT_NODE) {
448           len = chld.textContent.length;
449           wordb = 0;
450           i = 0;
451           while (i < len) {
452             space = ignore.exec(chld.textContent.substr(i));
453             if (space != null) {
454               if (wordb < i) {
455                 insertWrapped(chld.textContent.substr(wordb, i - wordb), chld);
456               }
457               $(document.createTextNode(space[0])).insertBefore(chld);
458               i += space[0].length;
459               wordb = i;
460             } else {
461               i = i + 1;
462             }
463           }
464           if (wordb < len - 1) {
465             insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld);
466           }
467           _results.push($(chld).remove());
468         } else {
469           _results.push(void 0);
470         }
471       }
472       return _results;
473     };
474
475     return Zastap;
476
477   })(Exercise);
478
479   Przyporzadkuj = (function(_super) {
480
481     __extends(Przyporzadkuj, _super);
482
483     Przyporzadkuj.prototype.is_multiple = function() {
484       var qp, _i, _len, _ref;
485       _ref = $(".question-piece", this.element);
486       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
487         qp = _ref[_i];
488         if ($(qp).data('solution').split(/[ ,]+/).length > 1) {
489           return true;
490         }
491       }
492       return false;
493     };
494
495     function Przyporzadkuj(element) {
496       Przyporzadkuj.__super__.constructor.call(this, element);
497       this.multiple = this.is_multiple();
498       this.dragging(this.multiple, true);
499     }
500
501     Przyporzadkuj.prototype.draggable_equal = function(d1, d2) {
502       return d1.data("no") === d2.data("no");
503     };
504
505     Przyporzadkuj.prototype.check_question = function(question) {
506       var all, count, mandatory, minimum, optional, pn, pred, qp, v, _i, _j, _len, _len1, _ref, _ref1;
507       minimum = $(question).data("minimum");
508       count = 0;
509       all = 0;
510       if (!minimum) {
511         all = $(".subjects .question-piece", question).length;
512       }
513       _ref = $(".predicate [data-predicate]", question);
514       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
515         pred = _ref[_i];
516         pn = $(pred).attr('data-predicate');
517         if (minimum != null) {
518           all += minimum;
519         }
520         _ref1 = $(".question-piece", pred);
521         for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
522           qp = _ref1[_j];
523           v = this.get_value_optional_list(qp, 'solution');
524           mandatory = v[0];
525           optional = v[1];
526           if (mandatory.indexOf(pn) >= 0 || (minimum && optional.indexOf(pn) >= 0)) {
527             count += 1;
528             this.piece_correct(qp);
529           } else {
530             this.piece_incorrect(qp);
531           }
532         }
533       }
534       return [count, all];
535     };
536
537     Przyporzadkuj.prototype.solve_question = function(question) {
538       var $ph, $pr, draggables, m, mandatory, minimum, optional, qp, v, _i, _len, _ref, _results;
539       minimum = $(question).data("min");
540       _ref = $(".subject .question-piece", question);
541       _results = [];
542       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
543         qp = _ref[_i];
544         v = this.get_value_optional_list(qp, 'solution');
545         mandatory = v[0];
546         optional = v[1];
547         if (minimum) {
548           draggables = mandatory.count(optional).slice(0, minimum);
549         } else {
550           draggables = mandatory;
551         }
552         _results.push((function() {
553           var _j, _len1, _results1;
554           _results1 = [];
555           for (_j = 0, _len1 = draggables.length; _j < _len1; _j++) {
556             m = draggables[_j];
557             $pr = $(".predicate [data-predicate=" + m + "]", question);
558             $ph = $pr.find(".placeholder:visible");
559             _results1.push(this.draggable_move($(qp), $ph, this.multiple));
560           }
561           return _results1;
562         }).call(this));
563       }
564       return _results;
565     };
566
567     return Przyporzadkuj;
568
569   })(Exercise);
570
571   PrawdaFalsz = (function(_super) {
572
573     __extends(PrawdaFalsz, _super);
574
575     function PrawdaFalsz(element) {
576       var qp, _i, _len, _ref;
577       PrawdaFalsz.__super__.constructor.call(this, element);
578       _ref = $(".question-piece", this.element);
579       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
580         qp = _ref[_i];
581         $(".true", qp).click(function(ev) {
582           ev.preventDefault();
583           this.retry();
584           $(this).closest(".question-piece").data("value", "true");
585           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
586         });
587         $(".false", qp).click(function(ev) {
588           ev.preventDefault();
589           this.retry();
590           $(this).closest(".question-piece").data("value", "false");
591           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
592         });
593       }
594     }
595
596     PrawdaFalsz.prototype.check_question = function() {
597       var all, good, qp, _i, _len, _ref;
598       all = 0;
599       good = 0;
600       _ref = $(".question-piece", this.element);
601       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
602         qp = _ref[_i];
603         if ($(qp).data("solution").toString() === $(qp).data("value")) {
604           good += 1;
605           this.piece_correct(qp);
606         } else {
607           this.piece_incorrect(qp);
608         }
609         all += 1;
610       }
611       return [good, all];
612     };
613
614     PrawdaFalsz.prototype.show_solutions = function() {
615       var qp, _i, _len, _ref, _results;
616       this.reset();
617       _ref = $(".question-piece", this.element);
618       _results = [];
619       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
620         qp = _ref[_i];
621         if ($(qp).data('solution') === true) {
622           _results.push($(".true", qp).click());
623         } else {
624           _results.push($(".false", qp).click());
625         }
626       }
627       return _results;
628     };
629
630     return PrawdaFalsz;
631
632   })(Exercise);
633
634   exercise = function(ele) {
635     var cls, es;
636     es = {
637       wybor: Wybor,
638       uporzadkuj: Uporzadkuj,
639       luki: Luki,
640       zastap: Zastap,
641       przyporzadkuj: Przyporzadkuj,
642       prawdafalsz: PrawdaFalsz
643     };
644     cls = es[$(ele).attr('data-type')];
645     return new cls(ele);
646   };
647
648   window.edumed = {
649     'EduModule': EduModule
650   };
651
652   $(document).ready(function() {
653     new EduModule($("#book-text"));
654     return $(".exercise").each(function(i, el) {
655       return exercise(this);
656     });
657   });
658
659 }).call(this);