diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py index 6edb621317..2349f1e3be 100644 --- a/common/djangoapps/xmodule_modifiers.py +++ b/common/djangoapps/xmodule_modifiers.py @@ -7,6 +7,7 @@ import json import logging import static_replace import uuid +import markupsafe from django.conf import settings from django.utils.timezone import UTC @@ -71,7 +72,7 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer, data = {} data.update(extra_data) - css_classes = ['xblock', 'xblock-{}'.format(view)] + css_classes = ['xblock', 'xblock-{}'.format(markupsafe.escape(view))] if isinstance(block, (XModule, XModuleDescriptor)): if view in PREVIEW_VIEWS: @@ -81,7 +82,7 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer, # The block is acting as an XModuleDescriptor css_classes.append('xmodule_edit') - css_classes.append('xmodule_' + class_name) + css_classes.append('xmodule_' + markupsafe.escape(class_name)) data['type'] = block.js_module_name shim_xmodule_js(frag) @@ -93,11 +94,14 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer, data['usage-id'] = usage_id_serializer(block.scope_ids.usage_id) data['request-token'] = request_token + if block.name: + data['name'] = block.name + template_context = { 'content': block.display_name if display_name_only else frag.content, 'classes': css_classes, 'display_name': block.display_name_with_default, - 'data_attributes': u' '.join(u'data-{}="{}"'.format(key, value) + 'data_attributes': u' '.join(u'data-{}="{}"'.format(markupsafe.escape(key), markupsafe.escape(value)) for key, value in data.iteritems()), } diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index bb6c486807..ef112666ef 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -191,6 +191,26 @@ class XModuleMixin(XBlockMixin): default=None ) + def __init__(self, *args, **kwargs): + self.xmodule_runtime = None + super(XModuleMixin, self).__init__(*args, **kwargs) + + @property + def runtime(self): + # Handle XModule backwards compatibility. If this is a pure + # XBlock, and it has an xmodule_runtime defined, then we're in + # an XModule context, not an XModuleDescriptor context, + # so we should use the xmodule_runtime (ModuleSystem) as the runtime. + if (not isinstance(self, (XModule, XModuleDescriptor)) and + self.xmodule_runtime is not None): + return self.xmodule_runtime + return self._runtime + + @runtime.setter + def runtime(self, value): + self._runtime = value + + @property def system(self): """ @@ -1168,9 +1188,8 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p return super(DescriptorSystem, self).render(block, view_name, context) def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False): - xmodule_runtime = getattr(block, 'xmodule_runtime', None) - if xmodule_runtime is not None: - return xmodule_runtime.handler_url(block, handler_name, suffix, query, thirdparty) + if block.xmodule_runtime is not None: + return block.xmodule_runtime.handler_url(block, handler_name, suffix, query, thirdparty) else: # Currently, Modulestore is responsible for instantiating DescriptorSystems # This means that LMS/CMS don't have a way to define a subclass of DescriptorSystem @@ -1182,9 +1201,8 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p """ See :meth:`xblock.runtime.Runtime:local_resource_url` for documentation. """ - xmodule_runtime = getattr(block, 'xmodule_runtime', None) - if xmodule_runtime is not None: - return xmodule_runtime.local_resource_url(block, uri) + if block.xmodule_runtime is not None: + return block.xmodule_runtime.local_resource_url(block, uri) else: # Currently, Modulestore is responsible for instantiating DescriptorSystems # This means that LMS/CMS don't have a way to define a subclass of DescriptorSystem @@ -1202,9 +1220,8 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p """ See :meth:`xblock.runtime.Runtime:publish` for documentation. """ - xmodule_runtime = getattr(block, 'xmodule_runtime', None) - if xmodule_runtime is not None: - return xmodule_runtime.publish(block, event_type, event) + if block.xmodule_runtime is not None: + return block.xmodule_runtime.publish(block, event_type, event) def add_block_as_child_node(self, block, node): child = etree.SubElement(node, "unknown") diff --git a/common/static/coffee/src/xblock/core.coffee b/common/static/coffee/src/xblock/core.coffee index 885d9af599..bafcff97c9 100644 --- a/common/static/coffee/src/xblock/core.coffee +++ b/common/static/coffee/src/xblock/core.coffee @@ -34,6 +34,7 @@ block.element = element block.name = $element.data("name") + block.type = $element.data("block-type") $element.trigger("xblock-initialized") $element.data("initialized", true) diff --git a/common/templates/xblock_wrapper.html b/common/templates/xblock_wrapper.html index 2bb3ba97e9..74574907df 100644 --- a/common/templates/xblock_wrapper.html +++ b/common/templates/xblock_wrapper.html @@ -1,4 +1,4 @@ -
+
% if js_pass_parameters: