Fixes tests, adds internationalized strings for new state tooltips, corrected tooltip javascript, etc.

This commit is contained in:
Kyle McCormick
2015-06-04 16:44:08 -04:00
committed by Marco Morales
parent 8acc72975e
commit aa5e2f49bd
16 changed files with 73 additions and 88 deletions

View File

@@ -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>

View File

@@ -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):

View File

@@ -39,11 +39,9 @@
% endfor
<span id="answer_${id}"></span>
</fieldset>
<div class="indicator_container">
<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="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:

View File

@@ -58,7 +58,7 @@
</fieldset>
<input class= "choicetextvalue" type="hidden" name="input_${id}{}" id="input_${id}" value="${value|h}" />
<div class="indicator_container">
<div class="indicator-container">
% if input_type == 'checkbox' or not element_checked:
<span class="status ${status.classname}" id="status_${id}"></span>
% endif

View File

@@ -10,7 +10,7 @@
% endif
/>
<span class="status" id="${id}_status" data-tooltip="This is ${status.display_name}.">
<span class="status" id="${id}_status" data-tooltip="${status.display_tooltip}">
<span class="sr">
${status.display_name}
</span>

View File

@@ -13,10 +13,10 @@
</select>
<span id="answer_${id}"></span>
<div class="indicator_container">
<div class="indicator-container">
<span class="status ${status.classname}"
id="status_${id}"
aria-describedby="input_${id}" data-tooltip="This is ${status.display_name}">
aria-describedby="input_${id}" data-tooltip="${status.display_tooltip}">
<span class="sr">${value|h} - ${status.display_name}</span>
</span>
</div>

View File

@@ -30,7 +30,7 @@
<span class="status"
%if status != 'unsubmitted':
%endif
aria-describedby="input_${id}" data-tooltip="This is ${status.display_name}.">
aria-describedby="input_${id}" data-tooltip="${status.display_tooltip}">
<span class="sr">
%if value:
${value|h}

View File

@@ -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
@@ -390,7 +390,7 @@ class TextlineTemplateTest(TemplateTestCase):
# 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, "//span[@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):

View File

@@ -114,6 +114,7 @@ iframe[seamless]{
div.problem-progress {
@include padding-left($baseline/4);
@extend %t-ultralight;
display: inline-block;
color: $gray-d1;
font-weight: 100;
@@ -151,11 +152,11 @@ div.problem {
@include box-sizing(border-box);
display: inline-block;
clear: both;
width: 100%;
margin-bottom: ($baseline/2);
border: 2px solid $gray-l4;
border-radius: 3px;
margin-bottom: ($baseline/2);
padding: ($baseline/2);
width: 100%;
&.choicegroup_correct {
@include status-icon($correct, "\f00c");
@@ -182,7 +183,7 @@ div.problem {
}
}
.indicator_container {
.indicator-container {
display: inline-block;
min-height: 1px;
width: 25px;
@@ -209,11 +210,11 @@ div.problem {
// Summary status indicators shown after the input area
div.problem {
.indicator_container {
.indicator-container {
.status {
width: 20px;
height: 20px;
width: $baseline;
height: $baseline;
// CASE: correct answer
&.correct {
@@ -232,8 +233,6 @@ div.problem {
// CASE: processing
&.processing {
// add once spinner is rotated through animations
//@include status-icon($gray-d1, "\f110", 0);
}
}
}
@@ -287,7 +286,7 @@ div.problem {
}
}
// known classes using this div: .indicator_container, moved to section above
// 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
@@ -297,7 +296,7 @@ div.problem {
}
&.status {
@include margin(8px, 0, 0, $baseline/2);
@include margin(8px, 0, 0, ($baseline/2));
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
@@ -329,7 +328,7 @@ div.problem {
}
input {
border-color: green;
border-color: $correct;
}
}
@@ -355,7 +354,7 @@ div.problem {
}
input {
border-color: red;
border-color: $incorrect;
}
}
@@ -369,7 +368,7 @@ div.problem {
}
input {
border-color: red;
border-color: $incorrect;
}
}
@@ -384,9 +383,9 @@ div.problem {
margin-bottom: 0;
&:before {
@extend %t-strong;
display: inline;
content: "Answer: ";
font-weight: bold;
}
&:empty {
@@ -596,7 +595,8 @@ div.problem {
}
dl dt {
font-weight: bold;
@extend %t-strong;
}
dl dd {
@@ -642,8 +642,8 @@ div.problem {
}
th {
@extend %t-strong;
text-align: left;
font-weight: bold;
}
td {
@@ -706,16 +706,16 @@ div.problem {
@include box-sizing(border-box);
border: 2px solid $gray-l4;
border-radius: 3px;
height: 46px;
min-width: 160px;
height: 46px;
}
> .incorrect, .correct, .unanswered {
.status {
display: inline-block;
background: none;
margin-top: ($baseline/2);
background: none;
}
}
@@ -769,7 +769,7 @@ div.problem {
@include margin-right($baseline/2);
}
.indicator_container {
.indicator-container {
display: inline-block;
.status.correct:after, .status.incorrect:after {
@@ -844,8 +844,8 @@ div.problem .action {
margin-bottom: ($baseline/2);
height: ($baseline*2);
vertical-align: middle;
font-weight: 600;
text-transform: uppercase;
font-weight: 600;
}
.save {
@@ -866,9 +866,9 @@ div.problem .action {
// border-radius: 3px;
// padding: 8px 12px;
// margin-top: ($baseline/2);
@include margin-left($baseline/2);
display: inline-block;
margin-top: 8px;
@include margin-left($baseline/2);
color: $gray-d1;
font-style: italic;
-webkit-font-smoothing: antialiased;
@@ -909,9 +909,9 @@ div.problem {
.detailed-solution {
> p:first-child {
@extend %t-strong;
color: #aaa;
text-transform: uppercase;
font-weight: bold;
font-style: normal;
font-size: 0.9em;
}
@@ -923,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;
}
@@ -937,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;
}
@@ -980,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);
}
@@ -1021,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;
}
@@ -1080,7 +1080,7 @@ div.problem {
}
.shortform {
font-weight: bold;
@extend %t-strong;
}
.longform {
@@ -1223,9 +1223,9 @@ div.problem {
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; }
@@ -1306,10 +1306,10 @@ 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;
}
}
@@ -1330,7 +1330,7 @@ div.problem {
@extend label.choicegroup_correct;
input[type="text"] {
border-color: green;
border-color: $correct;
}
}

View File

@@ -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>

View File

@@ -470,7 +470,7 @@ class @Problem
$(element).find('input').on 'input', ->
$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)
@@ -498,7 +498,7 @@ class @Problem
$(element).find('input').on 'input', ->
$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:

View File

@@ -432,8 +432,8 @@
// * +Icon - Font-Awesome - Extend
// ====================
%use-font-awesome {
display: inline-block;
font-family: FontAwesome;
-webkit-font-smoothing: antialiased;
display: inline-block;
speak: none;
}

View File

@@ -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):
"""

View File

@@ -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(),

View File

@@ -82,28 +82,6 @@ $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