import json from lxml import etree from mitxmako.shortcuts import render_to_string from x_module import XModule # HACK: This shouldn't be hard-coded to two types # OBSOLETE: This obsoletes 'type' class_priority = ['video', 'problem'] class Module(XModule): ''' Layout module which lays out content in a temporal sequence ''' id_attribute = 'id' def get_state(self): return json.dumps({ 'position':self.position }) @classmethod def get_xml_tags(c): return ["sequential", 'tab'] def get_html(self): 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']) return json.dumps({'success':True}) raise self.system.exception404 def render(self): if self.rendered: return def j(m): ''' jsonify contents so it can be embedded in a js array We also need to split </script> 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>', '<"+"/script>') return {'content':content, "destroy_js":m['destroy_js'], 'init_js':m['init_js'], '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]) self.contents = [j(self.render_function(e)) \ for e in self.xmltree] print self.titles for (content, element_class) in zip(self.contents, child_classes): new_class = 'other' for c in class_priority: 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} # TODO/BUG: Destroy JavaScript should only be called for the active view # This calls it for all the views # # To fix this, we'd probably want to have some way of assigning unique # IDs to sequences. destroy_js="".join([e['destroy_js'] for e in self.contents if 'destroy_js' in e]) if self.xmltree.tag == 'sequential': 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) self.xmltree = etree.fromstring(xml) self.position = 1 if state != None: state = json.loads(state) if 'position' in state: self.position = int(state['position']) self.rendered = False