Aids styleability of CAPA checkbox and radio problems

by making CAPA <input> elements siblings of their <label>s, instead of children.

Also:

* Moves radio submitted status block down below the problem
  to match the checkbox problem status blocks.
* Marks submitted choicegroup answers with a class
This commit is contained in:
Jillian Vogel
2019-07-23 16:23:40 +09:30
parent 3e4e027234
commit fb981bfbbe
6 changed files with 149 additions and 123 deletions

View File

@@ -222,52 +222,6 @@ div.problem {
&::after {
@include margin-left($baseline*0.75);
}
&:hover {
border: 2px solid $blue;
}
&.choicegroup_correct {
@include status-icon($correct, $checkmark-icon);
border: 2px solid $correct;
// keep green for correct answers on hover.
&:hover {
border-color: $correct;
}
}
&.choicegroup_partially-correct {
@include status-icon($partially-correct, $asterisk-icon);
border: 2px solid $partially-correct;
// keep green for correct answers on hover.
&:hover {
border-color: $partially-correct;
}
}
&.choicegroup_incorrect {
@include status-icon($incorrect, $cross-icon);
border: 2px solid $incorrect;
// keep red for incorrect answers on hover.
&:hover {
border-color: $incorrect;
}
}
&.choicegroup_submitted {
border: 2px solid $submitted;
// keep blue for submitted answers on hover.
&:hover {
border-color: $submitted;
}
}
}
.indicator-container {
@@ -284,6 +238,41 @@ div.problem {
input[type="checkbox"] {
@include margin(($baseline/4) ($baseline/2) ($baseline/4) ($baseline/4));
}
input {
&:focus,
&:hover {
& + label {
border: 2px solid $blue;
}
}
&,
&:focus,
&:hover {
& + label.choicegroup_correct {
@include status-icon($correct, $checkmark-icon);
border: 2px solid $correct;
}
& + label.choicegroup_partially-correct {
@include status-icon($partially-correct, $asterisk-icon);
border: 2px solid $partially-correct;
}
& + label.choicegroup_incorrect {
@include status-icon($incorrect, $cross-icon);
border: 2px solid $incorrect;
}
& + label.choicegroup_submitted {
border: 2px solid $submitted;
}
}
}
}
// +Problem - Choice Group
@@ -292,6 +281,10 @@ div.problem {
.choicegroup {
@extend %choicegroup-base;
.field {
position: relative;
}
label {
@include padding($baseline/2);
@include padding-left($baseline*1.9);
@@ -308,6 +301,9 @@ div.problem {
position: absolute;
top: em(9);
width: $baseline*1.1;
height: $baseline*1.1;
z-index: 1;
}
legend {
@@ -1628,6 +1624,17 @@ div.problem .imageinput.capa_inputtype {
top: 3px;
width: 25px;
height: 20px;
&.unsubmitted,
&.unanswered {
.status-icon {
content: '';
}
.status-message {
display: none;
}
}
}
.correct {
@@ -1658,6 +1665,17 @@ div.problem .annotation-input {
top: 3px;
width: 25px;
height: 20px;
&.unsubmitted,
&.unanswered {
.status-icon {
content: '';
}
.status-message {
display: none;
}
}
}
.correct {

View File

@@ -230,16 +230,16 @@
// Render 'x point(s) possible (un/graded, results hidden)' if no current score provided.
if (graded) {
progressTemplate = ngettext(
// Translators: %(num_points)s is the number of points possible (examples: 1, 3, 10).;
'%(num_points)s point possible (graded, results hidden)',
'%(num_points)s points possible (graded, results hidden)',
// Translators: {num_points} is the number of points possible (examples: 1, 3, 10).;
'{num_points} point possible (graded, results hidden)',
'{num_points} points possible (graded, results hidden)',
totalScore
);
} else {
progressTemplate = ngettext(
// Translators: %(num_points)s is the number of points possible (examples: 1, 3, 10).;
'%(num_points)s point possible (ungraded, results hidden)',
'%(num_points)s points possible (ungraded, results hidden)',
// Translators: {num_points} is the number of points possible (examples: 1, 3, 10).;
'{num_points} point possible (ungraded, results hidden)',
'{num_points} points possible (ungraded, results hidden)',
totalScore
);
}
@@ -248,14 +248,14 @@
// But if staff has overridden score to a non-zero number, show it
if (graded) {
progressTemplate = ngettext(
// Translators: %(num_points)s is the number of points possible (examples: 1, 3, 10).;
'%(num_points)s point possible (graded)', '%(num_points)s points possible (graded)',
// Translators: {num_points} is the number of points possible (examples: 1, 3, 10).;
'{num_points} point possible (graded)', '{num_points} points possible (graded)',
totalScore
);
} else {
progressTemplate = ngettext(
// Translators: %(num_points)s is the number of points possible (examples: 1, 3, 10).;
'%(num_points)s point possible (ungraded)', '%(num_points)s points possible (ungraded)',
// Translators: {num_points} is the number of points possible (examples: 1, 3, 10).;
'{num_points} point possible (ungraded)', '{num_points} points possible (ungraded)',
totalScore
);
}
@@ -264,25 +264,25 @@
if (graded) {
progressTemplate = ngettext(
// This comment needs to be on one line to be properly scraped for the translators.
// Translators: %(earned)s is the number of points earned. %(possible)s is the total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of points will always be at least 1. We pluralize based on the total number of points (example: 0/1 point; 1/2 points);
'%(earned)s/%(possible)s point (graded)', '%(earned)s/%(possible)s points (graded)',
// Translators: {earned} is the number of points earned. {possible} is the total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of points will always be at least 1. We pluralize based on the total number of points (example: 0/1 point; 1/2 points);
'{earned}/{possible} point (graded)', '{earned}/{possible} points (graded)',
totalScore
);
} else {
progressTemplate = ngettext(
// This comment needs to be on one line to be properly scraped for the translators.
// Translators: %(earned)s is the number of points earned. %(possible)s is the total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of points will always be at least 1. We pluralize based on the total number of points (example: 0/1 point; 1/2 points);
'%(earned)s/%(possible)s point (ungraded)', '%(earned)s/%(possible)s points (ungraded)',
// Translators: {earned} is the number of points earned. {possible} is the total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of points will always be at least 1. We pluralize based on the total number of points (example: 0/1 point; 1/2 points);
'{earned}/{possible} point (ungraded)', '{earned}/{possible} points (ungraded)',
totalScore
);
}
}
progress = interpolate(
progress = edx.StringUtils.interpolate(
progressTemplate, {
earned: curScore,
num_points: totalScore,
possible: totalScore
}, true
}
);
return this.$('.problem-progress').text(progress);
};
@@ -379,7 +379,7 @@
Problem.prototype.render = function(content, focusCallback) {
var that = this;
if (content) {
this.el.html(content);
edx.HtmlUtils.setHtml(this.el, edx.HtmlUtils.HTML(content));
return JavascriptLoader.executeModuleScripts(this.el, function() {
that.setupInputTypes();
that.bind();
@@ -389,7 +389,7 @@
});
} else {
return $.postWithPrefix('' + this.url + '/problem_get', function(response) {
that.el.html(response.html);
edx.HtmlUtils.setHtml(that.el, edx.HtmlUtils.HTML(response.html));
return JavascriptLoader.executeModuleScripts(that.el, function() {
that.setupInputTypes();
that.bind();
@@ -560,11 +560,12 @@
}
));
}
fd.append(element.id, file);
fd.append(element.id, file); // xss-lint: disable=javascript-jquery-append
}
if (element.files.length === 0) {
fileNotSelected = true;
fd.append(element.id, ''); // In case we want to allow submissions with no file
// In case we want to allow submissions with no file
fd.append(element.id, ''); // xss-lint: disable=javascript-jquery-append
}
if (requiredFiles.length !== 0) {
requiredFilesNotSubmitted = true;
@@ -575,18 +576,21 @@
));
}
} else {
fd.append(element.id, element.value);
fd.append(element.id, element.value); // xss-lint: disable=javascript-jquery-append
}
});
if (fileNotSelected) {
errors.push(gettext('You did not select any files to submit.'));
}
errorHtml = '<ul>\n';
errorHtml = '';
for (i = 0, len = errors.length; i < len; i++) {
error = errors[i];
errorHtml += '<li>' + error + '</li>\n';
errorHtml = edx.HtmlUtils.joinHtml(
errorHtml,
edx.HtmlUtils.interpolateHtml(edx.HtmlUtils.HTML('<li>{error}</li>'), {error: error})
);
}
errorHtml += '</ul>';
errorHtml = edx.HtmlUtils.interpolateHtml(edx.HtmlUtils.HTML('<ul>{errors}</ul>'), {errors: errorHtml});
this.gentle_alert(errorHtml);
abortSubmission = fileTooLarge || fileNotSelected || unallowedFileSubmitted || requiredFilesNotSubmitted;
if (abortSubmission) {
@@ -965,6 +969,7 @@
return $(element).find('input').on('input', function() {
var $p;
$p = $(element).find('span.status');
$p.removeClass('correct incorrect submitted');
return $p.parent().removeAttr('class').addClass('unsubmitted');
});
},
@@ -1002,6 +1007,7 @@
return $(element).find('input').on('input', function() {
var $p;
$p = $(element).find('span.status');
$p.removeClass('correct incorrect submitted');
return $p.parent().removeClass('correct incorrect').addClass('unsubmitted');
});
}
@@ -1069,8 +1075,8 @@
results = [];
for (i = 0, len = answer.length; i < len; i++) {
choice = answer[i];
$inputLabel = $element.find('#input_' + inputId + '_' + choice).parent('label');
$inputStatus = $inputLabel.find('#status_' + inputId);
$inputLabel = $element.find('#input_' + inputId + '_' + choice + ' + label');
$inputStatus = $element.find('#status_' + inputId);
// If the correct answer was already Submitted before "Show Answer" was selected,
// the status HTML will already be present. Otherwise, inject the status HTML.
@@ -1078,12 +1084,13 @@
// will be marked as "unanswered". In that case, for correct answers update the
// classes accordingly.
if ($inputStatus.hasClass('unanswered')) {
$inputStatus.removeAttr('class').addClass('status correct');
edx.HtmlUtils.append($inputLabel, edx.HtmlUtils.HTML(correctStatusHtml));
$inputLabel.addClass('choicegroup_correct');
} else if (!$inputLabel.hasClass('choicegroup_correct')) {
// If the status HTML is not already present (due to clicking Submit), append
// the status HTML for correct answers.
edx.HtmlUtils.append($inputLabel, edx.HtmlUtils.HTML(correctStatusHtml));
$inputLabel.removeClass('choicegroup_incorrect');
results.push($inputLabel.addClass('choicegroup_correct'));
}
}
@@ -1182,7 +1189,7 @@
types[key](context, value);
}
});
container.html(canvas);
edx.HtmlUtils.setHtml(container, edx.HtmlUtils.HTML(canvas));
} else {
console.log('Answer is absent for image input with id=' + id); // eslint-disable-line no-console
}