/* *
|
*
|
* (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<Highcharts.KeyboardNavigationHandler>}
|
* List of module objects.
|
*/
|
getKeyboardNavigation: function getKeyboardNavigation() {
|
return [this.getRangeSelectorButtonNavigation(), this.getRangeSelectorInputNavigation()];
|
}
|
|
});
|
|
exports.default = RangeSelectorComponent;
|