Standardize how JS XModules are instantiated
This commit is contained in:
@@ -14,7 +14,7 @@ from static_replace import replace_urls
|
||||
|
||||
from mitxmako.shortcuts import render_to_response, render_to_string
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule_modifiers import replace_static_urls
|
||||
from xmodule_modifiers import replace_static_urls, wrap_xmodule
|
||||
|
||||
|
||||
# ==== Public views ==================================================
|
||||
@@ -97,6 +97,7 @@ def edit_item(request):
|
||||
raise Http404 # TODO (vshnayder): better error
|
||||
|
||||
item = modulestore().get_item(item_location)
|
||||
item.get_html = wrap_xmodule(item.get_html, item, "xmodule_edit.html")
|
||||
return render_to_response('unit.html', {
|
||||
'contents': item.get_html(),
|
||||
'js_module': item.js_module_name,
|
||||
@@ -181,7 +182,10 @@ def load_sample_module(descriptor, instance_state, shared_state):
|
||||
"""
|
||||
system = sample_module_system(descriptor)
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
module.get_html = replace_static_urls(module.get_html, module.metadata['data_dir'])
|
||||
module.get_html = replace_static_urls(
|
||||
wrap_xmodule(module.get_html, module, "xmodule_display.html"),
|
||||
module.metadata['data_dir']
|
||||
)
|
||||
|
||||
return module
|
||||
|
||||
|
||||
@@ -4,20 +4,7 @@ class CMS.Models.Module extends Backbone.Model
|
||||
data: ''
|
||||
|
||||
loadModule: (element) ->
|
||||
moduleType = @get('type')
|
||||
|
||||
try
|
||||
@module = if moduleType? then new window[moduleType](element) else null
|
||||
catch error
|
||||
console.error "Unable to load #{moduleType}: #{error.message}" if console
|
||||
|
||||
loadPreview: (element) ->
|
||||
previewType = @get('previewType')
|
||||
|
||||
try
|
||||
@previewModule = if previewType? then new window[previewType](element) else null
|
||||
catch error
|
||||
console.error "Unable to load #{previewType}: #{error.message}" if console
|
||||
@module = XModule.loadModule($(element).find('.xmodule_edit'))
|
||||
|
||||
editUrl: ->
|
||||
"/edit_item?#{$.param(id: @get('id'))}"
|
||||
|
||||
@@ -10,8 +10,9 @@ class CMS.Views.ModuleEdit extends Backbone.View
|
||||
initialize: ->
|
||||
@$el.load @model.editUrl(), =>
|
||||
@model.loadModule(@el)
|
||||
@$el.find('.preview').children().each (idx, previewEl) =>
|
||||
@model.loadPreview(previewEl)
|
||||
|
||||
# Load preview modules
|
||||
XModule.loadModules('display')
|
||||
|
||||
save: (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
@@ -5,17 +5,38 @@ from static_replace import replace_urls
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
|
||||
|
||||
def replace_static_urls(original, prefix):
|
||||
def wrap_xmodule(get_html, module, template):
|
||||
"""
|
||||
Wraps the results of get_html in a standard <section> with identifying
|
||||
data so that the appropriate javascript module can be loaded onto it.
|
||||
|
||||
get_html: An XModule.get_html method or an XModuleDescriptor.get_html method
|
||||
module: An XModule
|
||||
template: A template that takes the variables:
|
||||
content: the results of get_html,
|
||||
module_name: the js_module_name of the module
|
||||
"""
|
||||
|
||||
@wraps(get_html)
|
||||
def _get_html():
|
||||
return render_to_string(template, {
|
||||
'content': get_html(),
|
||||
'module_name': module.js_module_name
|
||||
})
|
||||
return _get_html
|
||||
|
||||
|
||||
def replace_static_urls(get_html, prefix):
|
||||
"""
|
||||
Updates the supplied module with a new get_html function that wraps
|
||||
the old get_html function and substitutes urls of the form /static/...
|
||||
with urls that are /static/<prefix>/...
|
||||
"""
|
||||
|
||||
@wraps(original)
|
||||
def get_html():
|
||||
return replace_urls(original(), staticfiles_prefix=prefix)
|
||||
return get_html
|
||||
@wraps(get_html)
|
||||
def _get_html():
|
||||
return replace_urls(get_html(), staticfiles_prefix=prefix)
|
||||
return _get_html
|
||||
|
||||
|
||||
def grade_histogram(module_id):
|
||||
@@ -40,15 +61,15 @@ def grade_histogram(module_id):
|
||||
return grades
|
||||
|
||||
|
||||
def add_histogram(original, module):
|
||||
def add_histogram(get_html, module):
|
||||
"""
|
||||
Updates the supplied module with a new get_html function that wraps
|
||||
the output of the old get_html function with additional information
|
||||
for admin users only, including a histogram of student answers and the
|
||||
definition of the xmodule
|
||||
"""
|
||||
@wraps(original)
|
||||
def get_html():
|
||||
@wraps(get_html)
|
||||
def _get_html():
|
||||
module_id = module.id
|
||||
histogram = grade_histogram(module_id)
|
||||
render_histogram = len(histogram) > 0
|
||||
@@ -73,7 +94,7 @@ def add_histogram(original, module):
|
||||
'edit_link': edit_link,
|
||||
'histogram': json.dumps(histogram),
|
||||
'render_histogram': render_histogram,
|
||||
'module_content': original()}
|
||||
'module_content': get_html()}
|
||||
return render_to_string("staff_problem_info.html", staff_context)
|
||||
|
||||
return get_html
|
||||
return _get_html
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class @Problem
|
||||
constructor: (element) ->
|
||||
@el = $(element)
|
||||
@el = $(element).find('.problems-wrapper')
|
||||
@id = @el.data('problem-id')
|
||||
@element_id = @el.attr('id')
|
||||
@url = @el.data('url')
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
class @Sequence
|
||||
constructor: (element) ->
|
||||
(@id, @element_id, @elements, position) ->
|
||||
@el = $(element)
|
||||
@el = $(element).find('.sequence')
|
||||
@contents = @$('.seq_contents')
|
||||
@id = @el.data('id')
|
||||
@initProgress()
|
||||
@@ -81,12 +80,12 @@ class @Sequence
|
||||
|
||||
@mark_active new_position
|
||||
@$('#seq_content').html @contents.eq(new_position - 1).text()
|
||||
XModule.loadModules('display', @$('#seq_content'))
|
||||
|
||||
MathJax.Hub.Queue(["Typeset", MathJax.Hub])
|
||||
@position = new_position
|
||||
@toggleArrows()
|
||||
@hookUpProgressEvent()
|
||||
@el.trigger 'contentChanged'
|
||||
|
||||
goto: (event) =>
|
||||
event.preventDefault()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class @Video
|
||||
constructor: (@element) ->
|
||||
@id = $(@element).attr('id').replace(/video_/, '')
|
||||
@caption_data_dir = $(@element).data('caption-data-dir')
|
||||
constructor: (element) ->
|
||||
@el = $(element).find('.video')
|
||||
@id = @el.attr('id').replace(/video_/, '')
|
||||
@caption_data_dir = @el.data('caption-data-dir')
|
||||
window.player = null
|
||||
@el = $("#video_#{@id}")
|
||||
@parseVideos $(@element).data('streams')
|
||||
@parseVideos @el.data('streams')
|
||||
@fetchMetadata()
|
||||
@parseSpeed()
|
||||
$("#video_#{@id}").data('video', this).addClass('video-load-complete')
|
||||
|
||||
30
common/static/coffee/src/xmodule.coffee
Normal file
30
common/static/coffee/src/xmodule.coffee
Normal file
@@ -0,0 +1,30 @@
|
||||
@XModule =
|
||||
###
|
||||
Load a single module (either an edit module or a display module)
|
||||
from the supplied element, which should have a data-type attribute
|
||||
specifying the class to load
|
||||
###
|
||||
loadModule: (element) ->
|
||||
moduleType = $(element).data('type')
|
||||
if moduleType == 'None'
|
||||
return
|
||||
|
||||
try
|
||||
new window[moduleType](element)
|
||||
catch error
|
||||
console.error "Unable to load #{moduleType}: #{error.message}" if console
|
||||
|
||||
###
|
||||
Load all modules on the page of the specified type.
|
||||
If container is provided, only load modules inside that element
|
||||
Type is one of 'display' or 'edit'
|
||||
###
|
||||
loadModules: (type, container) ->
|
||||
selector = ".xmodule_#{type}"
|
||||
|
||||
if container?
|
||||
modules = $(container).find(selector)
|
||||
else
|
||||
modules = $(selector)
|
||||
|
||||
modules.each (idx, element) -> XModule.loadModule element
|
||||
3
common/templates/xmodule_display.html
Normal file
3
common/templates/xmodule_display.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<section class="xmodule_display" data-type="${module_name}">
|
||||
${content}
|
||||
</section>
|
||||
3
common/templates/xmodule_edit.html
Normal file
3
common/templates/xmodule_edit.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<section class="xmodule_edit" data-type="${module_name}">
|
||||
${content}
|
||||
</section>
|
||||
@@ -13,7 +13,7 @@ from models import StudentModule, StudentModuleCache
|
||||
from static_replace import replace_urls
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from xmodule_modifiers import replace_static_urls, add_histogram
|
||||
from xmodule_modifiers import replace_static_urls, add_histogram, wrap_xmodule
|
||||
|
||||
log = logging.getLogger("mitx.courseware")
|
||||
|
||||
@@ -163,7 +163,10 @@ def get_module(user, request, location, student_module_cache, position=None):
|
||||
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
|
||||
module.get_html = replace_static_urls(module.get_html, module.metadata['data_dir'])
|
||||
module.get_html = replace_static_urls(
|
||||
wrap_xmodule(module.get_html, module, 'xmodule_display.html'),
|
||||
module.metadata['data_dir']
|
||||
)
|
||||
|
||||
if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF') and user.is_staff:
|
||||
module.get_html = add_histogram(module.get_html)
|
||||
|
||||
@@ -5,19 +5,13 @@ class @Courseware
|
||||
Courseware.prefix = $("meta[name='path_prefix']").attr('content')
|
||||
new Navigation
|
||||
Logger.bind()
|
||||
@bind()
|
||||
@render()
|
||||
|
||||
@start: ->
|
||||
new Courseware
|
||||
|
||||
bind: ->
|
||||
$('.course-content .sequence, .course-content .tab')
|
||||
.bind 'contentChanged', @render
|
||||
|
||||
render: ->
|
||||
$('.course-content .video').each (idx, element) -> new Video element
|
||||
$('.course-content .problems-wrapper').each (idx, element) -> new Problem element
|
||||
XModule.loadModules('display')
|
||||
$('.course-content .histogram').each ->
|
||||
id = $(this).attr('id').replace(/histogram_/, '')
|
||||
new Histogram id, $(this).data('histogram')
|
||||
|
||||
@@ -32,11 +32,3 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<%block name="js_extra">
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
new Sequence($("#sequence_${element_id}"));
|
||||
});
|
||||
</script>
|
||||
</%block>
|
||||
|
||||
Reference in New Issue
Block a user