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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user