Iniital refactor of capa styling for basic checkbox and multiple choice problem types, including additional comments to sass styles

This commit is contained in:
Marco Morales
2015-05-20 08:31:33 -04:00
parent 61782ff9fa
commit 8acc72975e
12 changed files with 391 additions and 140 deletions

View File

@@ -1,24 +1,5 @@
<form class="choicegroup capa_inputtype" id="inputtype_${id}">
<div class="indicator_container">
% if input_type == 'checkbox' or not value:
<span class="status ${status.classname if show_correctness != 'never' else 'unanswered'}"
id="status_${id}"
aria-describedby="inputtype_${id}">
<span class="sr">
%for choice_id, choice_description in choices:
% if choice_id in value:
${choice_description},
%endif
%endfor
-
${status.display_name}
</span>
</span>
% endif
</div>
<fieldset role="${input_type}group" aria-label="${label}">
% for choice_id, choice_description in choices:
<label for="input_${id}_${choice_id}"
## If the student has selected this choice...
@@ -58,7 +39,23 @@
% endfor
<span id="answer_${id}"></span>
</fieldset>
<div class="indicator_container">
% if input_type == 'checkbox' or not value:
<span class="status ${status.classname if show_correctness != 'never' else 'unanswered'}"
id="status_${id}"
aria-describedby="inputtype_${id}" data-tooltip="This is ${status.display_name}.">
<span class="sr">
%for choice_id, choice_description in choices:
% if choice_id in value:
${choice_description},
%endif
%endfor
-
${status.display_name}
</span>
</span>
% endif
</div>
% if show_correctness == "never" and (value or status not in ['unsubmitted']):
<div class="capa_alert">${submitted_message}</div>
%endif

View File

@@ -9,12 +9,7 @@
<section id="choicetextinput_${id}" class="choicetextinput">
<form class="choicetextgroup capa_inputtype" id="inputtype_${id}">
<div class="script_placeholder" data-src="${STATIC_URL}js/capa/choicetextinput.js"/>
<div class="indicator_container">
% if input_type == 'checkbox' or not element_checked:
<span class="status ${status.classname}" id="status_${id}"></span>
% endif
</div>
<fieldset aria-label="${label}">
% for choice_id, choice_description in choices:
<%choice_id= choice_id %>
@@ -62,6 +57,13 @@
<span id="answer_${id}"></span>
</fieldset>
<input class= "choicetextvalue" type="hidden" name="input_${id}{}" id="input_${id}" value="${value|h}" />
<div class="indicator_container">
% if input_type == 'checkbox' or not element_checked:
<span class="status ${status.classname}" id="status_${id}"></span>
% endif
</div>
% if show_correctness == "never" and (value or status not in ['unsubmitted']):
<div class="capa_alert">${_(submitted_message)}</div>
%endif

View File

@@ -10,9 +10,11 @@
% endif
/>
<p class="status" id="${id}_status">
${status.display_name}
</p>
<span class="status" id="${id}_status" data-tooltip="This is ${status.display_name}.">
<span class="sr">
${status.display_name}
</span>
</span>
<div id="input_${id}_preview" class="equation">
\[\]

View File

@@ -13,12 +13,13 @@
</select>
<span id="answer_${id}"></span>
<span class="status ${status.classname}"
id="status_${id}"
aria-describedby="input_${id}">
<span class="sr">${value|h} - ${status.display_name}</span>
</span>
<div class="indicator_container">
<span class="status ${status.classname}"
id="status_${id}"
aria-describedby="input_${id}" data-tooltip="This is ${status.display_name}">
<span class="sr">${value|h} - ${status.display_name}</span>
</span>
</div>
% if msg:
<span class="message">${msg|n}</span>
% endif

View File

@@ -27,18 +27,20 @@
/>
${trailing_text | h}
<p class="status"
<span class="status"
%if status != 'unsubmitted':
%endif
aria-describedby="input_${id}">
%if value:
${value|h}
% else:
${label}
%endif
-
${status.display_name}
</p>
aria-describedby="input_${id}" data-tooltip="This is ${status.display_name}.">
<span class="sr">
%if value:
${value|h}
% else:
${label}
%endif
-
${status.display_name}
</span>
</span>
<p id="answer_${id}" class="answer"></p>

View File

@@ -388,9 +388,9 @@ class TextlineTemplateTest(TemplateTestCase):
xpath = "//div[@class='%s ']" % div_class
self.assert_has_xpath(xml, xpath, self.context)
# Expect that we get a <p> with class="status"
# Expect that we get a <span> with class="status"
# (used to by CSS to draw the green check / red x)
self.assert_has_text(xml, "//p[@class='status']",
self.assert_has_text(xml, "//span[@class='status']",
status_mark, exact=False)
def test_label(self):

View File

@@ -1,8 +1,54 @@
// capa - styling
// ====================
// Table of Contents
// * +Variables - Capa
// * +Extends - Capa
// * +Mixins - Status Icon - Capa
// * +Resets - Deprecate Please
// * +Problem - Base
// * +Problem - Choice Group
// * +Problem - Misc, Unclassified Mess
// * +Problem - Text Input, Numerical Input
// * +Problem - Option Input (Dropdown)
// * +Problem - CodeMirror
// * +Problem - Misc, Unclassified Mess Part 2
// * +Problem - Rubric
// * +Problem - Annotation
// * +Problem - Choice Text Group
// +Variables - Capa
// ====================
$annotation-yellow: rgba(255,255,10,0.3);
$color-copy-tip: rgb(100,100,100);
$color-success: rgb(0, 136, 1);
$color-fail: rgb(212, 64, 64);
$correct: $green-d1;
$incorrect: $red;
// +Extends - Capa
// ====================
// Duplicated from _mixins.scss due to xmodule compilation, inheritance issues
%use-font-awesome {
font-family: FontAwesome;
-webkit-font-smoothing: antialiased;
display: inline-block;
speak: none;
}
// +Mixins - Status Icon - Capa
// ====================
@mixin status-icon($color: $gray, $fontAwesomeIcon: "\f00d"){
&:after {
@extend %use-font-awesome;
@include margin-left(17px);
color: $color;
font-size: 1.2em;
content: $fontAwesomeIcon;
}
}
// +Resets - Deprecate Please
// ====================
h2 {
margin-top: 0;
margin-bottom: ($baseline*0.75);
@@ -24,12 +70,12 @@ h2 {
.feedback-hint-correct {
margin-top: ($baseline/2);
color: $color-success;
color: $correct;
}
.feedback-hint-incorrect {
margin-top: ($baseline/2);
color: $color-fail;
color: $incorrect;
}
.feedback-hint-text {
@@ -55,10 +101,9 @@ h2 {
display: block;
}
iframe[seamless]{
overflow: hidden;
padding: 0px;
padding: 0;
border: 0px none transparent;
background-color: transparent;
}
@@ -68,13 +113,15 @@ iframe[seamless]{
}
div.problem-progress {
@include padding-left($baseline/4);
display: inline-block;
padding-left: ($baseline/4);
color: #666;
color: $gray-d1;
font-weight: 100;
font-size: em(16);
}
// +Problem - Base
// ====================
div.problem {
@media print {
display: block;
@@ -89,7 +136,11 @@ div.problem {
.inline {
display: inline;
}
}
// +Problem - Choice Group
// ====================
div.problem {
.choicegroup {
@include clearfix();
min-width: 100px;
@@ -97,51 +148,100 @@ div.problem {
width: 100px;
label {
@include float(left);
@include box-sizing(border-box);
display: inline-block;
clear: both;
margin-bottom: ($baseline/4);
width: 100%;
border: 2px solid $gray-l4;
border-radius: 3px;
margin-bottom: ($baseline/2);
padding: ($baseline/2);
&.choicegroup_correct {
&:after {
margin-left: ($baseline*0.75);
content: url('../images/correct-icon.png');
@include status-icon($correct, "\f00c");
border: 2px solid $correct;
// keep green for correct answers on hover.
&:hover {
border-color: $correct;
}
}
&.choicegroup_incorrect {
&:after {
margin-left: ($baseline*0.75);
content: url('../images/incorrect-icon.png');
@include status-icon($incorrect, "\f00d");
border: 2px solid $incorrect;
// keep red for incorrect answers on hover.
&:hover {
border-color: $incorrect;
}
}
&:hover {
border: 2px solid $blue;
}
}
.indicator_container {
@include float(left);
display: inline-block;
min-height: 1px;
width: 25px;
height: 1px;
@include margin-right(15px);
}
fieldset {
@include box-sizing(border-box);
margin: 0px 0px $baseline;
@include padding-left($baseline);
@include border-left(1px solid #ddd);
}
input[type="radio"],
input[type="checkbox"] {
@include float(left);
@include margin(4px, 8px, 0, 0);
@include margin(($baseline/4) ($baseline/2) ($baseline/4) ($baseline/4));
}
text {
@include margin-left(25px);
display: inline;
margin-left: 25px;
}
}
}
// +Problem - Status Indicators
// ====================
// Summary status indicators shown after the input area
div.problem {
.indicator_container {
.status {
width: 20px;
height: 20px;
// CASE: correct answer
&.correct {
@include status-icon($correct, "\f00c");
}
// CASE: incorrect answer
&.incorrect {
@include status-icon($incorrect, "\f00d");
}
// CASE: unanswered
&.unanswered {
@include status-icon($gray-l4, "\f128");
}
// CASE: processing
&.processing {
// add once spinner is rotated through animations
//@include status-icon($gray-d1, "\f110", 0);
}
}
}
}
// +Problem - Misc, Unclassified Mess
// ====================
div.problem {
ol.enumerate {
li {
&:before {
@@ -187,17 +287,22 @@ div.problem {
}
}
// known classes using this div: .indicator_container, moved to section above
div {
// TO-DO: Styling used by advanced capa problem types. Should be synced up to use .status class
p {
&.answer {
margin-top: -2px;
}
&.status {
margin: 8px 0 0 $baseline/2;
@include margin(8px, 0, 0, $baseline/2);
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
span.clarification i {
font-style: normal;
&:hover {
@@ -241,7 +346,21 @@ div.problem {
}
}
&.incorrect, &.incomplete, &.ui-icon-close {
&.ui-icon-close {
p.status {
display: inline-block;
width: 20px;
height: 20px;
background: url('../images/incorrect-icon.png') center center no-repeat;
}
input {
border-color: red;
}
}
&.incorrect, &.incomplete {
p.status {
display: inline-block;
width: 20px;
@@ -260,9 +379,9 @@ div.problem {
}
p.answer {
@include margin-left($baseline/2);
display: inline-block;
margin-bottom: 0;
margin-left: $baseline/2;
&:before {
display: inline;
@@ -287,8 +406,8 @@ div.problem {
}
img.loading {
@include padding-left($baseline/2);
display: inline-block;
padding-left: ($baseline/2);
}
span {
@@ -303,7 +422,7 @@ div.problem {
background: #f1f1f1;
}
}
}
}
// Hides equation previews in symbolic response problems when printing
[id^='display'].equation {
@@ -312,8 +431,9 @@ div.problem {
}
}
//TO-DO: review and deprecate all these styles within span {}
span {
&.unanswered, &.ui-icon-bullet {
&.ui-icon-bullet {
display: inline-block;
position: relative;
top: 4px;
@@ -331,7 +451,7 @@ div.problem {
background: url('../images/spinner.gif') center center no-repeat;
}
&.correct, &.ui-icon-check {
&.ui-icon-check {
display: inline-block;
position: relative;
top: 3px;
@@ -349,7 +469,7 @@ div.problem {
background: url('../images/partially-correct-icon.png') center center no-repeat;
}
&.incorrect, &.incomplete, &.ui-icon-close {
&.incomplete, &.ui-icon-close {
display: inline-block;
position: relative;
top: 3px;
@@ -360,8 +480,8 @@ div.problem {
}
.reload {
float:right;
margin: $baseline/2;
@include float(right);
margin: ($baseline/2);
}
@@ -457,15 +577,6 @@ div.problem {
}
}
form.option-input {
margin: -$baseline/2 0 $baseline;
padding-bottom: $baseline;
select {
margin-right: flex-gutter();
}
}
ul {
margin-bottom: lh();
margin-left: .75em;
@@ -584,6 +695,93 @@ div.problem {
white-space: pre;
}
}
}
// +Problem - Text Input, Numerical Input
// ====================
.problem {
.capa_inputtype.textline, .inputtype.formulaequationinput {
input {
@include box-sizing(border-box);
border: 2px solid $gray-l4;
border-radius: 3px;
height: 46px;
min-width: 160px;
}
> .incorrect, .correct, .unanswered {
.status {
display: inline-block;
background: none;
margin-top: ($baseline/2);
}
}
// CASE: incorrect answer
> .incorrect {
input {
border: 2px solid $incorrect;
}
.status {
@include status-icon($incorrect, "\f00d");
}
}
// CASE: correct answer
> .correct {
input {
border: 2px solid $correct;
}
.status {
@include status-icon($correct, "\f00c");
}
}
// CASE: unanswered
> .unanswered {
input {
border: 2px solid $gray-l4;
}
.status {
@include status-icon($gray-l4, "\f128");
}
}
}
}
// +Problem - Option Input (Dropdown)
// ====================
.problem {
.inputtype.option-input {
margin: (-$baseline/2) 0 $baseline;
padding-bottom: $baseline;
select {
@include margin-right($baseline/2);
}
.indicator_container {
display: inline-block;
.status.correct:after, .status.incorrect:after {
@include margin-left(0);
}
}
}
}
// +Problem - CodeMirror
// ====================
div.problem {
.CodeMirror {
border: 1px solid black;
@@ -634,7 +832,52 @@ div.problem {
.CodeMirror-scroll {
margin-right: 0px;
}
}
// +Problem - Actions
// ====================
div.problem .action {
margin-top: $baseline;
.save, .check, .show, .reset, .hint-button {
@include margin-right($baseline/2);
margin-bottom: ($baseline/2);
height: ($baseline*2);
vertical-align: middle;
font-weight: 600;
text-transform: uppercase;
}
.save {
@extend .blue-button !optional;
}
.show {
.show-label {
font-weight: 600;
font-size: 1.0em;
}
}
.submission_feedback {
// background: #F3F3F3;
// border: 1px solid #ddd;
// border-radius: 3px;
// padding: 8px 12px;
// margin-top: ($baseline/2);
display: inline-block;
margin-top: 8px;
@include margin-left($baseline/2);
color: $gray-d1;
font-style: italic;
-webkit-font-smoothing: antialiased;
}
}
// +Problem - Misc, Unclassified Mess Part 2
// ====================
div.problem {
hr {
float: none;
clear: both;
@@ -663,47 +906,7 @@ div.problem {
padding: lh();
border: 1px solid $gray-l3;
}
div.action {
margin-top: $baseline;
.save, .check, .show, .reset, .hint-button {
height: ($baseline*2);
vertical-align: middle;
font-weight: 600;
@media print {
display: none;
}
}
.save {
@extend .blue-button !optional;
}
.show {
.show-label {
font-weight: 600;
font-size: 1.0em;
}
}
.submission_feedback {
// background: #F3F3F3;
// border: 1px solid #ddd;
// border-radius: 3px;
// padding: 8px 12px;
// margin-top: ($baseline/2);
display: inline-block;
margin-top: 8px;
@include margin-left($baseline/2);
color: #666;
font-style: italic;
-webkit-font-smoothing: antialiased;
}
}
.detailed-solution {
> p:first-child {
color: #aaa;
@@ -951,7 +1154,12 @@ div.problem {
}
}
}
}
// +Problem - Rubric
// ====================
div.problem {
.rubric {
tr {
margin: ($baseline/2) 0;
@@ -1004,7 +1212,11 @@ div.problem {
display: none;
}
}
}
// +Problem - Annotation
// ====================
div.problem {
.annotation-input {
margin: 0 0 1em 0;
border: 1px solid $gray-l3;
@@ -1102,8 +1314,12 @@ div.problem {
}
}
}
}
.choicetextgroup{
// +Problem - Choice Text Group
// ====================
div.problem {
.choicetextgroup {
@extend .choicegroup;
input[type="text"]{

View File

@@ -468,7 +468,7 @@ class @Problem
# They should set handlers on each <input> to reset the whole.
formulaequationinput: (element) ->
$(element).find('input').on 'input', ->
$p = $(element).find('p.status')
$p = $(element).find('span.status')
`// Translators: the word unanswered here is about answering a problem the student must solve.`
$p.parent().removeClass().addClass "unanswered"
@@ -496,7 +496,7 @@ class @Problem
textline: (element) ->
$(element).find('input').on 'input', ->
$p = $(element).find('p.status')
$p = $(element).find('span.status')
`// Translators: the word unanswered here is about answering a problem the student must solve.`
$p.parent().removeClass("correct incorrect").addClass "unanswered"

View File

@@ -23,6 +23,7 @@
// * +Content - Screenreader Text - Extend
// * +Content - Text Wrap - Extend
// * +Content - Text Truncate - Extend
// * +Icon - Font-Awesome - Extend
// +Font Sizing - Mixin
// ====================
@@ -428,3 +429,11 @@
text-overflow: ellipsis;
}
// * +Icon - Font-Awesome - Extend
// ====================
%use-font-awesome {
font-family: FontAwesome;
-webkit-font-smoothing: antialiased;
display: inline-block;
speak: none;
}

View File

@@ -176,11 +176,11 @@ Feature: LMS.Answer problems
Scenario: I can view and hide the answer if the problem has it:
Given I am viewing a "numerical" that shows the answer "always"
When I press the button with the label "Show Answer"
Then the Show/Hide button label is "Hide Answer"
When I press the button with the label "SHOW ANSWER"
Then the Show/Hide button label is "HIDE ANSWER"
And I should see "4.14159" somewhere in the page
When I press the button with the label "Hide Answer"
Then the Show/Hide button label is "Show Answer"
When I press the button with the label "HIDE ANSWER"
Then the Show/Hide button label is "SHOW ANSWER"
And I should not see "4.14159" anywhere on the page
Scenario: I can see my score on a problem when I answer it and after I reset it

View File

@@ -82,6 +82,28 @@ $gray-d2: shade($gray,40%); // #4c4c4c
$gray-d3: shade($gray,60%); // #323232
$gray-d4: shade($gray,80%); // #191919
// TO-DO: once existing lms $blue is removed, change $cms-blue to $blue.
$cms-blue: rgb(0, 159, 230);
$blue-l1: tint($cms-blue,20%);
$blue-l2: tint($cms-blue,40%);
$blue-l3: tint($cms-blue,60%);
$blue-l4: tint($cms-blue,80%);
$blue-l5: tint($cms-blue,90%);
$blue-d1: shade($cms-blue,20%);
$blue-d2: shade($cms-blue,40%);
$blue-d3: shade($cms-blue,60%);
$blue-d4: shade($cms-blue,80%);
$blue-s1: saturate($cms-blue,15%);
$blue-s2: saturate($cms-blue,30%);
$blue-s3: saturate($cms-blue,45%);
$blue-u1: desaturate($cms-blue,15%);
$blue-u2: desaturate($cms-blue,30%);
$blue-u3: desaturate($cms-blue,45%);
$blue-t0: rgba($cms-blue, 0.125);
$blue-t1: rgba($cms-blue, 0.25);
$blue-t2: rgba($cms-blue, 0.50);
$blue-t3: rgba($cms-blue, 0.75);
$pink: rgb(182,37,103); // #b72567;
$pink-l1: tint($pink,20%);
$pink-l2: tint($pink,40%);

View File

@@ -28,7 +28,7 @@ h1.top-header {
.light-button, a.light-button, // only used in askbot as classes
.gray-button {
@include button(simple, #eee);
@include button(simple, $gray-l5);
@extend .button-reset;
font-size: em(13);
}