From 0b266098467ac9c61a7a662505eb41c3801e6b85 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Mon, 30 Apr 2012 16:23:45 -0400 Subject: [PATCH] Rewrite Sequence module to use unobtrusive JS --- djangoapps/courseware/modules/seq_module.py | 38 ++---- templates/coffee/src/modules/sequence.coffee | 70 +++++++++++ templates/seq_module.html | 42 ++++--- templates/seq_module.js | 118 ------------------- 4 files changed, 104 insertions(+), 164 deletions(-) create mode 100644 templates/coffee/src/modules/sequence.coffee delete mode 100644 templates/seq_module.js diff --git a/djangoapps/courseware/modules/seq_module.py b/djangoapps/courseware/modules/seq_module.py index af41d0e8da..4239bc492f 100644 --- a/djangoapps/courseware/modules/seq_module.py +++ b/djangoapps/courseware/modules/seq_module.py @@ -28,14 +28,6 @@ class Module(XModule): self.render() return self.content - def get_init_js(self): - self.render() - return self.init_js - - def get_destroy_js(self): - self.render() - return self.destroy_js - def handle_ajax(self, dispatch, get): if dispatch=='goto_position': self.position = int(get['position']) @@ -45,45 +37,40 @@ class Module(XModule): def render(self): if self.rendered: return - def j(m): + def j(m): ''' jsonify contents so it can be embedded in a js array We also need to split tags so they don't break mid-string''' - if 'init_js' not in m: m['init_js']="" - if 'type' not in m: m['init_js']="" - content=json.dumps(m['content']) - content=content.replace('', '<"+"/script>') + content=json.dumps(m['content']) + content=content.replace('', '<"+"/script>') - return {'content':content, - "destroy_js":m['destroy_js'], - 'init_js':m['init_js'], + return {'content':content, 'type': m['type']} ## Returns a set of all types of all sub-children child_classes = [set([i.tag for i in e.iter()]) for e in self.xmltree] - self.titles = json.dumps(["\n".join([i.get("name").strip() for i in e.iter() if i.get("name") != None]) \ - for e in self.xmltree]) + titles = ["\n".join([i.get("name").strip() for i in e.iter() if i.get("name") != None]) \ + for e in self.xmltree] self.contents = [j(self.render_function(e)) \ for e in self.xmltree] - print self.titles + for i in range(len(self.contents)): + self.contents[i]['title'] = titles[i] for (content, element_class) in zip(self.contents, child_classes): new_class = 'other' for c in class_priority: - if c in element_class: + if c in element_class: new_class = c content['type'] = new_class - - js="" params={'items':self.contents, 'id':self.item_id, 'position': self.position, - 'titles':self.titles, + 'titles':titles, 'tag':self.xmltree.tag} # TODO/BUG: Destroy JavaScript should only be called for the active view @@ -94,16 +81,11 @@ class Module(XModule): destroy_js="".join([e['destroy_js'] for e in self.contents if 'destroy_js' in e]) if self.xmltree.tag in ['sequential', 'videosequence']: - self.init_js=js+render_to_string('seq_module.js',params) - self.destroy_js=destroy_js self.content=render_to_string('seq_module.html',params) if self.xmltree.tag == 'tab': params['id'] = 'tab' - self.init_js=js+render_to_string('tab_module.js',params) - self.destroy_js=destroy_js self.content=render_to_string('tab_module.html',params) self.rendered = True - def __init__(self, system, xml, item_id, state=None): XModule.__init__(self, system, xml, item_id, state) diff --git a/templates/coffee/src/modules/sequence.coffee b/templates/coffee/src/modules/sequence.coffee new file mode 100644 index 0000000000..013206093c --- /dev/null +++ b/templates/coffee/src/modules/sequence.coffee @@ -0,0 +1,70 @@ +class window.Sequence + constructor: (@id, @elements, @tag, position) -> + @buildNavigation() + @bind() + @render position + + bind: -> + $('#sequence-list a').click @goto + + buildNavigation: -> + $.each @elements, (index, item) -> + link = $('').attr class: "seq_#{item.type}_inactive", 'data-element': index + 1 + title = $('

').html(item.title) + list_item = $('

  • ').append(link.append(title)) + $('#sequence-list').append list_item + + toggleArrows: -> + $('.sequence-nav-buttons a').unbind('click') + + if @position == 1 + $('.sequence-nav-buttons .prev a').addClass('disabled') + else + $('.sequence-nav-buttons .prev a').removeClass('disabled').click(@previous) + + if @position == @elements.length + $('.sequence-nav-buttons .next a').addClass('disabled') + else + $('.sequence-nav-buttons .next a').removeClass('disabled').click(@next) + + render: (new_position) -> + if @position != undefined + @mark_visited @position + $.post "/modx/#{@tag}/#{@id}/goto_position", position: new_position + + if @position != new_position + @mark_active new_position + $('#seq_content').html eval(@elements[new_position - 1].content) + + MathJax.Hub.Queue(["Typeset",MathJax.Hub]) + @position = new_position + @toggleArrows() + + goto: (e) => + e.preventDefault() + new_position = $(e.srcElement).data('element') + log_event("seq_goto", old: @position, new: new_position, id: @id) + @render new_position + + next: (e) => + e.preventDefault() + new_position = @position + 1 + log_event("seq_next", old: @position, new: new_position, id: @id) + @render new_position + + previous: (e) => + e.preventDefault() + new_position = @position - 1 + log_event("seq_prev", old: @position, new: new_position, id: @id) + @render new_position + + link_for: (position) -> + $("#sequence-list a[data-element=#{position}]") + + mark_visited: (position) -> + @link_for(position).attr class: "seq_#{@elements[position - 1].type}_visited" + + mark_active: (position) -> + @link_for(position).attr class: "seq_#{@elements[position - 1].type}_active" + + diff --git a/templates/seq_module.html b/templates/seq_module.html index 94aa1661bc..ab903457dc 100644 --- a/templates/seq_module.html +++ b/templates/seq_module.html @@ -1,22 +1,28 @@ - -
    +
    - + + +<%block name="js_extra"> + + diff --git a/templates/seq_module.js b/templates/seq_module.js deleted file mode 100644 index 691cbb5544..0000000000 --- a/templates/seq_module.js +++ /dev/null @@ -1,118 +0,0 @@ -// IMPORTANT TODO: Namespace - -var ${ id }contents=["", - %for t in items: - ${t['content']} , - %endfor - "" - ]; - -var ${ id }types=["", - %for t in items: - "${t['type']}" , - %endfor - "" - ]; - -var ${ id }init_functions=["", - %for t in items: - function(){ ${t['init_js']} }, - %endfor - ""]; - -var ${ id }titles=${titles}; - -var ${ id }destroy_functions=["", - %for t in items: - function(){ ${t['destroy_js']} }, - %endfor - ""]; - -var ${ id }loc = -1; -function disablePrev() { - var i=${ id }loc-1; - log_event("seq_prev", {'old':${id}loc, 'new':i,'id':'${id}'}); - if (i < 1 ) { - $('.${ id }prev a').addClass('disabled'); - } else { - $('.${ id }prev a').removeClass('disabled'); - }; - } - - function disableNext() { - var i=${ id }loc+1; - log_event("seq_next", {'old':${id}loc, 'new':i,'id':'${id}'}); - - if(i > ${ len(items) } ) { - $('.${ id }next a').addClass('disabled'); - } else { - $('.${ id }next a').removeClass('disabled'); - }; -} - -function ${ id }goto(i) { - log_event("seq_goto", {'old':${id}loc, 'new':i,'id':'${id}'}); - - postJSON('${ MITX_ROOT_URL }/modx/${tag}/${ id }/goto_position', - {'position' : i }); - - if (${ id }loc!=-1) - ${ id }destroy_functions[ ${ id }loc ](); - $('#seq_content').html(${ id }contents[i]); - ${ id }init_functions[i]() - //$('#tt_'+${ id }loc).attr("style", "background-color:gray"); - $('#tt_'+${ id }loc).removeClass(); - $('#tt_'+${ id }loc).addClass("seq_"+${ id }types[${ id }loc]+"_visited"); - ${ id }loc=i; - //$('#tt_'+i).attr("style", "background-color:red"); - $('#tt_'+i).removeClass(); - $('#tt_'+i).addClass("seq_"+${ id }types[${ id }loc]+"_active"); - - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); - - disableNext(); - disablePrev(); -} - -function ${ id }setup_click(i) { - $('#tt_'+i).click(function(eo) { ${ id }goto(i);}); - $('#tt_'+i).addClass("seq_"+${ id }types[i]+"_inactive"); - $('#tt_'+i).append("

    " + ${ id }titles[i-1] + "

    "); - -} - -function ${ id }next() { - var i=${ id }loc+1; - log_event("seq_next", {'old':${id}loc, 'new':i,'id':'${id}'}); - if(i > ${ len(items) } ) { - i = ${ len(items) }; - } else { - ${ id }goto(i); - }; -} - - -function ${ id }prev() { - var i=${ id }loc-1; - log_event("seq_prev", {'old':${id}loc, 'new':i,'id':'${id}'}); - if (i < 1 ) { - i = 1; - } else { - ${ id }goto(i); - }; -} - - - -$(function() { - var i; - for(i=1; i<${ len(items)+1 }; i++) { - ${ id }setup_click(i); - } - - - $('.${ id }next a').click(function(eo) { ${ id }next(); return false;}); - $('.${ id }prev a').click(function(eo) { ${ id }prev(); return false;}); - ${ id }goto( ${ position } ); - -});