Merge pull request #8151 from edx/marco/capa-styling
Updated styling for basic capa problems (multiple choice, dropdown, checkboxes, numerical input and text input) including support for mobile app experience.
This commit is contained in:
@@ -351,7 +351,7 @@
|
||||
</p>
|
||||
<p>What Apple device competed with the portable CD player?</p>
|
||||
<span><form class="choicegroup capa_inputtype" id="inputtype_i4x-AndyA-ABT101-problem-46d2b65d793549e2876729d55df9a2cb_2_1">
|
||||
<div class="indicator_container">
|
||||
<div class="indicator-container">
|
||||
<span class="unanswered" style="display:inline-block;" id="status_i4x-AndyA-ABT101-problem-46d2b65d793549e2876729d55df9a2cb_2_1"></span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ registry = TagRegistry() # pylint: disable=invalid-name
|
||||
class Status(object):
|
||||
"""
|
||||
Problem status
|
||||
attributes: classname, display_name
|
||||
attributes: classname, display_name, display_tooltip
|
||||
"""
|
||||
css_classes = {
|
||||
# status: css class
|
||||
@@ -77,7 +77,7 @@ class Status(object):
|
||||
'incomplete': 'incorrect',
|
||||
'queued': 'processing',
|
||||
}
|
||||
__slots__ = ('classname', '_status', 'display_name')
|
||||
__slots__ = ('classname', '_status', 'display_name', 'display_tooltip')
|
||||
|
||||
def __init__(self, status, gettext_func=unicode):
|
||||
self.classname = self.css_classes.get(status, status)
|
||||
@@ -90,7 +90,16 @@ class Status(object):
|
||||
'unsubmitted': _('unanswered'),
|
||||
'queued': _('processing'),
|
||||
}
|
||||
tooltips = {
|
||||
# Translators: these are tooltips that indicate the state of an assessment question
|
||||
'correct': _('This is correct.'),
|
||||
'incorrect': _('This is incorrect.'),
|
||||
'unanswered': _('This is unanswered.'),
|
||||
'unsubmitted': _('This is unanswered.'),
|
||||
'queued': _('This is being processed.'),
|
||||
}
|
||||
self.display_name = names.get(status, unicode(status))
|
||||
self.display_tooltip = tooltips.get(status, u'')
|
||||
self._status = status or ''
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -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,21 @@
|
||||
% 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="${status.display_tooltip}">
|
||||
<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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
% endif
|
||||
/>
|
||||
|
||||
<p class="status" id="${id}_status">
|
||||
${status.display_name}
|
||||
</p>
|
||||
<span class="status" id="${id}_status" data-tooltip="${status.display_tooltip}">
|
||||
<span class="sr">
|
||||
${status.display_name}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div id="input_${id}_preview" class="equation">
|
||||
\[\]
|
||||
|
||||
@@ -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="${status.display_tooltip}">
|
||||
<span class="sr">${value|h} - ${status.display_name}</span>
|
||||
</span>
|
||||
</div>
|
||||
% if msg:
|
||||
<span class="message">${msg|n}</span>
|
||||
% endif
|
||||
|
||||
@@ -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="${status.display_tooltip}">
|
||||
<span class="sr">
|
||||
%if value:
|
||||
${value|h}
|
||||
% else:
|
||||
${label}
|
||||
%endif
|
||||
-
|
||||
${status.display_name}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<p id="answer_${id}" class="answer"></p>
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
|
||||
# Should mark the entire problem correct
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status correct']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status correct']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -172,7 +172,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
for test_conditions in conditions:
|
||||
self.context.update(test_conditions)
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status incorrect']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status incorrect']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -204,7 +204,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
for test_conditions in conditions:
|
||||
self.context.update(test_conditions)
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status unanswered']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status unanswered']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -234,7 +234,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark the whole problem
|
||||
xpath = "//div[@class='indicator_container']/span"
|
||||
xpath = "//div[@class='indicator-container']/span"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
def test_option_marked_incorrect(self):
|
||||
@@ -255,7 +255,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark the whole problem
|
||||
xpath = "//div[@class='indicator_container']/span"
|
||||
xpath = "//div[@class='indicator-container']/span"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
def test_never_show_correctness(self):
|
||||
@@ -289,10 +289,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
|
||||
xml = self.render_to_xml(self.context)
|
||||
|
||||
# Should NOT mark the entire problem correct/incorrect
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status correct']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status correct']"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status incorrect']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status incorrect']"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -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']/span[@class='sr']",
|
||||
status_mark, exact=False)
|
||||
|
||||
def test_label(self):
|
||||
@@ -848,7 +848,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
|
||||
|
||||
# Should mark the entire problem correct
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status correct']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status correct']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -875,7 +875,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
|
||||
for test_conditions in conditions:
|
||||
self.context.update(test_conditions)
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status incorrect']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status incorrect']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -907,7 +907,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
|
||||
for test_conditions in conditions:
|
||||
self.context.update(test_conditions)
|
||||
xml = self.render_to_xml(self.context)
|
||||
xpath = "//div[@class='indicator_container']/span[@class='status unanswered']"
|
||||
xpath = "//div[@class='indicator-container']/span[@class='status unanswered']"
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark individual options
|
||||
@@ -937,7 +937,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark the whole problem
|
||||
xpath = "//div[@class='indicator_container']/span"
|
||||
xpath = "//div[@class='indicator-container']/span"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
def test_option_marked_incorrect(self):
|
||||
@@ -957,7 +957,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
|
||||
self.assert_has_xpath(xml, xpath, self.context)
|
||||
|
||||
# Should NOT mark the whole problem
|
||||
xpath = "//div[@class='indicator_container']/span"
|
||||
xpath = "//div[@class='indicator-container']/span"
|
||||
self.assert_no_xpath(xml, xpath, self.context)
|
||||
|
||||
def test_label(self):
|
||||
|
||||
@@ -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,16 @@ iframe[seamless]{
|
||||
}
|
||||
|
||||
div.problem-progress {
|
||||
@include padding-left($baseline/4);
|
||||
@extend %t-ultralight;
|
||||
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 +137,11 @@ div.problem {
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
// +Problem - Choice Group
|
||||
// ====================
|
||||
div.problem {
|
||||
.choicegroup {
|
||||
@include clearfix();
|
||||
min-width: 100px;
|
||||
@@ -97,51 +149,98 @@ div.problem {
|
||||
width: 100px;
|
||||
|
||||
label {
|
||||
@include float(left);
|
||||
@include box-sizing(border-box);
|
||||
display: inline-block;
|
||||
clear: both;
|
||||
margin-bottom: ($baseline/4);
|
||||
margin-bottom: ($baseline/2);
|
||||
border: 2px solid $gray-l4;
|
||||
border-radius: 3px;
|
||||
padding: ($baseline/2);
|
||||
width: 100%;
|
||||
|
||||
&.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);
|
||||
.indicator-container {
|
||||
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: $baseline;
|
||||
height: $baseline;
|
||||
|
||||
// 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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// +Problem - Misc, Unclassified Mess
|
||||
// ====================
|
||||
div.problem {
|
||||
ol.enumerate {
|
||||
li {
|
||||
&:before {
|
||||
@@ -187,17 +286,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 {
|
||||
@@ -224,7 +328,7 @@ div.problem {
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: green;
|
||||
border-color: $correct;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +345,7 @@ div.problem {
|
||||
}
|
||||
}
|
||||
|
||||
&.incorrect, &.incomplete, &.ui-icon-close {
|
||||
&.ui-icon-close {
|
||||
p.status {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
@@ -250,7 +354,21 @@ div.problem {
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: red;
|
||||
border-color: $incorrect;
|
||||
}
|
||||
}
|
||||
|
||||
&.incorrect, &.incomplete {
|
||||
|
||||
p.status {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: url('../images/incorrect-icon.png') center center no-repeat;
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: $incorrect;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,14 +378,14 @@ div.problem {
|
||||
}
|
||||
|
||||
p.answer {
|
||||
@include margin-left($baseline/2);
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
margin-left: $baseline/2;
|
||||
|
||||
&:before {
|
||||
@extend %t-strong;
|
||||
display: inline;
|
||||
content: "Answer: ";
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
&:empty {
|
||||
@@ -287,8 +405,8 @@ div.problem {
|
||||
}
|
||||
|
||||
img.loading {
|
||||
@include padding-left($baseline/2);
|
||||
display: inline-block;
|
||||
padding-left: ($baseline/2);
|
||||
}
|
||||
|
||||
span {
|
||||
@@ -303,7 +421,7 @@ div.problem {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hides equation previews in symbolic response problems when printing
|
||||
[id^='display'].equation {
|
||||
@@ -312,8 +430,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 +450,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 +468,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 +479,8 @@ div.problem {
|
||||
}
|
||||
|
||||
.reload {
|
||||
float:right;
|
||||
margin: $baseline/2;
|
||||
@include float(right);
|
||||
margin: ($baseline/2);
|
||||
}
|
||||
|
||||
|
||||
@@ -457,15 +576,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;
|
||||
@@ -485,7 +595,8 @@ div.problem {
|
||||
}
|
||||
|
||||
dl dt {
|
||||
font-weight: bold;
|
||||
@extend %t-strong;
|
||||
|
||||
}
|
||||
|
||||
dl dd {
|
||||
@@ -531,8 +642,8 @@ div.problem {
|
||||
}
|
||||
|
||||
th {
|
||||
@extend %t-strong;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
@@ -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;
|
||||
min-width: 160px;
|
||||
height: 46px;
|
||||
}
|
||||
|
||||
> .incorrect, .correct, .unanswered {
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
margin-top: ($baseline/2);
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.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);
|
||||
@include margin-left($baseline/2);
|
||||
display: inline-block;
|
||||
margin-top: 8px;
|
||||
color: $gray-d1;
|
||||
font-style: italic;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
}
|
||||
|
||||
// +Problem - Misc, Unclassified Mess Part 2
|
||||
// ====================
|
||||
div.problem {
|
||||
hr {
|
||||
float: none;
|
||||
clear: both;
|
||||
@@ -663,52 +906,12 @@ 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 {
|
||||
@extend %t-strong;
|
||||
color: #aaa;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
@@ -720,9 +923,9 @@ div.problem {
|
||||
|
||||
.detailed-targeted-feedback {
|
||||
> p:first-child {
|
||||
color: red;
|
||||
@extend %t-strong;
|
||||
color: $incorrect;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
@@ -734,9 +937,9 @@ div.problem {
|
||||
|
||||
.detailed-targeted-feedback-correct {
|
||||
> p:first-child {
|
||||
color: green;
|
||||
@extend %t-strong;
|
||||
color: $correct;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
@@ -777,11 +980,11 @@ div.problem {
|
||||
border: 1px solid $gray-l3;
|
||||
|
||||
h3 {
|
||||
@extend %t-strong;
|
||||
padding: 9px;
|
||||
border-bottom: 1px solid #e3e3e3;
|
||||
background: #eee;
|
||||
text-shadow: 0 1px 0 $white;
|
||||
font-weight: bold;
|
||||
font-size: em(16);
|
||||
}
|
||||
|
||||
@@ -818,9 +1021,9 @@ div.problem {
|
||||
margin-bottom: 12px;
|
||||
|
||||
h3 {
|
||||
@extend %t-strong;
|
||||
color: #aaa;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
@@ -877,7 +1080,7 @@ div.problem {
|
||||
}
|
||||
|
||||
.shortform {
|
||||
font-weight: bold;
|
||||
@extend %t-strong;
|
||||
}
|
||||
|
||||
.longform {
|
||||
@@ -951,7 +1154,12 @@ div.problem {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// +Problem - Rubric
|
||||
// ====================
|
||||
div.problem {
|
||||
.rubric {
|
||||
tr {
|
||||
margin: ($baseline/2) 0;
|
||||
@@ -1004,16 +1212,20 @@ div.problem {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// +Problem - Annotation
|
||||
// ====================
|
||||
div.problem {
|
||||
.annotation-input {
|
||||
margin: 0 0 1em 0;
|
||||
border: 1px solid $gray-l3;
|
||||
border-radius: 1em;
|
||||
|
||||
.annotation-header {
|
||||
@extend %t-strong;
|
||||
padding: .5em 1em;
|
||||
border-bottom: 1px solid $gray-l3;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.annotation-body { padding: .5em 1em; }
|
||||
@@ -1094,16 +1306,20 @@ div.problem {
|
||||
pre { background-color: $gray-l3; color: $black; }
|
||||
|
||||
&:before {
|
||||
@extend %t-strong;
|
||||
display: block;
|
||||
content: "debug input value";
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.choicetextgroup{
|
||||
// +Problem - Choice Text Group
|
||||
// ====================
|
||||
div.problem {
|
||||
.choicetextgroup {
|
||||
@extend .choicegroup;
|
||||
|
||||
input[type="text"]{
|
||||
@@ -1114,7 +1330,7 @@ div.problem {
|
||||
@extend label.choicegroup_correct;
|
||||
|
||||
input[type="text"] {
|
||||
border-color: green;
|
||||
border-color: $correct;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ describe 'Problem', ->
|
||||
<div><p></p><span><section id="choicetextinput_1_2_1" class="choicetextinput">
|
||||
|
||||
<form class="choicetextgroup capa_inputtype" id="inputtype_1_2_1">
|
||||
<div class="indicator_container">
|
||||
<div class="indicator-container">
|
||||
<span class="unanswered" style="display:inline-block;" id="status_1_2_1"></span>
|
||||
</div>
|
||||
<fieldset>
|
||||
|
||||
@@ -468,9 +468,9 @@ 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"
|
||||
$p.parent().removeClass().addClass "unsubmitted"
|
||||
|
||||
choicegroup: (element) ->
|
||||
$element = $(element)
|
||||
@@ -496,9 +496,9 @@ 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"
|
||||
$p.parent().removeClass("correct incorrect").addClass "unsubmitted"
|
||||
|
||||
inputtypeSetupMethods:
|
||||
|
||||
|
||||
@@ -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 {
|
||||
display: inline-block;
|
||||
font-family: FontAwesome;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
speak: none;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class ProblemPage(PageObject):
|
||||
"""
|
||||
Is there a "correct" status showing?
|
||||
"""
|
||||
return self.q(css="div.problem div.capa_inputtype.textline div.correct p.status").is_present()
|
||||
return self.q(css="div.problem div.capa_inputtype.textline div.correct span.status").is_present()
|
||||
|
||||
def click_clarification(self, index=0):
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -84,7 +84,7 @@ PROBLEM_DICT = {
|
||||
'answer': 'correct string'},
|
||||
'correct': ['div.correct'],
|
||||
'incorrect': ['div.incorrect'],
|
||||
'unanswered': ['div.unanswered']},
|
||||
'unanswered': ['div.unanswered', 'div.unsubmitted']},
|
||||
|
||||
'numerical': {
|
||||
'factory': NumericalResponseXMLFactory(),
|
||||
@@ -95,7 +95,7 @@ PROBLEM_DICT = {
|
||||
'math_display': True},
|
||||
'correct': ['div.correct'],
|
||||
'incorrect': ['div.incorrect'],
|
||||
'unanswered': ['div.unanswered']},
|
||||
'unanswered': ['div.unanswered', 'div.unsubmitted']},
|
||||
|
||||
'formula': {
|
||||
'factory': FormulaResponseXMLFactory(),
|
||||
@@ -108,7 +108,7 @@ PROBLEM_DICT = {
|
||||
'answer': 'x^2+2*x+y'},
|
||||
'correct': ['div.correct'],
|
||||
'incorrect': ['div.incorrect'],
|
||||
'unanswered': ['div.unanswered']},
|
||||
'unanswered': ['div.unanswered', 'div.unsubmitted']},
|
||||
|
||||
'script': {
|
||||
'factory': CustomResponseXMLFactory(),
|
||||
@@ -129,7 +129,7 @@ PROBLEM_DICT = {
|
||||
""")},
|
||||
'correct': ['div.correct'],
|
||||
'incorrect': ['div.incorrect'],
|
||||
'unanswered': ['div.unanswered']},
|
||||
'unanswered': ['div.unanswered', 'div.unsubmitted']},
|
||||
|
||||
'code': {
|
||||
'factory': CodeResponseXMLFactory(),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
0
test_root/db/test_edx.db-journal
Normal file
0
test_root/db/test_edx.db-journal
Normal file
Reference in New Issue
Block a user