// Once generated by CoffeeScript 1.9.3, but now lives as pure JS /* eslint-disable */ /* Keyboard Support If focus is on the hint button: * Enter: Open or close hint popup. Select last focused hint item if opening * Space: Open or close hint popup. Select last focused hint item if opening If focus is on a hint item: * Left arrow: Select previous hint item * Up arrow: Select previous hint item * Right arrow: Select next hint item * Down arrow: Select next hint item */ (function() { this.Calculator = (function() { function Calculator() { this.hintButton = $('#calculator_hint'); this.calcInput = $('#calculator_input'); this.hintPopup = $('.help'); this.hintsList = this.hintPopup.find('.hint-item'); this.selectHint($('#' + this.hintPopup.attr('data-calculator-hint'))); $('.calc').click(this.toggle); $('form#calculator').submit(this.calculate).submit(function(e) { return e.preventDefault(); }); this.hintButton.click($.proxy(this.handleClickOnHintButton, this)); this.hintPopup.click($.proxy(this.handleClickOnHintPopup, this)); this.hintPopup.keydown($.proxy(this.handleKeyDownOnHint, this)); $('#calculator_wrapper').keyup($.proxy(this.handleKeyUpOnHint, this)); this.handleClickOnDocument = $.proxy(this.handleClickOnDocument, this); this.calcInput.focus($.proxy(this.inputClickHandler, this)); } Calculator.prototype.KEY = { TAB: 9, ENTER: 13, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 }; Calculator.prototype.toggle = function(event) { var $calc, $calcWrapper, icon, isExpanded, text; event.preventDefault(); $calc = $('.calc'); $calcWrapper = $('#calculator_wrapper'); text = gettext('Open Calculator'); isExpanded = false; icon = 'fa-calculator'; $('.calc-main').toggleClass('open'); if ($calc.hasClass('closed')) { $calcWrapper.attr('aria-hidden', 'true'); } else { text = gettext('Close Calculator'); icon = 'fa-close'; isExpanded = true; $calcWrapper.attr('aria-hidden', 'false'); /* 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((function() { return $calcWrapper.find('#calculator_input').focus(); }), 100); } $calc.attr({ 'title': text, 'aria-expanded': isExpanded }).find('.utility-control-label').text(text); $calc.find('.icon').removeClass('fa-calculator').removeClass('fa-close').addClass(icon); return $calc.toggleClass('closed'); }; Calculator.prototype.inputClickHandler = function() { return $('#calculator_output').removeClass('has-result'); }; Calculator.prototype.showHint = function() { this.hintPopup.addClass('shown').attr('aria-hidden', false); $('#calculator_output').removeClass('has-result'); return $(document).on('click', this.handleClickOnDocument); }; Calculator.prototype.hideHint = function() { this.hintPopup.removeClass('shown').attr('aria-hidden', true); $('#calculator_output').removeClass('has-result'); return $(document).off('click', this.handleClickOnDocument); }; Calculator.prototype.selectHint = function(element) { if (!element || (element && element.length === 0)) { element = this.hintsList.first(); } this.activeHint = element; this.activeHint.focus(); return this.hintPopup.attr('data-calculator-hint', element.attr('id')); }; Calculator.prototype.prevHint = function() { /* the previous hint */ var prev; prev = this.activeHint.prev(); /* if this was the first item select the last one in the group. */ if (this.activeHint.index() === 0) { prev = this.hintsList.last(); } /* select the previous hint */ return this.selectHint(prev); }; Calculator.prototype.nextHint = function() { /* the next hint */ var next; next = this.activeHint.next(); /* if this was the last item, select the first one in the group. */ if (this.activeHint.index() === this.hintsList.length - 1) { next = this.hintsList.first(); } /* give the next hint focus */ return this.selectHint(next); }; Calculator.prototype.handleKeyDown = function(e) { if (e.altKey) { /* do nothing */ return true; } if (e.keyCode === this.KEY.ENTER || e.keyCode === this.KEY.SPACE) { if (this.hintPopup.hasClass('shown')) { this.hideHint(); } else { this.showHint(); this.activeHint.focus(); } e.preventDefault(); return false; } /* allow the event to propagate */ return true; }; Calculator.prototype.handleKeyDownOnHint = function(e) { if (e.altKey) { /* do nothing */ return true; } switch (e.keyCode) { case this.KEY.ESC: /* hide popup with hints */ this.hideHint(); this.hintButton.focus(); e.stopPropagation(); return false; case this.KEY.LEFT: case this.KEY.UP: if (e.shiftKey) { /* do nothing */ } return true; this.prevHint(); e.stopPropagation(); return false; case this.KEY.RIGHT: case this.KEY.DOWN: if (e.shiftKey) { /* do nothing */ return true; } this.nextHint(); e.stopPropagation(); return false; } /* allow the event to propagate */ return true; }; Calculator.prototype.handleKeyUpOnHint = function(e) { switch (e.keyCode) { case this.KEY.TAB: /* move focus to hint links and hide hint once focus is out of hint pop up */ this.active_element = document.activeElement; if (!$(this.active_element).parents().is(this.hintPopup)) { return this.hideHint(); } } }; Calculator.prototype.handleClickOnDocument = function(e) { return this.hideHint(); }; Calculator.prototype.handleClickOnHintButton = function(e) { e.preventDefault(); e.stopPropagation(); if (this.hintPopup.hasClass('shown')) { this.hideHint(); return this.hintButton.attr('aria-expanded', false); } else { this.showHint(); this.hintButton.attr('aria-expanded', true); return this.activeHint.focus(); } }; Calculator.prototype.handleClickOnHintPopup = function(e) { return e.stopPropagation(); }; Calculator.prototype.calculate = function() { return $.getWithPrefix('/calculate', { equation: $('#calculator_input').val() }, function(data) { return $('#calculator_output').val(data.result).addClass('has-result').focus(); }); }; return Calculator; })(); }).call(this);