Commit 02fa6d72 by E. Kolpakov

Added ability to use HTML LightChild in question blocks

parent 850080ed
......@@ -26,6 +26,7 @@
import logging
from .light_children import LightChild, Scope, String
from .utils import loader, ContextConstants
# Globals ###########################################################
......@@ -41,3 +42,16 @@ class ChoiceBlock(LightChild):
"""
value = String(help="Value of the choice when selected", scope=Scope.content, default="")
content = String(help="Human-readable version of the choice value", scope=Scope.content, default="")
has_children = True
def render(self):
# return self.content
"""
Returns a fragment containing the formatted tip
"""
fragment, named_children = self.get_children_fragment({ContextConstants.AS_TEMPLATE: False})
fragment.add_content(loader.render_template('templates/html/choice.html', {
'self': self,
'named_children': named_children,
}))
return self.xblock_container.fragment_text_rewriting(fragment)
......@@ -33,6 +33,7 @@ from .light_children import LightChild, Scope, String
# Globals ###########################################################
from .utils import ContextConstants
log = logging.getLogger(__name__)
......@@ -56,7 +57,7 @@ class HTMLBlock(LightChild):
return block
def student_view(self, context=None):
as_template = context.get('as_template', True) if context is not None else True
as_template = context.get(ContextConstants.AS_TEMPLATE, True) if context is not None else True
if as_template:
return Fragment(u"<script type='text/template' id='{}'>\n{}\n</script>".format(
'light-child-template',
......
......@@ -80,3 +80,13 @@
text-indent: -22px;
line-height: 1.3;
}
.mentoring .choices-list .choice-text > div.xblock-light-child,
.mentoring .choices-list .choice-text > div.xblock-light-child > div{
/*
HTML Light Child content is wrapped in two divs: div.xblock-light-child and just div
On the other hand, choice are usually rendered inline.
Hence, we render first two divs inline, than all the actual content of HTML is rendered as is
*/
display: inline;
}
......@@ -31,7 +31,7 @@ from .choice import ChoiceBlock
from .step import StepMixin
from .light_children import LightChild, Scope, String, Float
from .tip import TipBlock
from .utils import loader
from .utils import loader, ContextConstants
# Globals ###########################################################
......@@ -75,7 +75,7 @@ class QuestionnaireAbstractBlock(LightChild, StepMixin):
def student_view(self, context=None):
name = self.__class__.__name__
as_template = context.get('as_template', True) if context is not None else True
as_template = context.get(ContextConstants.AS_TEMPLATE, True) if context is not None else True
if str(self.type) not in self.valid_types:
raise ValueError(u'Invalid value for {}.type: `{}`'.format(name, self.type))
......
<span class="choice-text">
{% if self.content %}{{ self.content }}{% endif %}
{% for name, c in named_children %}
{{c.body_html|safe}}
{% endfor %}
</span>
\ No newline at end of file
......@@ -8,7 +8,8 @@
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label class="choice-label">
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == choice.value %} checked{% endif %} />{{ choice.content }}
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == choice.value %} checked{% endif %} />
{{ choice.render.body_html|safe }}
</label>
<div class="choice-tips"></div>
</div>
......
......@@ -34,7 +34,9 @@
{% for choice in custom_choices %}
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == '{{ choice.value }}' %} checked{% endif %} />{{ choice.content }}</label>
<label><input type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == '{{ choice.value }}' %} checked{% endif %} />
{{ choice.render.body_html|safe }}
</label>
<div class="choice-tips"></div>
</div>
{% endfor %}
......
......@@ -11,7 +11,7 @@
<input class="choice-selector" type="checkbox" name="{{ self.name }}"
value="{{ choice.value }}"
{% if choice.value in self.student_choices %} checked{% endif %} />
{{ choice.content }}
{{ choice.render.body_html|safe }}
</label>
<div class="choice-tips"></div>
</div>
......
......@@ -89,3 +89,7 @@ class XBlockWithChildrenFragmentsMixin(object):
for name, child_fragment in named_children:
fragment.add_content(child_fragment.content)
return fragment
class ContextConstants(object):
AS_TEMPLATE = 'as_template'
\ No newline at end of file
......@@ -36,7 +36,7 @@ class AnswerBlockTest(MentoringBaseTest):
# Answer should initially be blank on all instances with the same answer name
mentoring = self.go_to_page('Answer Edit 2')
answer1_bis = mentoring.find_element_by_css_selector('.xblock textarea')
answer1_bis = mentoring.find_element_by_css_selector('textarea')
answer1_readonly = mentoring.find_element_by_css_selector('blockquote.answer.read_only')
self.assertEqual(answer1_bis.get_attribute('value'), '')
self.assertEqual(answer1_readonly.text, '')
......@@ -47,7 +47,7 @@ class AnswerBlockTest(MentoringBaseTest):
self.assertEqual(header1.text, 'XBlock: Answer Edit 1')
# Check <html> child
p = mentoring.find_element_by_css_selector('div.xblock p')
p = mentoring.find_element_by_css_selector('p')
self.assertEqual(p.text, 'This should be displayed in the answer_edit scenario')
# Initial unsubmitted text
......@@ -77,7 +77,7 @@ class AnswerBlockTest(MentoringBaseTest):
# Answer content should show on a different instance with the same name
mentoring = self.go_to_page('Answer Edit 2')
answer1_bis = mentoring.find_element_by_css_selector('.xblock textarea')
answer1_bis = mentoring.find_element_by_css_selector('textarea')
answer1_readonly = mentoring.find_element_by_css_selector('blockquote.answer.read_only')
self.assertEqual(answer1_bis.get_attribute('value'), 'This is the answer. It has a second statement.')
self.assertEqual(answer1_readonly.text, 'This is the answer. It has a second statement.')
......
......@@ -183,3 +183,21 @@ class MCQBlockTest(MentoringBaseTest):
mentoring.click()
self.assertFalse(item_feedback_popup.is_displayed())
def test_mcq_html_choices(self):
mentoring = self.go_to_page('Mrq With Html Choices')
choices_list = mentoring.find_element_by_css_selector(".choices-list")
contents = [
"<b>Its elegance</b>",
"<i>Its beauty</i>",
"<strong>Its gracefulness</strong>",
'<span style="font-color:red">Its bugs</span>'
]
for index, expected_content in enumerate(contents):
choice_wrapper = choices_list.find_elements_by_css_selector(".choice")[index]
choice_label = choice_wrapper.find_element_by_css_selector(".choice-label .choice-text")
light_child = choice_label.find_element_by_css_selector(".xblock-light-child")
content = light_child.find_element_by_css_selector("div").get_attribute('innerHTML')
self.assertEqual(content, expected_content)
<vertical_demo>
<mentoring url_name="mcq_with_comments" display_name="MRQ Exercise 7" weight="1" enforce_dependency="false">
<title>MRQ With Resizable popups</title>
<mrq name="mrq_1_1_7" type="choices">
<question>What do you like in this MRQ?</question>
<choice value="elegance"><html><b>Its elegance</b></html></choice>
<choice value="beauty"><html><i>Its beauty</i></html></choice>
<choice value="gracefulness"><html><strong>Its gracefulness</strong></html></choice>
<choice value="bugs"><html><span style="font-color:red">Its bugs</span></html></choice>
<tip require="gracefulness" width ="200" height = "200">This MRQ is indeed very graceful</tip>
<tip require="elegance" width ="600" height = "800">This is something everyone has to like about this MRQ</tip>
<tip require="beauty" width ="400" height = "600">This is something everyone has to like about beauty</tip>
<tip reject="bugs" width = "100" height = "200">Nah, there isn\'t any!</tip>
</mrq>
<message type="completed">
<html><p>Congratulations!</p></html>
</message>
<message type="incomplete">
<html><p>Still some work to do...</p></html>
</message>
</mentoring>
</vertical_demo>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment