ec1bcd0e02f3bc4b7cad4710fcffc0ee21eb1109
[redakcja.git] / redakcja / static / edumed / js / edumed.coffee
1
2 $ = jQuery
3
4 class Binding
5   constructor: (@handler, @element) ->
6     $(@element).data(@handler, this)
7
8
9 class EduModule extends Binding
10   constructor: (element) ->
11     super 'edumodule', element
12
13     $("[name=teacher-toggle]").change (ev) =>
14       if $(ev.target).is(":checked")
15         $(".teacher", @element).addClass "show"
16       else
17         $(".teacher", @element).removeClass "show"
18
19
20 class Excercise extends Binding
21   constructor: (element) ->
22     super 'excercise', element
23
24     $(".check", @element).click =>
25       @check()
26     $('.solutions', @element).click =>
27       @show_solutions()
28
29   piece_correct: (qpiece) ->
30     $(qpiece).removeClass('incorrect').addClass('correct')
31
32   piece_incorrect: (qpiece) ->
33     $(qpiece).removeClass('correct').addClass('incorrect')
34
35   check: ->
36     scores = []
37     $(".question", @element).each (i, question) =>
38       scores.push(@check_question question)
39
40     score = [0, 0]
41     $.each scores, (i, s) ->
42       score[0] += s[0]
43       score[1] += s[1]
44     @show_score(score)
45
46   get_value_list: (elem, data_key) ->
47     $(elem).data(data_key).split(',').map($.trim).map((x) -> parseInt(x))
48
49
50   show_score: (score) ->
51     $(".message", @element).text("Wynik: #{score[0]} / #{score[1]}")
52
53
54 class Wybor extends Excercise
55   constructor: (element) ->
56     super element
57
58
59   check_question: (question) ->
60     all = 0
61     good = 0
62     solution = @get_value_list(question, 'solution')
63     $(".question-piece", question).each (i, qpiece) =>
64       piece_no = parseInt $(qpiece).attr 'data-no'
65       should_be_checked = solution.indexOf(piece_no) >= 0
66       is_checked = $("input", qpiece).is(":checked")
67
68       if should_be_checked
69         all += 1
70
71       if is_checked
72         if should_be_checked
73           good += 1
74           @piece_correct qpiece
75         else
76           @piece_incorrect qpiece
77       else
78         $(qpiece).removeClass("correct,incorrect")
79
80     return [good, all]
81
82   show_solutions: ->
83
84
85 class Uporzadkuj extends Excercise
86   constructor: (element) ->
87     super element
88     $('ol, ul', @element).sortable({ items: "> li" })
89
90   check_question: (question) ->
91     positions = @get_value_list(question, 'original')
92     sorted = positions.sort()
93     pkts = $('.question-piece', question)
94
95     correct = 0
96     all = 0
97
98     for pkt in [0...pkts.length]
99       all +=1
100       if pkts.eq(pkt).data('pos') == sorted[pkt]
101         correct += 1
102         @piece_correct pkts.eq(pkt)
103       else
104         @piece_incorrect pkts.eq(pkt)
105     return [correct, all]
106
107
108 class Luki extends Excercise
109   constructor: (element) ->
110     super element
111
112   check: ->
113     all = 0
114     correct = 0
115     $(".question-piece", @element).each (i, qpiece) =>
116       if $(qpiece).data('solution') == $(qpiece).val()
117         @piece_correct qpiece
118         correct += 1
119       else
120         @piece_incorrect qpiece
121       all += 1
122
123     @show_score [correct, all]
124
125
126 class Zastap extends Excercise
127   constructor: (element) ->
128     super element
129     $(".paragraph", @element).each (i, par) =>
130       @wrap_words $(par), $('<span class="zastap question-piece"/>')
131       spans = $("> span", par).attr("contenteditable", "true")
132       spans.click (ev) =>
133         spans.filter(':not(:empty)').removeClass('editing')
134         $(ev.target).addClass('editing')
135
136
137   check: ->
138     all = 0
139     correct = 0
140     $(".question-piece", @element).each (i, qpiece) =>
141       txt = $(qpiece).data('original')
142       should_be_changed = false
143       if not txt?
144         txt = $(qpiece).data('solution')
145         should_be_changed = true
146       if not txt?
147         return
148
149       if should_be_changed
150         all += 1
151
152       if txt != $(qpiece).text()
153         @piece_incorrect qpiece
154       else
155         if should_be_changed
156           @piece_correct qpiece
157           correct += 1
158
159     @show_score [correct, all]
160
161   wrap_words: (element, wrapper) ->
162     # This function wraps each word of element in wrapper, but does not descend into child-tags of element.
163     # It doesn't wrap things between words (defined by ignore RE below). Warning - ignore must begin with ^
164     ignore = /^[ \t.,:;()]+/
165
166     insertWrapped = (txt, elem) ->
167       nw = wrapper.clone()
168       $(document.createTextNode(txt))
169         .wrap(nw).parent().attr("data-original", txt).insertBefore(elem)
170
171     for j in [element.get(0).childNodes.length-1..0]
172       chld = element.get(0).childNodes[j]
173       if chld.nodeType == document.TEXT_NODE
174         len = chld.textContent.length
175         wordb = 0
176         i = 0
177         while i < len
178           space = ignore.exec(chld.textContent.substr(i))
179           if space?
180             if wordb < i
181               insertWrapped(chld.textContent.substr(wordb, i-wordb), chld)
182
183             $(document.createTextNode(space[0])).insertBefore(chld)
184             i += space[0].length
185             wordb = i
186           else
187             i = i + 1
188         if wordb < len - 1
189           insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld)
190         $(chld).remove()
191
192
193 class Przyporzadkuj extends Excercise
194   constructor: (element) ->
195     super element
196
197     if @element.attr('multiple')?
198       @multiple = true
199     else
200       @multiple = false
201
202     $(".question", @element).each (i, question) =>
203       draggable_opts =
204         revert: 'invalid'
205         helper: if @multiple then "clone" else null
206
207       $(".draggable", question).draggable(draggable_opts)
208         .droppable({
209           accept: ".draggable"
210           })
211
212       $(".predicate .droppable", question).droppable
213         accept: ".draggable"
214         drop: (ev, ui) ->
215           is_multiple = ui.draggable.is(".multiple")
216
217           added = ui.draggable.clone()
218
219           added.attr('style', '')
220           $(this).append(added)
221           added.draggable(draggable_opts)
222
223           if not is_multiple
224             ui.draggable.remove()
225
226       $(".subject", question).droppable
227         accept: ".draggable"
228         drop: (ev, ui) ->
229           is_multiple = ui.draggable.is(".multiple")
230
231           added = ui.draggable.clone()
232
233           added.attr('style', '')
234           if not is_multiple
235             $(this).append(added)
236             added.draggable(draggable_opts)
237
238           ui.draggable.remove()
239
240
241
242
243 ##########
244
245 excercise = (ele) ->
246   es =
247     wybor: Wybor
248     uporzadkuj: Uporzadkuj
249     luki: Luki
250     zastap: Zastap
251     przyporzadkuj: Przyporzadkuj
252
253
254   cls = es[$(ele).attr('data-type')]
255   new cls(ele)
256
257
258 window.edumed =
259   'EduModule': EduModule
260
261
262
263
264 $(document).ready () ->
265   new EduModule($("#book-text"))
266
267   $(".excercise").each (i, el) ->
268     excercise(this)