diff --git a/lms/static/coffee/fixtures/calculator.html b/lms/static/coffee/fixtures/calculator.html
index 61c6f5e153..d0f7d3f652 100644
--- a/lms/static/coffee/fixtures/calculator.html
+++ b/lms/static/coffee/fixtures/calculator.html
@@ -1,17 +1,17 @@
-
- Calculator
+ Open Calculator
diff --git a/lms/static/coffee/spec/calculator_spec.coffee b/lms/static/coffee/spec/calculator_spec.coffee
index 8258d8965a..81034bbd20 100644
--- a/lms/static/coffee/spec/calculator_spec.coffee
+++ b/lms/static/coffee/spec/calculator_spec.coffee
@@ -9,8 +9,10 @@ describe 'Calculator', ->
it 'bind the help button', ->
# These events are bind by $.hover()
- expect($('div.help-wrapper a')).toHandleWith 'mouseover', @calculator.helpToggle
- expect($('div.help-wrapper a')).toHandleWith 'mouseout', @calculator.helpToggle
+ expect($('div.help-wrapper a')).toHandle 'mouseover'
+ expect($('div.help-wrapper a')).toHandle 'mouseout'
+ expect($('div.help-wrapper')).toHandle 'focusin'
+ expect($('div.help-wrapper')).toHandle 'focusout'
it 'prevent default behavior on help button', ->
$('div.help-wrapper a').click (e) ->
@@ -33,8 +35,8 @@ describe 'Calculator', ->
# Since the focus is called asynchronously, we need to
# wait until focus() is called.
didFocus = false
- runs ->
- spyOn($.fn, 'focus').andCallFake (elementName) -> didFocus = true
+ runs ->
+ spyOn($.fn, 'focus').andCallFake (elementName) -> didFocus = true
@calculator.toggle(jQuery.Event("click"))
waitsFor (-> didFocus), "focus() should have been called on the input", 1000
@@ -49,12 +51,14 @@ describe 'Calculator', ->
@calculator.toggle(jQuery.Event("click"))
expect($('.calc')).not.toHaveClass('closed')
- describe 'helpToggle', ->
- it 'toggle the help overlay', ->
- @calculator.helpToggle()
+ describe 'helpShow', ->
+ it 'show the help overlay', ->
+ @calculator.helpShow()
expect($('.help')).toHaveClass('shown')
- @calculator.helpToggle()
+ describe 'helpHide', ->
+ it 'show the help overlay', ->
+ @calculator.helpHide()
expect($('.help')).not.toHaveClass('shown')
describe 'calculate', ->
diff --git a/lms/static/coffee/src/calculator.coffee b/lms/static/coffee/src/calculator.coffee
index 788081ebd6..e8cfea63f3 100644
--- a/lms/static/coffee/src/calculator.coffee
+++ b/lms/static/coffee/src/calculator.coffee
@@ -3,26 +3,70 @@ class @Calculator
$('.calc').click @toggle
$('form#calculator').submit(@calculate).submit (e) ->
e.preventDefault()
- $('div.help-wrapper a').hover(@helpToggle).click (e) ->
- e.preventDefault()
+ $('div.help-wrapper a')
+ .hover(
+ $.proxy(@helpShow, @),
+ $.proxy(@helpHide, @)
+ )
+ .click (e) ->
+ e.preventDefault()
+ $('div.help-wrapper')
+ .focusin($.proxy @helpOnFocus, @)
+ .focusout($.proxy @helpOnBlur, @)
toggle: (event) ->
event.preventDefault()
+ $calc = $('.calc')
+ $calcWrapper = $('#calculator_wrapper')
+ text = gettext('Open Calculator')
+ isExpanded = false
+
$('div.calc-main').toggleClass 'open'
- if $('.calc.closed').length
- $('.calc').attr 'aria-label', 'Open Calculator'
+ if $calc.hasClass('closed')
+ $calcWrapper
+ .find('input, a, dt, dd')
+ .attr 'tabindex', -1
else
- $('.calc').attr 'aria-label', 'Close Calculator'
+ text = gettext('Close Calculator')
+ isExpanded = true
+
+ $calcWrapper
+ .find('input, a, dt, dd')
+ .attr 'tabindex', 0
# TODO: Investigate why doing this without the timeout causes it to jump
# down to the bottom of the page. I suspect it's because it's putting the
# focus on the text field before it transitions onto the page.
- setTimeout (-> $('#calculator_wrapper #calculator_input').focus()), 100
+ setTimeout (-> $calcWrapper.find('#calculator_input').focus()), 100
- $('.calc').toggleClass 'closed'
+ $calc
+ .attr
+ 'title': text
+ 'aria-expanded': isExpanded
+ .text text
- helpToggle: ->
- $('.help').toggleClass 'shown'
+ $calc.toggleClass 'closed'
+
+ helpOnFocus: (e) ->
+ e.preventDefault()
+ @isFocusedHelp = true
+ @helpShow()
+
+ helpOnBlur: (e) ->
+ e.preventDefault()
+ @isFocusedHelp = false
+ @helpHide()
+
+ helpShow: ->
+ $('.help').addClass 'shown'
+ $('#calculator_hint').attr 'aria-expanded', true
+
+ helpHide: ->
+ if not @isFocusedHelp
+ $('.help').removeClass 'shown'
+ $('#calculator_hint').attr 'aria-expanded', false
calculate: ->
$.getWithPrefix '/calculate', { equation: $('#calculator_input').val() }, (data) ->
- $('#calculator_output').val(data.result)
+ $('#calculator_output')
+ .val(data.result)
+ .focus()
diff --git a/lms/static/sass/course/layout/_calculator.scss b/lms/static/sass/course/layout/_calculator.scss
index 046afbbcf8..b60ae2285b 100644
--- a/lms/static/sass/course/layout/_calculator.scss
+++ b/lms/static/sass/course/layout/_calculator.scss
@@ -117,6 +117,7 @@ div.calc-main {
height: 35px;
@include hide-text;
width: 35px;
+ display: block;
}
dl {
@@ -124,8 +125,6 @@ div.calc-main {
border-radius: 3px;
box-shadow: 0 0 3px #999;
color: #333;
- display: none;
- line-height: lh();
opacity: 0;
padding: 10px;
position: absolute;
@@ -133,10 +132,15 @@ div.calc-main {
top: -122px;
@include transition(none);
width: 600px;
+ height: 0;
+ overflow: hidden;
+ pointer-events: none;
&.shown {
- display: block;
- opacity: 1.0;
+ height: auto;
+ opacity: 1;
+ overflow: visible;
+ pointer-events: auto;
}
dt {
diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html
index da3beba262..fd3c741be6 100644
--- a/lms/templates/courseware/courseware.html
+++ b/lms/templates/courseware/courseware.html
@@ -208,24 +208,23 @@ ${fragment.foot_html()}
% if course.show_calculator: