9d22b645e217e23246e487dbcc1560cec776bb54
[redakcja.git] / redakcja / static / edumed / js / edumed.js
1 (function() {
2   var $, Binding, EduModule, Excercise, Luki, PrawdaFalsz, Przyporzadkuj, Uporzadkuj, Wybor, Zastap, excercise,
3     __hasProp = Object.prototype.hasOwnProperty,
4     __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; };
5
6   $ = jQuery;
7
8   Binding = (function() {
9
10     function Binding(handler, element) {
11       this.handler = handler;
12       this.element = element;
13       $(this.element).data(this.handler, this);
14     }
15
16     return Binding;
17
18   })();
19
20   EduModule = (function(_super) {
21
22     __extends(EduModule, _super);
23
24     function EduModule(element) {
25       var _this = this;
26       EduModule.__super__.constructor.call(this, 'edumodule', element);
27       $("[name=teacher-toggle]").change(function(ev) {
28         if ($(ev.target).is(":checked")) {
29           return $(".teacher", _this.element).addClass("show");
30         } else {
31           return $(".teacher", _this.element).removeClass("show");
32         }
33       });
34     }
35
36     return EduModule;
37
38   })(Binding);
39
40   Excercise = (function(_super) {
41
42     __extends(Excercise, _super);
43
44     function Excercise(element) {
45       var _this = this;
46       Excercise.__super__.constructor.call(this, 'excercise', element);
47       $(".check", this.element).click(function() {
48         return _this.check();
49       });
50       $('.solutions', this.element).click(function() {
51         return _this.show_solutions();
52       });
53     }
54
55     Excercise.prototype.piece_correct = function(qpiece) {
56       return $(qpiece).removeClass('incorrect').addClass('correct');
57     };
58
59     Excercise.prototype.piece_incorrect = function(qpiece) {
60       return $(qpiece).removeClass('correct').addClass('incorrect');
61     };
62
63     Excercise.prototype.check = function() {
64       var score, scores,
65         _this = this;
66       scores = [];
67       $(".question", this.element).each(function(i, question) {
68         return scores.push(_this.check_question(question));
69       });
70       score = [0, 0];
71       $.each(scores, function(i, s) {
72         score[0] += s[0];
73         return score[1] += s[1];
74       });
75       return this.show_score(score);
76     };
77
78     Excercise.prototype.get_value_list = function(elem, data_key, numbers) {
79       var vl;
80       vl = $(elem).attr("data-" + data_key).split(/[ ,]+/).map($.trim);
81       if (numbers) {
82         vl = vl.map(function(x) {
83           return parseInt(x);
84         });
85       }
86       return vl;
87     };
88
89     Excercise.prototype.get_value_optional_list = function(elem, data_key) {
90       var mandat, opt, v, vals, _i, _len;
91       vals = this.get_value_list(elem, data_key);
92       mandat = [];
93       opt = [];
94       for (_i = 0, _len = vals.length; _i < _len; _i++) {
95         v = vals[_i];
96         if (v.slice(-1) === "?") {
97           opt.push(v.slice(0, -1));
98         } else {
99           mandat.push(v);
100         }
101       }
102       return [mandat, opt];
103     };
104
105     Excercise.prototype.show_score = function(score) {
106       return $(".message", this.element).text("Wynik: " + score[0] + " / " + score[1]);
107     };
108
109     Excercise.prototype.draggable_equal = function($draggable1, $draggable2) {
110       return false;
111     };
112
113     Excercise.prototype.draggable_accept = function($draggable, $droppable) {
114       var d, dropped, _i, _len;
115       dropped = $droppable.closest("ul, ol").find(".draggable");
116       for (_i = 0, _len = dropped.length; _i < _len; _i++) {
117         d = dropped[_i];
118         if (this.draggable_equal($draggable, $(d))) return false;
119       }
120       return true;
121     };
122
123     Excercise.prototype.draggable_dropped = function($draggable) {
124       return $draggable.append('<span class="close">x</span>');
125     };
126
127     Excercise.prototype.dragging = function(ismultiple, issortable) {
128       var _this = this;
129       return $(".question", this.element).each(function(i, question) {
130         var draggable_opts, self;
131         draggable_opts = {
132           revert: 'invalid',
133           helper: 'clone'
134         };
135         $(".draggable", question).draggable(draggable_opts);
136         self = _this;
137         return $(".placeholder", question).droppable({
138           accept: function(draggable) {
139             var $draggable, is_accepted;
140             $draggable = $(draggable);
141             is_accepted = true;
142             if (!$draggable.is(".draggable")) is_accepted = false;
143             if (is_accepted) {
144               is_accepted = self.draggable_accept($draggable, $(this));
145             }
146             if (is_accepted) {
147               $(this).addClass('accepting');
148             } else {
149               $(this).removeClass('accepting');
150             }
151             return is_accepted;
152           },
153           drop: function(ev, ui) {
154             var $added, added,
155               _this = this;
156             $(ev.target).removeClass('accepting');
157             added = $(ui.draggable).clone();
158             $added = added;
159             $added.data("original", ui.draggable);
160             if (!ismultiple) {
161               $(ui.draggable).addClass('disabled').draggable('disable');
162             }
163             $(ev.target).after(added);
164             if (!$(ev.target).hasClass('multiple')) $(ev.target).hide();
165             $added.append('<span class="remove">x</span>');
166             return $('.remove', added).click(function(ev) {
167               $added.prev(".placeholder:not(.multiple)").show();
168               if (!ismultiple) {
169                 $added.data('original').removeClass('disabled').draggable('enable');
170               }
171               return $(added).remove();
172             });
173           },
174           over: function(ev, ui) {
175             return $(ev.target).addClass('dragover');
176           },
177           out: function(ev, ui) {
178             return $(ev.target).removeClass('dragover');
179           }
180         });
181       });
182     };
183
184     return Excercise;
185
186   })(Binding);
187
188   Wybor = (function(_super) {
189
190     __extends(Wybor, _super);
191
192     function Wybor(element) {
193       Wybor.__super__.constructor.call(this, element);
194     }
195
196     Wybor.prototype.check_question = function(question) {
197       var all, good, solution,
198         _this = this;
199       all = 0;
200       good = 0;
201       solution = this.get_value_list(question, 'solution');
202       $(".question-piece", question).each(function(i, qpiece) {
203         var is_checked, piece_name, piece_no, should_be_checked;
204         piece_no = $(qpiece).attr('data-no');
205         piece_name = $(qpiece).attr('data-name');
206         if (piece_name) {
207           should_be_checked = solution.indexOf(piece_name) >= 0;
208         } else {
209           should_be_checked = solution.indexOf(piece_no) >= 0;
210         }
211         is_checked = $("input", qpiece).is(":checked");
212         if (should_be_checked) all += 1;
213         if (is_checked) {
214           if (should_be_checked) {
215             good += 1;
216             return _this.piece_correct(qpiece);
217           } else {
218             return _this.piece_incorrect(qpiece);
219           }
220         } else {
221           return $(qpiece).removeClass("correct,incorrect");
222         }
223       });
224       return [good, all];
225     };
226
227     Wybor.prototype.show_solutions = function() {};
228
229     return Wybor;
230
231   })(Excercise);
232
233   Uporzadkuj = (function(_super) {
234
235     __extends(Uporzadkuj, _super);
236
237     function Uporzadkuj(element) {
238       Uporzadkuj.__super__.constructor.call(this, element);
239       $('ol, ul', this.element).sortable({
240         items: "> li"
241       });
242     }
243
244     Uporzadkuj.prototype.check_question = function(question) {
245       var all, correct, pkt, pkts, positions, sorted, _ref;
246       positions = this.get_value_list(question, 'original', true);
247       sorted = positions.sort();
248       pkts = $('.question-piece', question);
249       correct = 0;
250       all = 0;
251       for (pkt = 0, _ref = pkts.length; 0 <= _ref ? pkt < _ref : pkt > _ref; 0 <= _ref ? pkt++ : pkt--) {
252         all += 1;
253         if (pkts.eq(pkt).data('pos') === sorted[pkt]) {
254           correct += 1;
255           this.piece_correct(pkts.eq(pkt));
256         } else {
257           this.piece_incorrect(pkts.eq(pkt));
258         }
259       }
260       return [correct, all];
261     };
262
263     return Uporzadkuj;
264
265   })(Excercise);
266
267   Luki = (function(_super) {
268
269     __extends(Luki, _super);
270
271     function Luki(element) {
272       Luki.__super__.constructor.call(this, element);
273       this.dragging(false, false);
274     }
275
276     Luki.prototype.check = function() {
277       var all, correct,
278         _this = this;
279       all = 0;
280       correct = 0;
281       $(".placeholder + .question-piece", this.element).each(function(i, qpiece) {
282         var $placeholder;
283         $placeholder = $(qpiece).prev(".placeholder");
284         if ($placeholder.data('solution') === $(qpiece).data('no')) {
285           _this.piece_correct(qpiece);
286           correct += 1;
287         } else {
288           _this.piece_incorrect(qpiece);
289         }
290         return all += 1;
291       });
292       return this.show_score([correct, all]);
293     };
294
295     return Luki;
296
297   })(Excercise);
298
299   Zastap = (function(_super) {
300
301     __extends(Zastap, _super);
302
303     function Zastap(element) {
304       var _this = this;
305       Zastap.__super__.constructor.call(this, element);
306       $(".paragraph", this.element).each(function(i, par) {
307         return _this.wrap_words($(par), $('<span class="placeholder zastap"/>'));
308       });
309       this.dragging(false, false);
310     }
311
312     Zastap.prototype.check = function() {
313       var all, correct,
314         _this = this;
315       all = 0;
316       correct = 0;
317       $(".paragraph", this.element).each(function(i, par) {
318         return $(".placeholder", par).each(function(j, qpiece) {
319           var $dragged, $qp, should_be_checked;
320           should_be_checked = false;
321           $qp = $(qpiece);
322           $dragged = $qp.next(".draggable");
323           if ($qp.data("solution")) {
324             if ($dragged && $qp.data("solution") === $dragged.data("no")) {
325               _this.piece_correct($dragged);
326               correct += 1;
327             }
328             return all += 1;
329           }
330         });
331       });
332       return this.show_score([correct, all]);
333     };
334
335     Zastap.prototype.wrap_words = function(element, wrapper) {
336       var chld, i, ignore, insertWrapped, j, len, space, wordb, _ref, _results;
337       ignore = /^[ \t.,:;()]+/;
338       insertWrapped = function(txt, elem) {
339         var nw;
340         nw = wrapper.clone();
341         return $(document.createTextNode(txt)).wrap(nw).parent().attr("data-original", txt).insertBefore(elem);
342       };
343       _results = [];
344       for (j = _ref = element.get(0).childNodes.length - 1; _ref <= 0 ? j <= 0 : j >= 0; _ref <= 0 ? j++ : j--) {
345         chld = element.get(0).childNodes[j];
346         if (chld.nodeType === document.TEXT_NODE) {
347           len = chld.textContent.length;
348           wordb = 0;
349           i = 0;
350           while (i < len) {
351             space = ignore.exec(chld.textContent.substr(i));
352             if (space != null) {
353               if (wordb < i) {
354                 insertWrapped(chld.textContent.substr(wordb, i - wordb), chld);
355               }
356               $(document.createTextNode(space[0])).insertBefore(chld);
357               i += space[0].length;
358               wordb = i;
359             } else {
360               i = i + 1;
361             }
362           }
363           if (wordb < len - 1) {
364             insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld);
365           }
366           _results.push($(chld).remove());
367         } else {
368           _results.push(void 0);
369         }
370       }
371       return _results;
372     };
373
374     return Zastap;
375
376   })(Excercise);
377
378   Przyporzadkuj = (function(_super) {
379
380     __extends(Przyporzadkuj, _super);
381
382     Przyporzadkuj.prototype.is_multiple = function() {
383       var qp, _i, _len, _ref;
384       _ref = $(".question-piece", this.element);
385       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
386         qp = _ref[_i];
387         if ($(qp).data('solution').split(/[ ,]+/).length > 1) return true;
388       }
389       return false;
390     };
391
392     function Przyporzadkuj(element) {
393       Przyporzadkuj.__super__.constructor.call(this, element);
394       this.multiple = this.is_multiple();
395       this.dragging(this.multiple, true);
396     }
397
398     Przyporzadkuj.prototype.draggable_equal = function(d1, d2) {
399       return d1.data("no") === d2.data("no");
400     };
401
402     Przyporzadkuj.prototype.check_question = function(question) {
403       var all, all_multiple, count, mandatory, optional, pn, pred, qp, v, _i, _j, _len, _len2, _ref, _ref2;
404       count = 0;
405       all = 0;
406       all_multiple = 0;
407       _ref = $(".predicate .question-piece", question);
408       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
409         qp = _ref[_i];
410         pred = $(qp).closest("[data-predicate]");
411         v = this.get_value_optional_list(qp, 'solution');
412         mandatory = v[0];
413         optional = v[1];
414         all_multiple += mandatory.length + optional.length;
415         pn = pred.data('predicate');
416         if (mandatory.indexOf(pn) >= 0 || optional.indexOf(pn) >= 0) {
417           count += 1;
418           this.piece_correct(qp);
419         } else {
420           this.piece_incorrect(qp);
421         }
422         all += 1;
423       }
424       if (this.multiple) {
425         _ref2 = $(".subject .question-piece", question);
426         for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
427           qp = _ref2[_j];
428           v = this.get_value_optional_list(qp, 'solution');
429           mandatory = v[0];
430           optional = v[1];
431           all_multiple += mandatory.length + optional.length;
432         }
433         return [count, all_multiple];
434       } else {
435         return [count, all];
436       }
437     };
438
439     return Przyporzadkuj;
440
441   })(Excercise);
442
443   PrawdaFalsz = (function(_super) {
444
445     __extends(PrawdaFalsz, _super);
446
447     function PrawdaFalsz(element) {
448       var qp, _i, _len, _ref;
449       PrawdaFalsz.__super__.constructor.call(this, element);
450       _ref = $(".question-piece", this.element);
451       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
452         qp = _ref[_i];
453         $(".true", qp).click(function(ev) {
454           ev.preventDefault();
455           $(this).closest(".question-piece").data("value", "true");
456           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
457         });
458         $(".false", qp).click(function(ev) {
459           ev.preventDefault();
460           $(this).closest(".question-piece").data("value", "false");
461           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
462         });
463       }
464     }
465
466     PrawdaFalsz.prototype.check_question = function() {
467       var all, good, qp, _i, _len, _ref;
468       all = 0;
469       good = 0;
470       _ref = $(".question-piece", this.element);
471       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
472         qp = _ref[_i];
473         if ($(qp).data("solution").toString() === $(qp).data("value")) {
474           good += 1;
475           this.piece_correct(qp);
476         } else {
477           this.piece_incorrect(qp);
478         }
479         all += 1;
480       }
481       return [good, all];
482     };
483
484     return PrawdaFalsz;
485
486   })(Excercise);
487
488   excercise = function(ele) {
489     var cls, es;
490     es = {
491       wybor: Wybor,
492       uporzadkuj: Uporzadkuj,
493       luki: Luki,
494       zastap: Zastap,
495       przyporzadkuj: Przyporzadkuj,
496       prawdafalsz: PrawdaFalsz
497     };
498     cls = es[$(ele).attr('data-type')];
499     return new cls(ele);
500   };
501
502   window.edumed = {
503     'EduModule': EduModule
504   };
505
506   $(document).ready(function() {
507     new EduModule($("#book-text"));
508     return $(".excercise").each(function(i, el) {
509       return excercise(this);
510     });
511   });
512
513 }).call(this);