dragging overhaul
[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;
140             $draggable = $(draggable);
141             if (!$draggable.is(".draggable")) return false;
142             return self.draggable_accept($draggable, $(this));
143           },
144           drop: function(ev, ui) {
145             var $added, added,
146               _this = this;
147             added = $(ui.draggable).clone();
148             $added = added;
149             $added.data("original", ui.draggable);
150             if (!ismultiple) {
151               $(ui.draggable).addClass('disabled').draggable('disable');
152             }
153             $(ev.target).after(added);
154             if (!$(ev.target).hasClass('multiple')) $(ev.target).hide();
155             $added.append('<span class="remove">x</span>');
156             return $('.remove', added).click(function(ev) {
157               $added.prev(".placeholder:not(.multiple)").show();
158               if (!ismultiple) {
159                 $added.data('original').removeClass('disabled').draggable('enable');
160               }
161               return $(added).remove();
162             });
163           }
164         });
165       });
166     };
167
168     return Excercise;
169
170   })(Binding);
171
172   Wybor = (function(_super) {
173
174     __extends(Wybor, _super);
175
176     function Wybor(element) {
177       Wybor.__super__.constructor.call(this, element);
178     }
179
180     Wybor.prototype.check_question = function(question) {
181       var all, good, solution,
182         _this = this;
183       all = 0;
184       good = 0;
185       solution = this.get_value_list(question, 'solution');
186       $(".question-piece", question).each(function(i, qpiece) {
187         var is_checked, piece_name, piece_no, should_be_checked;
188         piece_no = $(qpiece).attr('data-no');
189         piece_name = $(qpiece).attr('data-name');
190         if (piece_name) {
191           should_be_checked = solution.indexOf(piece_name) >= 0;
192         } else {
193           should_be_checked = solution.indexOf(piece_no) >= 0;
194         }
195         is_checked = $("input", qpiece).is(":checked");
196         if (should_be_checked) all += 1;
197         if (is_checked) {
198           if (should_be_checked) {
199             good += 1;
200             return _this.piece_correct(qpiece);
201           } else {
202             return _this.piece_incorrect(qpiece);
203           }
204         } else {
205           return $(qpiece).removeClass("correct,incorrect");
206         }
207       });
208       return [good, all];
209     };
210
211     Wybor.prototype.show_solutions = function() {};
212
213     return Wybor;
214
215   })(Excercise);
216
217   Uporzadkuj = (function(_super) {
218
219     __extends(Uporzadkuj, _super);
220
221     function Uporzadkuj(element) {
222       Uporzadkuj.__super__.constructor.call(this, element);
223       $('ol, ul', this.element).sortable({
224         items: "> li"
225       });
226     }
227
228     Uporzadkuj.prototype.check_question = function(question) {
229       var all, correct, pkt, pkts, positions, sorted, _ref;
230       positions = this.get_value_list(question, 'original', true);
231       sorted = positions.sort();
232       pkts = $('.question-piece', question);
233       correct = 0;
234       all = 0;
235       for (pkt = 0, _ref = pkts.length; 0 <= _ref ? pkt < _ref : pkt > _ref; 0 <= _ref ? pkt++ : pkt--) {
236         all += 1;
237         if (pkts.eq(pkt).data('pos') === sorted[pkt]) {
238           correct += 1;
239           this.piece_correct(pkts.eq(pkt));
240         } else {
241           this.piece_incorrect(pkts.eq(pkt));
242         }
243       }
244       return [correct, all];
245     };
246
247     return Uporzadkuj;
248
249   })(Excercise);
250
251   Luki = (function(_super) {
252
253     __extends(Luki, _super);
254
255     function Luki(element) {
256       Luki.__super__.constructor.call(this, element);
257       this.dragging(false, false);
258     }
259
260     Luki.prototype.check = function() {
261       var all, correct,
262         _this = this;
263       all = 0;
264       correct = 0;
265       $(".placeholder + .question-piece", this.element).each(function(i, qpiece) {
266         var $placeholder;
267         $placeholder = $(qpiece).prev(".placeholder");
268         if ($placeholder.data('solution') === $(qpiece).data('no')) {
269           _this.piece_correct(qpiece);
270           correct += 1;
271         } else {
272           _this.piece_incorrect(qpiece);
273         }
274         return all += 1;
275       });
276       return this.show_score([correct, all]);
277     };
278
279     return Luki;
280
281   })(Excercise);
282
283   Zastap = (function(_super) {
284
285     __extends(Zastap, _super);
286
287     function Zastap(element) {
288       var _this = this;
289       Zastap.__super__.constructor.call(this, element);
290       $(".paragraph", this.element).each(function(i, par) {
291         var spans;
292         _this.wrap_words($(par), $('<span class="zastap question-piece"/>'));
293         spans = $("> span", par).attr("contenteditable", "true");
294         return spans.click(function(ev) {
295           spans.filter(':not(:empty)').removeClass('editing');
296           return $(ev.target).addClass('editing');
297         });
298       });
299     }
300
301     Zastap.prototype.check = function() {
302       var all, correct,
303         _this = this;
304       all = 0;
305       correct = 0;
306       $(".question-piece", this.element).each(function(i, qpiece) {
307         var should_be_changed, txt;
308         txt = $(qpiece).data('original');
309         should_be_changed = false;
310         if (!(txt != null)) {
311           txt = $(qpiece).data('solution');
312           should_be_changed = true;
313         }
314         if (!(txt != null)) return;
315         if (should_be_changed) all += 1;
316         if (txt !== $(qpiece).text()) {
317           return _this.piece_incorrect(qpiece);
318         } else {
319           if (should_be_changed) {
320             _this.piece_correct(qpiece);
321             return correct += 1;
322           }
323         }
324       });
325       return this.show_score([correct, all]);
326     };
327
328     Zastap.prototype.wrap_words = function(element, wrapper) {
329       var chld, i, ignore, insertWrapped, j, len, space, wordb, _ref, _results;
330       ignore = /^[ \t.,:;()]+/;
331       insertWrapped = function(txt, elem) {
332         var nw;
333         nw = wrapper.clone();
334         return $(document.createTextNode(txt)).wrap(nw).parent().attr("data-original", txt).insertBefore(elem);
335       };
336       _results = [];
337       for (j = _ref = element.get(0).childNodes.length - 1; _ref <= 0 ? j <= 0 : j >= 0; _ref <= 0 ? j++ : j--) {
338         chld = element.get(0).childNodes[j];
339         if (chld.nodeType === document.TEXT_NODE) {
340           len = chld.textContent.length;
341           wordb = 0;
342           i = 0;
343           while (i < len) {
344             space = ignore.exec(chld.textContent.substr(i));
345             if (space != null) {
346               if (wordb < i) {
347                 insertWrapped(chld.textContent.substr(wordb, i - wordb), chld);
348               }
349               $(document.createTextNode(space[0])).insertBefore(chld);
350               i += space[0].length;
351               wordb = i;
352             } else {
353               i = i + 1;
354             }
355           }
356           if (wordb < len - 1) {
357             insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld);
358           }
359           _results.push($(chld).remove());
360         } else {
361           _results.push(void 0);
362         }
363       }
364       return _results;
365     };
366
367     return Zastap;
368
369   })(Excercise);
370
371   Przyporzadkuj = (function(_super) {
372
373     __extends(Przyporzadkuj, _super);
374
375     Przyporzadkuj.prototype.is_multiple = function() {
376       var qp, _i, _len, _ref;
377       _ref = $(".question-piece", this.element);
378       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
379         qp = _ref[_i];
380         if ($(qp).data('solution').split(/[ ,]+/).length > 1) return true;
381       }
382       return false;
383     };
384
385     function Przyporzadkuj(element) {
386       Przyporzadkuj.__super__.constructor.call(this, element);
387       this.multiple = this.is_multiple();
388       this.dragging(this.multiple, true);
389     }
390
391     Przyporzadkuj.prototype.draggable_equal = function(d1, d2) {
392       return d1.data("no") === d2.data("no");
393     };
394
395     Przyporzadkuj.prototype.check_question = function(question) {
396       var all, all_multiple, count, mandatory, optional, pn, pred, qp, v, _i, _j, _len, _len2, _ref, _ref2;
397       count = 0;
398       all = 0;
399       all_multiple = 0;
400       _ref = $(".predicate .question-piece", question);
401       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
402         qp = _ref[_i];
403         pred = $(qp).closest("[data-predicate]");
404         v = this.get_value_optional_list(qp, 'solution');
405         mandatory = v[0];
406         optional = v[1];
407         all_multiple += mandatory.length + optional.length;
408         pn = pred.data('predicate');
409         if (mandatory.indexOf(pn) >= 0 || optional.indexOf(pn) >= 0) {
410           count += 1;
411           this.piece_correct(qp);
412         } else {
413           this.piece_incorrect(qp);
414         }
415         all += 1;
416       }
417       if (this.multiple) {
418         _ref2 = $(".subject .question-piece", question);
419         for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
420           qp = _ref2[_j];
421           v = this.get_value_optional_list(qp, 'solution');
422           mandatory = v[0];
423           optional = v[1];
424           all_multiple += mandatory.length + optional.length;
425         }
426         return [count, all_multiple];
427       } else {
428         return [count, all];
429       }
430     };
431
432     return Przyporzadkuj;
433
434   })(Excercise);
435
436   PrawdaFalsz = (function(_super) {
437
438     __extends(PrawdaFalsz, _super);
439
440     function PrawdaFalsz(element) {
441       var qp, _i, _len, _ref;
442       PrawdaFalsz.__super__.constructor.call(this, element);
443       _ref = $(".question-piece", this.element);
444       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
445         qp = _ref[_i];
446         $(".true", qp).click(function(ev) {
447           ev.preventDefault();
448           $(this).closest(".question-piece").data("value", "true");
449           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
450         });
451         $(".false", qp).click(function(ev) {
452           ev.preventDefault();
453           $(this).closest(".question-piece").data("value", "false");
454           return $(this).addClass('chosen').siblings('a').removeClass('chosen');
455         });
456       }
457     }
458
459     PrawdaFalsz.prototype.check_question = function() {
460       var all, good, qp, _i, _len, _ref;
461       all = 0;
462       good = 0;
463       _ref = $(".question-piece", this.element);
464       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
465         qp = _ref[_i];
466         if ($(qp).data("solution").toString() === $(qp).data("value")) {
467           good += 1;
468           this.piece_correct(qp);
469         } else {
470           this.piece_incorrect(qp);
471         }
472         all += 1;
473       }
474       return [good, all];
475     };
476
477     return PrawdaFalsz;
478
479   })(Excercise);
480
481   excercise = function(ele) {
482     var cls, es;
483     es = {
484       wybor: Wybor,
485       uporzadkuj: Uporzadkuj,
486       luki: Luki,
487       zastap: Zastap,
488       przyporzadkuj: Przyporzadkuj,
489       prawdafalsz: PrawdaFalsz
490     };
491     cls = es[$(ele).attr('data-type')];
492     return new cls(ele);
493   };
494
495   window.edumed = {
496     'EduModule': EduModule
497   };
498
499   $(document).ready(function() {
500     new EduModule($("#book-text"));
501     return $(".excercise").each(function(i, el) {
502       return excercise(this);
503     });
504   });
505
506 }).call(this);