/* * * * (c) 2009-2019 Øystein Moseng * * Accessibility component for the range selector. * * License: www.highcharts.com/license * * */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _Globals = require('../../../parts/Globals.js'); var _Globals2 = _interopRequireDefault(_Globals); var _AccessibilityComponent = require('../AccessibilityComponent.js'); var _AccessibilityComponent2 = _interopRequireDefault(_AccessibilityComponent); var _KeyboardNavigationHandler = require('../KeyboardNavigationHandler.js'); var _KeyboardNavigationHandler2 = _interopRequireDefault(_KeyboardNavigationHandler); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Highlight range selector button by index. * * @private * @function Highcharts.Chart#highlightRangeSelectorButton * * @param {number} ix * * @return {boolean} */ _Globals2.default.Chart.prototype.highlightRangeSelectorButton = function (ix) { var buttons = this.rangeSelector.buttons; // Deselect old if (buttons[this.highlightedRangeSelectorItemIx]) { buttons[this.highlightedRangeSelectorItemIx].setState(this.oldRangeSelectorItemState || 0); } // Select new this.highlightedRangeSelectorItemIx = ix; if (buttons[ix]) { this.setFocusToElement(buttons[ix].box, buttons[ix].element); this.oldRangeSelectorItemState = buttons[ix].state; buttons[ix].setState(2); return true; } return false; }; /** * The RangeSelectorComponent class * * @private * @class * @name Highcharts.RangeSelectorComponent * @param {Highcharts.Chart} chart * Chart object */ var RangeSelectorComponent = function RangeSelectorComponent(chart) { this.initBase(chart); }; RangeSelectorComponent.prototype = new _AccessibilityComponent2.default(); _Globals2.default.extend(RangeSelectorComponent.prototype, /** @lends Highcharts.RangeSelectorComponent */{ // eslint-disable-line /** * Called on first render/updates to the chart, including options changes. */ onChartUpdate: function onChartUpdate() { var chart = this.chart, component = this, rangeSelector = chart.rangeSelector; if (!rangeSelector) { return; } // Make sure buttons are accessible and focusable if (rangeSelector.buttons && rangeSelector.buttons.length) { rangeSelector.buttons.forEach(function (button) { component.unhideElementFromScreenReaders(button.element); button.element.setAttribute('tabindex', '-1'); button.element.setAttribute('role', 'button'); button.element.setAttribute('aria-label', chart.langFormat('accessibility.rangeSelectorButton', { chart: chart, buttonText: button.text && button.text.textStr })); }); } // Make sure input boxes are accessible and focusable if (rangeSelector.maxInput && rangeSelector.minInput) { ['minInput', 'maxInput'].forEach(function (key, i) { if (rangeSelector[key]) { component.unhideElementFromScreenReaders(rangeSelector[key]); rangeSelector[key].setAttribute('tabindex', '-1'); rangeSelector[key].setAttribute('role', 'textbox'); rangeSelector[key].setAttribute('aria-label', chart.langFormat('accessibility.rangeSelector' + (i ? 'MaxInput' : 'MinInput'), { chart: chart })); } }); } }, /** * Get navigation for the range selector buttons. * @private * @return {Highcharts.KeyboardNavigationHandler} The module object. */ getRangeSelectorButtonNavigation: function getRangeSelectorButtonNavigation() { var chart = this.chart, keys = this.keyCodes, a11yOptions = chart.options.accessibility, component = this; return new _KeyboardNavigationHandler2.default(chart, { keyCodeMap: [ // Left/Right/Up/Down [[keys.left, keys.right, keys.up, keys.down], function (keyCode) { var direction = keyCode === keys.left || keyCode === keys.up ? -1 : 1; // Try to highlight next/prev button if (!chart.highlightRangeSelectorButton(chart.highlightedRangeSelectorItemIx + direction)) { // If we failed, handle wrap around/move if (a11yOptions.keyboardNavigation.wrapAround) { this.init(direction); return this.response.success; } return this.response[direction > 0 ? 'next' : 'prev']; } }], // Enter/Spacebar [[keys.enter, keys.space], function () { // Don't allow click if button used to be disabled if (chart.oldRangeSelectorItemState !== 3) { component.fakeClickEvent(chart.rangeSelector.buttons[chart.highlightedRangeSelectorItemIx].element); } }]], // Only run this module if we have range selector validate: function validate() { return chart.rangeSelector && chart.rangeSelector.buttons && chart.rangeSelector.buttons.length; }, // Focus first/last button init: function init(direction) { chart.highlightRangeSelectorButton(direction > 0 ? 0 : chart.rangeSelector.buttons.length - 1); } }); }, /** * Get navigation for the range selector input boxes. * @private * @return {Highcharts.KeyboardNavigationHandler} * The module object. */ getRangeSelectorInputNavigation: function getRangeSelectorInputNavigation() { var chart = this.chart, keys = this.keyCodes; return new _KeyboardNavigationHandler2.default(chart, { keyCodeMap: [ // Tab/Up/Down [[keys.tab, keys.up, keys.down], function (keyCode, e) { var direction = keyCode === keys.tab && e.shiftKey || keyCode === keys.up ? -1 : 1, newIx = chart.highlightedInputRangeIx = chart.highlightedInputRangeIx + direction; // Try to highlight next/prev item in list. if (newIx > 1 || newIx < 0) { // Out of range return this.response[direction > 0 ? 'next' : 'prev']; } chart.rangeSelector[newIx ? 'maxInput' : 'minInput'].focus(); return this.response.success; }]], // Only run if we have range selector with input boxes validate: function validate() { var inputVisible = chart.rangeSelector && chart.rangeSelector.inputGroup && chart.rangeSelector.inputGroup.element.getAttribute('visibility') !== 'hidden'; return inputVisible && chart.options.rangeSelector.inputEnabled !== false && chart.rangeSelector.minInput && chart.rangeSelector.maxInput; }, // Highlight first/last input box init: function init(direction) { chart.highlightedInputRangeIx = direction > 0 ? 0 : 1; chart.rangeSelector[chart.highlightedInputRangeIx ? 'maxInput' : 'minInput'].focus(); }, // Hide HTML element when leaving boxes terminate: function terminate() { var rangeSel = chart.rangeSelector; if (rangeSel && rangeSel.maxInput && rangeSel.minInput) { rangeSel.hideInput('max'); rangeSel.hideInput('min'); } } }); }, /** * Get keyboard navigation handlers for this component. * @return {Array} * List of module objects. */ getKeyboardNavigation: function getKeyboardNavigation() { return [this.getRangeSelectorButtonNavigation(), this.getRangeSelectorInputNavigation()]; } }); exports.default = RangeSelectorComponent;