5   constructor: (@handler, @element) ->
 
   6     $(@element).data(@handler, this)
 
   9 class EduModule extends Binding
 
  10   constructor: (element) ->
 
  11     super 'edumodule', element
 
  13     # $("[name=teacher-toggle]").change (ev) =>
 
  14     #   if $(ev.target).is(":checked")
 
  15     #     $(".teacher", @element).addClass "show"
 
  17     #     $(".teacher", @element).removeClass "show"
 
  20 class Exercise extends Binding
 
  21   constructor: (element) ->
 
  22     super 'exercise', element
 
  23     # just save the html to reset the exercise
 
  24     $(@element).data("exercise-html", $(@element).html())
 
  26     $(".check", @element).click (ev) =>
 
  28       $(".retry", @element).show()
 
  29       $(".check", @element).hide()
 
  30     $(".retry", @element).click (ev) =>
 
  32     $('.solutions', @element).click =>
 
  34       $(".comment", @element).show()
 
  35     $('.reset', @element).click =>
 
  39     $(".correct, .incorrect", @element).removeClass("correct incorrect")
 
  40     $(".check", @element).show()
 
  41     $(".retry", @element).hide()
 
  44     $(@element).html($(@element).data('exercise-html'))
 
  47   piece_correct: (qpiece) ->
 
  48     $(qpiece).removeClass('incorrect').addClass('correct')
 
  50   piece_incorrect: (qpiece) ->
 
  51     $(qpiece).removeClass('correct').addClass('incorrect')
 
  55     $(".question", @element).each (i, question) =>
 
  56       scores.push(@check_question question)
 
  59     $.each scores, (i, s) ->
 
  67     $(".question", @element).each (i, question) =>
 
  68       @solve_question question
 
  72     $('.question', @element).each (i, question) =>
 
  73       answers.push(@get_answer question)
 
  76   # Parses a list of values, separated by space or comma.
 
  77   # The list is read from data attribute of elem using data_key
 
  78   # Returns a list with elements
 
  79   # eg.: things_i_need: "house bike tv playstation"
 
  80   # yields ["house", "bike", "tv", "playstation"]
 
  81   # If optional numbers argument is true, returns list of numbers
 
  83   get_value_list: (elem, data_key, numbers) ->
 
  84     vl = $(elem).attr("data-" + data_key).split(/[ ,]+/).map($.trim) #.map((x) -> parseInt(x))
 
  86       vl = vl.map((x) -> parseInt(x))
 
  89   # Parses a list of values, separated by space or comma.
 
  90   # The list is read from data attribute of elem using data_key
 
  91   # Returns a 2-element list with mandatory and optional
 
  92   # items. optional items are marked with a question mark on the end
 
  93   # eg.: things_i_need: "house bike tv? playstation?"
 
  94   # yields [[ "house", "bike"], ["tv", "playstation"]]
 
  95   get_value_optional_list: (elem, data_key) ->
 
  96     vals = @get_value_list(elem, data_key)
 
 100       if v.slice(-1) == "?"
 
 101         opt.push v.slice(0, -1)
 
 106   show_score: (score) ->
 
 107     $msg = $(".message", @element)
 
 108     $msg.text("Wynik: #{score[0]} / #{score[2]}")
 
 109     if score[0] >= score[2] and score[1] == 0
 
 110       $msg.addClass("maxscore")
 
 112       $msg.removeClass("maxscore")
 
 115   draggable_equal: ($draggable1, $draggable2) ->
 
 118   draggable_accept: ($draggable, $droppable) ->
 
 119     dropped = $droppable.closest("ul, ol").find(".draggable")
 
 121       if @draggable_equal $draggable, $(d)
 
 125   draggable_move: ($draggable, $placeholder, ismultiple) ->
 
 126     $added = $draggable.clone()
 
 127     $added.data("original", $draggable.get(0))
 
 129       $draggable.addClass('disabled').draggable('disable')
 
 131     $placeholder.after($added)
 
 132     if not $placeholder.hasClass('multiple')
 
 134     if $added.is(".add-li")
 
 137     $added.append('<span class="remove">x</span><div class="clr"></div>')
 
 138     $('.remove', $added).click (ev) =>
 
 141         $($added.data('original')).removeClass('disabled').draggable('enable')
 
 143       if $added.is(".add-li")
 
 144         $added = $added.closest('li')
 
 145       $added.prev(".placeholder:not(.multiple)").show()
 
 149 ## XXX co z issortable?
 
 150   dragging: (ismultiple, issortable) ->
 
 151     $(".question", @element).each (i, question) =>
 
 157       $(".draggable", question).draggable(draggable_opts)
 
 159       $(".placeholder", question).droppable
 
 160         accept: (draggable) ->
 
 161           $draggable = $(draggable)
 
 164           if not $draggable.is(".draggable")
 
 168             is_accepted= self.draggable_accept $draggable, $(this)
 
 171             $(this).addClass 'accepting'
 
 173             $(this).removeClass 'accepting'
 
 177           $(ev.target).removeClass 'accepting dragover'
 
 179           @draggable_move $(ui.draggable), $(ev.target), ismultiple
 
 181           # $added = $(ui.draggable).clone()
 
 182           # $added.data("original", ui.draggable)
 
 184           #   $(ui.draggable).addClass('disabled').draggable('disable')
 
 186           # $(ev.target).after(added)
 
 187           # if not $(ev.target).hasClass('multiple')
 
 188           #   $(ev.target).hide()
 
 189           # $added.append('<span class="remove">x</span>')
 
 190           # $('.remove', added).click (ev) =>
 
 191           #   $added.prev(".placeholder:not(.multiple)").show()
 
 193           #     $added.data('original').removeClass('disabled').draggable('enable')
 
 197           $(ev.target).addClass 'dragover'
 
 201           $(ev.target).removeClass 'dragover'
 
 205 class Wybor extends Exercise
 
 206   constructor: (element) ->
 
 208     $(".question-piece input", element).change(@retry);
 
 211   check_question: (question) ->
 
 215     solution = @get_value_list(question, 'solution')
 
 216     $(".question-piece", question).each (i, qpiece) =>
 
 217       piece_no = $(qpiece).attr 'data-no'
 
 218       piece_name = $(qpiece).attr 'data-name'
 
 220         should_be_checked = solution.indexOf(piece_name) >= 0
 
 222         should_be_checked = solution.indexOf(piece_no) >= 0
 
 223       is_checked = $("input", qpiece).is(":checked")
 
 231           @piece_correct qpiece
 
 234           @piece_incorrect qpiece
 
 236         $(qpiece).removeClass("correct,incorrect")
 
 238     return [good, bad, all]
 
 240   solve_question: (question) ->
 
 241     solution = @get_value_list(question, 'solution')
 
 242     $(".question-piece", question).each (i, qpiece) =>
 
 243       piece_no = $(qpiece).attr 'data-no'
 
 244       piece_name = $(qpiece).attr 'data-name'
 
 246         should_be_checked = solution.indexOf(piece_name) >= 0
 
 248         should_be_checked = solution.indexOf(piece_no) >= 0
 
 249       console.log("check " + $("input[type=checkbox]", qpiece).attr("id") + " -> " + should_be_checked)
 
 250       $("input[type=checkbox],input[type=radio]", qpiece).prop 'checked', should_be_checked
 
 252   get_answer: (question) ->
 
 254     $('.question-piece', question).each (i, qpiece) =>
 
 256       if $("input[type=checkbox],input[type=radio]", qpiece).is(':checked')
 
 257         answer.push($qpiece.attr('data-name'))
 
 261 class Uporzadkuj extends Exercise
 
 262   constructor: (element) ->
 
 264     $('ol, ul', @element).sortable({ items: "> li", start: @retry })
 
 266   check_question: (question) ->
 
 267     positions = @get_value_list(question, 'original', true)
 
 268     sorted = positions.sort()
 
 269     pkts = $('.question-piece', question)
 
 275     for pkt in [0...pkts.length]
 
 277       if pkts.eq(pkt).data('pos') == sorted[pkt]
 
 279         @piece_correct pkts.eq(pkt)
 
 282         @piece_incorrect pkts.eq(pkt)
 
 283     return [correct, bad, all]
 
 285   solve_question: (question) ->
 
 286     positions = @get_value_list(question, 'original', true)
 
 287     sorted = positions.sort()
 
 288     pkts = $('.question-piece', question)
 
 296     parent = pkts.eq(0).parent()
 
 300   get_answer: (question) ->
 
 302     $(".question-piece", @element).each (i, qpiece) =>
 
 303       answer.push($(qpiece).attr('data-pos'))
 
 307 # XXX propozycje="1/0"
 
 308 class Luki extends Exercise
 
 309   constructor: (element) ->
 
 311     @dragging false, false
 
 314     all = $(".placeholder", @element).length
 
 317     $(".placeholder + .question-piece", @element).each (i, qpiece) =>
 
 318       $placeholder = $(qpiece).prev(".placeholder")
 
 319       if $placeholder.data('solution') == $(qpiece).data('no')
 
 320         @piece_correct qpiece
 
 324         @piece_incorrect qpiece
 
 326     @show_score [correct, bad, all]
 
 328   solve_question: (question) ->
 
 329     $(".placeholder", question).each (i, placeholder) =>
 
 330       $qp = $(".question-piece[data-no=" + $(placeholder).data('solution') + "]", question)
 
 331       @draggable_move $qp, $(placeholder), false
 
 334 class Zastap extends Exercise
 
 335   constructor: (element) ->
 
 337     $(".paragraph", @element).each (i, par) =>
 
 338       @wrap_words $(par), $('<span class="placeholder zastap"/>')
 
 339     @dragging false, false
 
 346     $(".paragraph", @element).each (i, par) =>
 
 347       $(".placeholder", par).each (j, qpiece) =>
 
 349         $dragged = $qp.next(".draggable")
 
 350         if $qp.data("solution")
 
 351           if $dragged and $qp.data("solution") == $dragged.data("no")
 
 352             @piece_correct $dragged
 
 354 #          else -- we dont mark enything here, so not to hint user about solution. He sees he hasn't used all the draggables
 
 358     @show_score [correct, bad, all]
 
 362     $(".paragraph", @element).each (i, par) =>
 
 363       $(".placeholder[data-solution]", par).each (j, qpiece) =>
 
 365         $dr = $(".draggable[data-no=" + $qp.data('solution') + "]", @element)
 
 366         @draggable_move $dr, $qp, false
 
 369   wrap_words: (element, wrapper) ->
 
 370     # This function wraps each word of element in wrapper, but does not descend into child-tags of element.
 
 371     # It doesn't wrap things between words (defined by ignore RE below). Warning - ignore must begin with ^
 
 372     ignore = /^[ \t.,:;()]+/
 
 374     insertWrapped = (txt, elem) ->
 
 376       $(document.createTextNode(txt))
 
 377         .wrap(nw).parent().attr("data-original", txt).insertBefore(elem)
 
 379     for j in [element.get(0).childNodes.length-1..0]
 
 380       chld = element.get(0).childNodes[j]
 
 381       if chld.nodeType == document.TEXT_NODE
 
 382         len = chld.textContent.length
 
 386           space = ignore.exec(chld.textContent.substr(i))
 
 389               insertWrapped(chld.textContent.substr(wordb, i-wordb), chld)
 
 391             $(document.createTextNode(space[0])).insertBefore(chld)
 
 397           insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld)
 
 401 class Przyporzadkuj extends Exercise
 
 403     for qp in $(".question-piece", @element)
 
 404       if $(qp).attr('data-solution').split(/[ ,]+/).length > 1
 
 408   constructor: (element) ->
 
 411     @multiple = @is_multiple()
 
 413     @dragging @multiple, true
 
 415   draggable_equal: (d1, d2) ->
 
 416     return d1.data("no") == d2.data("no")
 
 418   draggable_accept: ($draggable, $droppable) ->
 
 419     dropped = $droppable.closest("ul, ol").find(".draggable")
 
 420     return (super $draggable, $droppable) && dropped.length == 0
 
 422   check_question: (question) ->
 
 423     # subjects placed in predicates
 
 424     minimum = $(question).data("minimum")
 
 430       $(".subject .question-piece", question).each (i, el) ->
 
 431         v = self.get_value_optional_list el, 'solution'
 
 433         all += mandatory.length
 
 435     for pred in $(".predicate [data-predicate]", question)
 
 436       pn = $(pred).attr('data-predicate')
 
 440       for qp in $(".question-piece", pred)
 
 441         v = @get_value_optional_list qp, 'solution'
 
 445         if mandatory.indexOf(pn) >= 0 or (minimum and optional.indexOf(pn) >= 0)
 
 452     return [count, bad_count, all]
 
 454   solve_question: (question) ->
 
 455     minimum = $(question).data("min")
 
 457     for qp in $(".subject .question-piece", question)
 
 458       v = @get_value_optional_list qp, 'solution'
 
 463         draggables = mandatory.count(optional)[0...minimum]
 
 465         draggables = mandatory
 
 467         $pr = $(".predicate [data-predicate=" + m + "]", question)
 
 468         $ph = $pr.find ".placeholder:visible"
 
 469         @draggable_move $(qp), $ph.eq(0), @multiple
 
 471   get_answer: (question) ->
 
 473     $(".predicate [data-predicate]", question).each (i, subjects) =>
 
 474       predicate = $(subjects).attr('data-predicate')
 
 475       answer[predicate] = []
 
 476       $('.question-piece', subjects).each (i, qpiece) =>
 
 478         answer[predicate].push($qpiece.attr('data-id'))
 
 482 class PrawdaFalsz extends Exercise
 
 483   constructor: (element) ->
 
 486     for qp in $(".question-piece", @element)
 
 487       $(".true", qp).click (ev) =>
 
 490         $(ev.target).closest(".question-piece").data("value", "true")
 
 491         $(ev.target).addClass('chosen').siblings('a').removeClass('chosen')
 
 492       $(".false", qp).click (ev) =>
 
 495         $(ev.target).closest(".question-piece").data("value", "false")
 
 496         $(ev.target).addClass('chosen').siblings('a').removeClass('chosen')
 
 503     for qp in $(".question-piece", @element)
 
 504       if $(qp).data("solution").toString() == $(qp).data("value")
 
 513     return [good, bad, all]
 
 517     for qp in $(".question-piece", @element)
 
 518       if $(qp).data('solution') == true
 
 519         $(".true", qp).click()
 
 521         $(".false", qp).click()
 
 523   get_answer: (question) ->
 
 525     $(".question-piece", @element).each (i, qpiece) =>
 
 526       answer.push($(qpiece).data('value') || '-')
 
 534     uporzadkuj: Uporzadkuj
 
 537     przyporzadkuj: Przyporzadkuj
 
 538     prawdafalsz: PrawdaFalsz
 
 541   cls = es[$(ele).attr('data-type')]
 
 546   'EduModule': EduModule
 
 551 $(document).ready () ->
 
 552   new EduModule($("#book-text"))
 
 554   $(".exercise").each (i, el) ->