Commit 4788bc70 by Braden MacDonald

Fix major bugs with the JavaScript that only occurred in Studio

1. MRQBlock initialization function had an unused parameter that Studio's runtime crashed on
2. The result of an assessment's JS runtime.children() call was different if the first child was an HTMLModule compared to an html_demo XBlock. This broke assessments. We now properly filter the result of .children() to only use actual question "steps"
parent 297d77d5
...@@ -152,7 +152,7 @@ class AnswerBlock(AnswerMixin, StepMixin, StudioEditableXBlockMixin, XBlock): ...@@ -152,7 +152,7 @@ class AnswerBlock(AnswerMixin, StepMixin, StudioEditableXBlockMixin, XBlock):
return student_input return student_input
def mentoring_view(self, context=None): def fallback_view(self, view_name, context=None):
context = context or {} context = context or {}
context['self'] = self context['self'] = self
html = loader.render_template('templates/html/answer_editable.html', context) html = loader.render_template('templates/html/answer_editable.html', context)
......
...@@ -141,7 +141,7 @@ function RatingBlock(runtime, element) { ...@@ -141,7 +141,7 @@ function RatingBlock(runtime, element) {
return MCQBlock(runtime, element); return MCQBlock(runtime, element);
} }
function MRQBlock(runtime, element, mentoring) { function MRQBlock(runtime, element) {
return { return {
mode: null, mode: null,
mentoring: null, mentoring: null,
......
...@@ -135,6 +135,15 @@ class QuestionnaireAbstractBlock(StudioEditableXBlockMixin, StudioContainerXBloc ...@@ -135,6 +135,15 @@ class QuestionnaireAbstractBlock(StudioEditableXBlockMixin, StudioContainerXBloc
def mentoring_view(self, context=None): def mentoring_view(self, context=None):
return self.student_view(context) return self.student_view(context)
def assessment_step_view(self, context=None):
"""
assessment_step_view is the same as mentoring_view, except its DIV will have a different
class (.xblock-v1-assessment_step_view) that we use for assessments to hide all the
steps with CSS and to detect which children of mentoring are "Steps" and which are just
decorative elements/instructions.
"""
return self.mentoring_view(context)
@property @property
def custom_choices(self): def custom_choices(self):
custom_choices = [] custom_choices = []
......
...@@ -188,20 +188,20 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -188,20 +188,20 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
for child_id in self.children: for child_id in self.children:
child = self.runtime.get_block(child_id) child = self.runtime.get_block(child_id)
if isinstance(child, MentoringMessageBlock): if isinstance(child, MentoringMessageBlock):
pass # TODO pass
else: else:
try: try:
if self.is_assessment and isinstance(child, StepMixin):
child_fragment = child.render('assessment_step_view', context)
else:
child_fragment = child.render('mentoring_view', context) child_fragment = child.render('mentoring_view', context)
except NoSuchViewError: except NoSuchViewError:
if child.scope_ids.block_type == 'html': if child.scope_ids.block_type == 'html' and getattr(self.runtime, 'is_author_mode', False):
if getattr(self.runtime, 'is_author_mode', False):
# html block doesn't support mentoring_view, and if we use student_view Studio will wrap # html block doesn't support mentoring_view, and if we use student_view Studio will wrap
# it in HTML that we don't want in the preview. So just render its HTML directly: # it in HTML that we don't want in the preview. So just render its HTML directly:
child_fragment = Fragment(child.data) child_fragment = Fragment(child.data)
else: else:
child_fragment = child.render('student_view', context) child_fragment = child.render('student_view', context)
else:
raise # This type of child is not supported.
fragment.add_frag_resources(child_fragment) fragment.add_frag_resources(child_fragment)
child_content += child_fragment.content child_content += child_fragment.content
......
...@@ -105,6 +105,11 @@ ...@@ -105,6 +105,11 @@
padding: 20px; padding: 20px;
} }
.mentoring .assessment-question-block > .xblock-v1-assessment_step_view,
.mentoring .assessment-question-block > .xblock-assessment_step_view {
display: none; /* Each "step" (question) is hidden at first, and shown one at a time by JavaScript */
}
.mentoring .assessment-checkmark { .mentoring .assessment-checkmark {
margin-right: 10px; margin-right: 10px;
} }
......
...@@ -2,6 +2,7 @@ function MentoringBlock(runtime, element) { ...@@ -2,6 +2,7 @@ function MentoringBlock(runtime, element) {
var attemptsTemplate = _.template($('#xblock-attempts-template').html()); var attemptsTemplate = _.template($('#xblock-attempts-template').html());
var data = $('.mentoring', element).data(); var data = $('.mentoring', element).data();
var children = runtime.children(element); var children = runtime.children(element);
var steps = runtime.children(element).filter(function(c) { return c.element.className.indexOf('assessment_step_view') > -1; });
var step = data.step; var step = data.step;
var mentoring = { var mentoring = {
...@@ -12,8 +13,9 @@ function MentoringBlock(runtime, element) { ...@@ -12,8 +13,9 @@ function MentoringBlock(runtime, element) {
children: children, children: children,
initChildren: initChildren, initChildren: initChildren,
getChildByName: getChildByName, getChildByName: getChildByName,
hideAllChildren: hideAllChildren, hideAllSteps: hideAllSteps,
step: step, step: step,
steps: steps,
publish_event: publish_event publish_event: publish_event
}; };
...@@ -88,9 +90,9 @@ function MentoringBlock(runtime, element) { ...@@ -88,9 +90,9 @@ function MentoringBlock(runtime, element) {
} }
} }
function hideAllChildren() { function hideAllSteps() {
for (var i=0; i < children.length; i++) { for (var i=0; i < steps.length; i++) {
$(children[i].element).hide(); $(steps[i].element).hide();
} }
} }
......
...@@ -16,8 +16,8 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -16,8 +16,8 @@ function MentoringAssessmentView(runtime, element, mentoring) {
// Clear all selections // Clear all selections
$('input[type=radio], input[type=checkbox]', element).prop('checked', false); $('input[type=radio], input[type=checkbox]', element).prop('checked', false);
// hide all children // hide all questions
mentoring.hideAllChildren(); mentoring.hideAllSteps();
$('.grade').html(''); $('.grade').html('');
$('.attempts').html(''); $('.attempts').html('');
...@@ -96,11 +96,11 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -96,11 +96,11 @@ function MentoringAssessmentView(runtime, element, mentoring) {
} }
function isLastChild() { function isLastChild() {
return (active_child == mentoring.children.length-1); return (active_child == mentoring.steps.length-1);
} }
function isDone() { function isDone() {
return (active_child == mentoring.children.length); return (active_child == mentoring.steps.length);
} }
function displayNextChild() { function displayNextChild() {
...@@ -108,7 +108,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -108,7 +108,7 @@ function MentoringAssessmentView(runtime, element, mentoring) {
// find the next real child block to display. HTMLBlock are always displayed // find the next real child block to display. HTMLBlock are always displayed
active_child++; active_child++;
var child = mentoring.children[active_child]; var child = mentoring.steps[active_child];
$(child.element).show(); $(child.element).show();
mentoring.publish_event({ mentoring.publish_event({
event_type: 'xblock.mentoring.assessment.shown', event_type: 'xblock.mentoring.assessment.shown',
...@@ -164,7 +164,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -164,7 +164,7 @@ function MentoringAssessmentView(runtime, element, mentoring) {
function submit() { function submit() {
var success = true; var success = true;
var data = {}; var data = {};
var child = mentoring.children[active_child]; var child = mentoring.steps[active_child];
if (child && child.name !== undefined) { if (child && child.name !== undefined) {
data[child.name] = callIfExists(child, 'submit'); data[child.name] = callIfExists(child, 'submit');
} }
...@@ -178,12 +178,12 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -178,12 +178,12 @@ function MentoringAssessmentView(runtime, element, mentoring) {
function validateXBlock() { function validateXBlock() {
var is_valid = true; var is_valid = true;
var data = $('.attempts', element).data(); var data = $('.attempts', element).data();
var children = mentoring.children; var steps = mentoring.steps;
// if ((data.max_attempts > 0) && (data.num_attempts >= data.max_attempts)) { // if ((data.max_attempts > 0) && (data.num_attempts >= data.max_attempts)) {
// is_valid = false; // is_valid = false;
// } // }
var child = mentoring.children[active_child]; var child = mentoring.steps[active_child];
if (child && child.name !== undefined) { if (child && child.name !== undefined) {
var child_validation = callIfExists(child, 'validate'); var child_validation = callIfExists(child, 'validate');
if (_.isBoolean(child_validation)) { if (_.isBoolean(child_validation)) {
......
...@@ -5,6 +5,13 @@ ...@@ -5,6 +5,13 @@
<p>Please answer the questions below.</p> <p>Please answer the questions below.</p>
</html_demo> </html_demo>
<html_demo>
We need an XBlock with JavaScript here to test that it doesn't interfere
with the assessment, since it will show up in runtime(element).children,
but it is not a "step" element:
</html_demo>
<acid/>
<answer name="goal" question="What is your goal?" /> <answer name="goal" question="What is your goal?" />
<mcq name="mcq_1_1" question="Do you like this MCQ?" correct_choices="yes"> <mcq name="mcq_1_1" question="Do you like this MCQ?" correct_choices="yes">
......
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