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 mitxmako.shortcuts import render_to_response, render_to_string
|
||||||
from xmodule.modulestore.django import modulestore
|
from xmodule.modulestore.django import modulestore
|
||||||
from xmodule_modifiers import replace_static_urls
|
from xmodule_modifiers import replace_static_urls, wrap_xmodule
|
||||||
|
|
||||||
|
|
||||||
# ==== Public views ==================================================
|
# ==== Public views ==================================================
|
||||||
@@ -97,6 +97,7 @@ def edit_item(request):
|
|||||||
raise Http404 # TODO (vshnayder): better error
|
raise Http404 # TODO (vshnayder): better error
|
||||||
|
|
||||||
item = modulestore().get_item(item_location)
|
item = modulestore().get_item(item_location)
|
||||||
|
item.get_html = wrap_xmodule(item.get_html, item, "xmodule_edit.html")
|
||||||
return render_to_response('unit.html', {
|
return render_to_response('unit.html', {
|
||||||
'contents': item.get_html(),
|
'contents': item.get_html(),
|
||||||
'js_module': item.js_module_name,
|
'js_module': item.js_module_name,
|
||||||
@@ -181,7 +182,10 @@ def load_sample_module(descriptor, instance_state, shared_state):
|
|||||||
"""
|
"""
|
||||||
system = sample_module_system(descriptor)
|
system = sample_module_system(descriptor)
|
||||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
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
|
return module
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,7 @@ class CMS.Models.Module extends Backbone.Model
|
|||||||
data: ''
|
data: ''
|
||||||
|
|
||||||
loadModule: (element) ->
|
loadModule: (element) ->
|
||||||
moduleType = @get('type')
|
@module = XModule.loadModule($(element).find('.xmodule_edit'))
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
editUrl: ->
|
editUrl: ->
|
||||||
"/edit_item?#{$.param(id: @get('id'))}"
|
"/edit_item?#{$.param(id: @get('id'))}"
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ class CMS.Views.ModuleEdit extends Backbone.View
|
|||||||
initialize: ->
|
initialize: ->
|
||||||
@$el.load @model.editUrl(), =>
|
@$el.load @model.editUrl(), =>
|
||||||
@model.loadModule(@el)
|
@model.loadModule(@el)
|
||||||
@$el.find('.preview').children().each (idx, previewEl) =>
|
|
||||||
@model.loadPreview(previewEl)
|
# Load preview modules
|
||||||
|
XModule.loadModules('display')
|
||||||
|
|
||||||
save: (event) ->
|
save: (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|||||||
@@ -5,17 +5,38 @@ from static_replace import replace_urls
|
|||||||
from mitxmako.shortcuts import render_to_string
|
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
|
Updates the supplied module with a new get_html function that wraps
|
||||||
the old get_html function and substitutes urls of the form /static/...
|
the old get_html function and substitutes urls of the form /static/...
|
||||||
with urls that are /static/<prefix>/...
|
with urls that are /static/<prefix>/...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@wraps(original)
|
@wraps(get_html)
|
||||||
def get_html():
|
def _get_html():
|
||||||
return replace_urls(original(), staticfiles_prefix=prefix)
|
return replace_urls(get_html(), staticfiles_prefix=prefix)
|
||||||
return get_html
|
return _get_html
|
||||||
|
|
||||||
|
|
||||||
def grade_histogram(module_id):
|
def grade_histogram(module_id):
|
||||||
@@ -40,15 +61,15 @@ def grade_histogram(module_id):
|
|||||||
return grades
|
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
|
Updates the supplied module with a new get_html function that wraps
|
||||||
the output of the old get_html function with additional information
|
the output of the old get_html function with additional information
|
||||||
for admin users only, including a histogram of student answers and the
|
for admin users only, including a histogram of student answers and the
|
||||||
definition of the xmodule
|
definition of the xmodule
|
||||||
"""
|
"""
|
||||||
@wraps(original)
|
@wraps(get_html)
|
||||||
def get_html():
|
def _get_html():
|
||||||
module_id = module.id
|
module_id = module.id
|
||||||
histogram = grade_histogram(module_id)
|
histogram = grade_histogram(module_id)
|
||||||
render_histogram = len(histogram) > 0
|
render_histogram = len(histogram) > 0
|
||||||
@@ -73,7 +94,7 @@ def add_histogram(original, module):
|
|||||||
'edit_link': edit_link,
|
'edit_link': edit_link,
|
||||||
'histogram': json.dumps(histogram),
|
'histogram': json.dumps(histogram),
|
||||||
'render_histogram': render_histogram,
|
'render_histogram': render_histogram,
|
||||||
'module_content': original()}
|
'module_content': get_html()}
|
||||||
return render_to_string("staff_problem_info.html", staff_context)
|
return render_to_string("staff_problem_info.html", staff_context)
|
||||||
|
|
||||||
return get_html
|
return _get_html
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class @Problem
|
class @Problem
|
||||||
constructor: (element) ->
|
constructor: (element) ->
|
||||||
@el = $(element)
|
@el = $(element).find('.problems-wrapper')
|
||||||
@id = @el.data('problem-id')
|
@id = @el.data('problem-id')
|
||||||
@element_id = @el.attr('id')
|
@element_id = @el.attr('id')
|
||||||
@url = @el.data('url')
|
@url = @el.data('url')
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
class @Sequence
|
class @Sequence
|
||||||
constructor: (element) ->
|
constructor: (element) ->
|
||||||
(@id, @element_id, @elements, position) ->
|
@el = $(element).find('.sequence')
|
||||||
@el = $(element)
|
|
||||||
@contents = @$('.seq_contents')
|
@contents = @$('.seq_contents')
|
||||||
@id = @el.data('id')
|
@id = @el.data('id')
|
||||||
@initProgress()
|
@initProgress()
|
||||||
@@ -81,12 +80,12 @@ class @Sequence
|
|||||||
|
|
||||||
@mark_active new_position
|
@mark_active new_position
|
||||||
@$('#seq_content').html @contents.eq(new_position - 1).text()
|
@$('#seq_content').html @contents.eq(new_position - 1).text()
|
||||||
|
XModule.loadModules('display', @$('#seq_content'))
|
||||||
|
|
||||||
MathJax.Hub.Queue(["Typeset", MathJax.Hub])
|
MathJax.Hub.Queue(["Typeset", MathJax.Hub])
|
||||||
@position = new_position
|
@position = new_position
|
||||||
@toggleArrows()
|
@toggleArrows()
|
||||||
@hookUpProgressEvent()
|
@hookUpProgressEvent()
|
||||||
@el.trigger 'contentChanged'
|
|
||||||
|
|
||||||
goto: (event) =>
|
goto: (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
class @Video
|
class @Video
|
||||||
constructor: (@element) ->
|
constructor: (element) ->
|
||||||
@id = $(@element).attr('id').replace(/video_/, '')
|
@el = $(element).find('.video')
|
||||||
@caption_data_dir = $(@element).data('caption-data-dir')
|
@id = @el.attr('id').replace(/video_/, '')
|
||||||
|
@caption_data_dir = @el.data('caption-data-dir')
|
||||||
window.player = null
|
window.player = null
|
||||||
@el = $("#video_#{@id}")
|
@el = $("#video_#{@id}")
|
||||||
@parseVideos $(@element).data('streams')
|
@parseVideos @el.data('streams')
|
||||||
@fetchMetadata()
|
@fetchMetadata()
|
||||||
@parseSpeed()
|
@parseSpeed()
|
||||||
$("#video_#{@id}").data('video', this).addClass('video-load-complete')
|
$("#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 static_replace import replace_urls
|
||||||
from xmodule.exceptions import NotFoundError
|
from xmodule.exceptions import NotFoundError
|
||||||
from xmodule.x_module import ModuleSystem
|
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")
|
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 = 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:
|
if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF') and user.is_staff:
|
||||||
module.get_html = add_histogram(module.get_html)
|
module.get_html = add_histogram(module.get_html)
|
||||||
|
|||||||
@@ -5,19 +5,13 @@ class @Courseware
|
|||||||
Courseware.prefix = $("meta[name='path_prefix']").attr('content')
|
Courseware.prefix = $("meta[name='path_prefix']").attr('content')
|
||||||
new Navigation
|
new Navigation
|
||||||
Logger.bind()
|
Logger.bind()
|
||||||
@bind()
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
@start: ->
|
@start: ->
|
||||||
new Courseware
|
new Courseware
|
||||||
|
|
||||||
bind: ->
|
|
||||||
$('.course-content .sequence, .course-content .tab')
|
|
||||||
.bind 'contentChanged', @render
|
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
$('.course-content .video').each (idx, element) -> new Video element
|
XModule.loadModules('display')
|
||||||
$('.course-content .problems-wrapper').each (idx, element) -> new Problem element
|
|
||||||
$('.course-content .histogram').each ->
|
$('.course-content .histogram').each ->
|
||||||
id = $(this).attr('id').replace(/histogram_/, '')
|
id = $(this).attr('id').replace(/histogram_/, '')
|
||||||
new Histogram id, $(this).data('histogram')
|
new Histogram id, $(this).data('histogram')
|
||||||
|
|||||||
@@ -32,11 +32,3 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%block name="js_extra">
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function(){
|
|
||||||
new Sequence($("#sequence_${element_id}"));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</%block>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user