/**
 * @license Highcharts JS v8.0.0 (2019-12-10)
 *
 * Accessibility module
 *
 * (c) 2010-2019 Highsoft AS
 * Author: Oystein Moseng
 *
 * License: www.highcharts.com/license
 */
'use strict';
(function (factory) {
    if (typeof module === 'object' && module.exports) {
        factory['default'] = factory;
        module.exports = factory;
    } else if (typeof define === 'function' && define.amd) {
        define('highcharts/modules/accessibility', ['highcharts'], function (Highcharts) {
            factory(Highcharts);
            factory.Highcharts = Highcharts;
            return factory;
        });
    } else {
        factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
    }
}(function (Highcharts) {
    var _modules = Highcharts ? Highcharts._modules : {};
    function _registerModule(obj, path, args, fn) {
        if (!obj.hasOwnProperty(path)) {
            obj[path] = fn.apply(null, args);
        }
    }
    _registerModule(_modules, 'modules/accessibility/utils/htmlUtilities.js', [_modules['parts/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Utility functions for accessibility module.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var merge = H.merge, win = H.win, doc = win.document;
        /* eslint-disable valid-jsdoc */
        /**
         * @private
         * @param {Highcharts.HTMLDOMElement} el
         * @param {string} className
         * @return {void}
         */
        function addClass(el, className) {
            if (el.classList) {
                el.classList.add(className);
            }
            else if (el.className.indexOf(className) < 0) {
                // Note: Dumb check for class name exists, should be fine for practical
                // use cases, but will return false positives if the element has a class
                // that contains the className.
                el.className += className;
            }
        }
        /**
         * @private
         * @param {string} str
         * @return {string}
         */
        function escapeStringForHTML(str) {
            return str
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#x27;')
                .replace(/\//g, '&#x2F;');
        }
        /**
         * Get an element by ID
         * @param {string} id
         * @private
         * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|null}
         */
        function getElement(id) {
            return doc.getElementById(id);
        }
        /**
         * Get a fake mouse event of a given type
         * @param {string} type
         * @private
         * @return {global.MouseEvent}
         */
        function getFakeMouseEvent(type) {
            if (typeof win.MouseEvent === 'function') {
                return new win.MouseEvent(type);
            }
            // No MouseEvent support, try using initMouseEvent
            if (doc.createEvent) {
                var evt = doc.createEvent('MouseEvent');
                if (evt.initMouseEvent) {
                    evt.initMouseEvent(type, true, // Bubble
                    true, // Cancel
                    win, // View
                    type === 'click' ? 1 : 0, // Detail
                    // Coords
                    0, 0, 0, 0, 
                    // Pressed keys
                    false, false, false, false, 0, // button
                    null // related target
                    );
                    return evt;
                }
            }
            return { type: type };
        }
        /**
         * Remove an element from the DOM.
         * @private
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} [element]
         * @return {void}
         */
        function removeElement(element) {
            if (element && element.parentNode) {
                element.parentNode.removeChild(element);
            }
        }
        /**
         * Utility function. Reverses child nodes of a DOM element.
         * @private
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} node
         * @return {void}
         */
        function reverseChildNodes(node) {
            var i = node.childNodes.length;
            while (i--) {
                node.appendChild(node.childNodes[i]);
            }
        }
        /**
         * Set attributes on element. Set to null to remove attribute.
         * @private
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
         * @param {Highcharts.HTMLAttributes|Highcharts.SVGAttributes} attrs
         * @return {void}
         */
        function setElAttrs(el, attrs) {
            Object.keys(attrs).forEach(function (attr) {
                var val = attrs[attr];
                if (val === null) {
                    el.removeAttribute(attr);
                }
                else {
                    var cleanedVal = escapeStringForHTML('' + val);
                    el.setAttribute(attr, cleanedVal);
                }
            });
        }
        /**
         * Used for aria-label attributes, painting on a canvas will fail if the
         * text contains tags.
         * @private
         * @param {string} str
         * @return {string}
         */
        function stripHTMLTagsFromString(str) {
            return typeof str === 'string' ?
                str.replace(/<\/?[^>]+(>|$)/g, '') : str;
        }
        /**
         * Utility function for hiding an element visually, but still keeping it
         * available to screen reader users.
         * @private
         * @param {Highcharts.HTMLDOMElement} element
         * @return {void}
         */
        function visuallyHideElement(element) {
            var hiddenStyle = {
                position: 'absolute',
                width: '1px',
                height: '1px',
                overflow: 'hidden',
                '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)',
                filter: 'alpha(opacity=1)',
                opacity: '0.01'
            };
            merge(true, element.style, hiddenStyle);
        }
        var HTMLUtilities = {
            addClass: addClass,
            escapeStringForHTML: escapeStringForHTML,
            getElement: getElement,
            getFakeMouseEvent: getFakeMouseEvent,
            removeElement: removeElement,
            reverseChildNodes: reverseChildNodes,
            setElAttrs: setElAttrs,
            stripHTMLTagsFromString: stripHTMLTagsFromString,
            visuallyHideElement: visuallyHideElement
        };

        return HTMLUtilities;
    });
    _registerModule(_modules, 'modules/accessibility/utils/chartUtilities.js', [_modules['modules/accessibility/utils/htmlUtilities.js'], _modules['parts/Globals.js']], function (HTMLUtilities, H) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Utils for dealing with charts.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString;
        var find = H.find;
        /* eslint-disable valid-jsdoc */
        /**
         * @return {string}
         */
        function getChartTitle(chart) {
            return stripHTMLTags(chart.options.title.text ||
                chart.langFormat('accessibility.defaultChartTitle', { chart: chart }));
        }
        /**
         * @param {Highcharts.Axis} axis
         * @return {string}
         */
        function getAxisDescription(axis) {
            return stripHTMLTags(axis && (axis.userOptions && axis.userOptions.accessibility &&
                axis.userOptions.accessibility.description ||
                axis.axisTitle && axis.axisTitle.textStr ||
                axis.options.id ||
                axis.categories && 'categories' ||
                axis.isDatetimeAxis && 'Time' ||
                'values'));
        }
        /**
         * Get the DOM element for the first point in the series.
         * @private
         * @param {Highcharts.Series} series
         * The series to get element for.
         * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined}
         * The DOM element for the point.
         */
        function getSeriesFirstPointElement(series) {
            if (series.points &&
                series.points.length &&
                series.points[0].graphic) {
                return series.points[0].graphic.element;
            }
        }
        /**
         * Get the DOM element for the series that we put accessibility info on.
         * @private
         * @param {Highcharts.Series} series
         * The series to get element for.
         * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined}
         * The DOM element for the series
         */
        function getSeriesA11yElement(series) {
            var firstPointEl = getSeriesFirstPointElement(series);
            return (firstPointEl &&
                firstPointEl.parentNode || series.graph &&
                series.graph.element || series.group &&
                series.group.element); // Could be tracker series depending on series type
        }
        /**
         * Remove aria-hidden from element. Also unhides parents of the element, and
         * hides siblings that are not explicitly unhidden.
         * @private
         * @param {Highcharts.Chart} chart
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element
         * @return {void}
         */
        function unhideChartElementFromAT(chart, element) {
            element.setAttribute('aria-hidden', false);
            if (element === chart.renderTo || !element.parentNode) {
                return;
            }
            // Hide siblings unless their hidden state is already explicitly set
            Array.prototype.forEach.call(element.parentNode.childNodes, function (node) {
                if (!node.hasAttribute('aria-hidden')) {
                    node.setAttribute('aria-hidden', true);
                }
            });
            // Repeat for parent
            unhideChartElementFromAT(chart, element.parentNode);
        }
        /**
         * Hide series from screen readers.
         * @private
         * @param {Highcharts.Series} series
         * The series to hide
         * @return {void}
         */
        function hideSeriesFromAT(series) {
            var seriesEl = getSeriesA11yElement(series);
            if (seriesEl) {
                seriesEl.setAttribute('aria-hidden', true);
            }
        }
        /**
         * Get series objects by series name.
         * @private
         * @param {Highcharts.Chart} chart
         * @param {string} name
         * @return {Array<Highcharts.Series>}
         */
        function getSeriesFromName(chart, name) {
            if (!name) {
                return chart.series;
            }
            return (chart.series || []).filter(function (s) {
                return s.name === name;
            });
        }
        /**
         * Get point in a series from x/y values.
         * @private
         * @param {Array<Highcharts.Series>} series
         * @param {number} x
         * @param {number} y
         * @return {Highcharts.Point|undefined}
         */
        function getPointFromXY(series, x, y) {
            var i = series.length, res;
            while (i--) {
                res = find(series[i].points || [], function (p) {
                    return p.x === x && p.y === y;
                });
                if (res) {
                    return res;
                }
            }
        }
        var ChartUtilities = {
            getChartTitle: getChartTitle,
            getAxisDescription: getAxisDescription,
            getPointFromXY: getPointFromXY,
            getSeriesFirstPointElement: getSeriesFirstPointElement,
            getSeriesFromName: getSeriesFromName,
            getSeriesA11yElement: getSeriesA11yElement,
            unhideChartElementFromAT: unhideChartElementFromAT,
            hideSeriesFromAT: hideSeriesFromAT
        };

        return ChartUtilities;
    });
    _registerModule(_modules, 'modules/accessibility/KeyboardNavigationHandler.js', [_modules['parts/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Keyboard navigation handler base class definition
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var find = H.find;
        /**
         * Options for the keyboard navigation handler.
         *
         * @interface Highcharts.KeyboardNavigationHandlerOptionsObject
         */ /**
        * An array containing pairs of an array of keycodes, mapped to a handler
        * function. When the keycode is received, the handler is called with the
        * keycode as parameter.
        * @name Highcharts.KeyboardNavigationHandlerOptionsObject#keyCodeMap
        * @type {Array<Array<Array<number>, Function>>}
        */ /**
        * Function to run on initialization of module.
        * @name Highcharts.KeyboardNavigationHandlerOptionsObject#init
        * @type {Function}
        */ /**
        * Function to run before moving to next/prev module. Receives moving direction
        * as parameter: +1 for next, -1 for previous.
        * @name Highcharts.KeyboardNavigationHandlerOptionsObject#terminate
        * @type {Function|undefined}
        */ /**
        * Function to run to validate module. Should return false if module should not
        * run, true otherwise. Receives chart as parameter.
        * @name Highcharts.KeyboardNavigationHandlerOptionsObject#validate
        * @type {Function|undefined}
        */
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * Define a keyboard navigation handler for use with a
         * Highcharts.AccessibilityComponent instance. This functions as an abstraction
         * layer for keyboard navigation, and defines a map of keyCodes to handler
         * functions.
         *
         * @requires module:modules/accessibility
         *
         * @sample highcharts/accessibility/custom-component
         *         Custom accessibility component
         *
         * @class
         * @name Highcharts.KeyboardNavigationHandler
         *
         * @param {Highcharts.Chart} chart
         * The chart this module should act on.
         *
         * @param {Highcharts.KeyboardNavigationHandlerOptionsObject} options
         * Options for the keyboard navigation handler.
         */
        function KeyboardNavigationHandler(chart, options) {
            this.chart = chart;
            this.keyCodeMap = options.keyCodeMap || [];
            this.validate = options.validate;
            this.init = options.init;
            this.terminate = options.terminate;
            // Response enum
            this.response = {
                success: 1,
                prev: 2,
                next: 3,
                noHandler: 4,
                fail: 5 // Handler failed
            };
        }
        KeyboardNavigationHandler.prototype = {
            /**
             * Find handler function(s) for key code in the keyCodeMap and run it.
             *
             * @function KeyboardNavigationHandler#run
             * @param {global.KeyboardEvent} e
             * @return {number} Returns a response code indicating whether the run was
             *      a success/fail/unhandled, or if we should move to next/prev module.
             */
            run: function (e) {
                var keyCode = e.which || e.keyCode, response = this.response.noHandler, handlerCodeSet = find(this.keyCodeMap, function (codeSet) {
                    return codeSet[0].indexOf(keyCode) > -1;
                });
                if (handlerCodeSet) {
                    response = handlerCodeSet[1].call(this, keyCode, e);
                }
                else if (keyCode === 9) {
                    // Default tab handler, move to next/prev module
                    response = this.response[e.shiftKey ? 'prev' : 'next'];
                }
                else if (keyCode === 27) {
                    // Default esc handler, hide tooltip
                    if (this.chart && this.chart.tooltip) {
                        this.chart.tooltip.hide(0);
                    }
                    response = this.response.success;
                }
                return response;
            }
        };

        return KeyboardNavigationHandler;
    });
    _registerModule(_modules, 'modules/accessibility/utils/EventProvider.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Class that can keep track of events added, and clean them up on destroy.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         * @class
         */
        var EventProvider = function () {
            this.eventRemovers = [];
        };
        extend(EventProvider.prototype, {
            /**
             * Add an event to an element and keep track of it for later removal.
             * Same args as Highcharts.addEvent.
             * @private
             * @return {Function}
             */
            addEvent: function () {
                var remover = H.addEvent.apply(H, arguments);
                this.eventRemovers.push(remover);
                return remover;
            },
            /**
             * Remove all added events.
             * @private
             * @return {void}
             */
            removeAddedEvents: function () {
                this.eventRemovers.forEach(function (remover) {
                    remover();
                });
                this.eventRemovers = [];
            }
        });

        return EventProvider;
    });
    _registerModule(_modules, 'modules/accessibility/utils/DOMElementProvider.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Class that can keep track of elements added to DOM and clean them up on
         *  destroy.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var doc = H.win.document;
        var extend = U.extend;
        var removeElement = HTMLUtilities.removeElement;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         * @class
         */
        var DOMElementProvider = function () {
            this.elements = [];
        };
        extend(DOMElementProvider.prototype, {
            /**
             * Create an element and keep track of it for later removal.
             * Same args as document.createElement
             * @private
             */
            createElement: function () {
                var el = doc.createElement.apply(doc, arguments);
                this.elements.push(el);
                return el;
            },
            /**
             * Destroy all created elements, removing them from the DOM.
             * @private
             */
            destroyCreatedElements: function () {
                this.elements.forEach(function (element) {
                    removeElement(element);
                });
                this.elements = [];
            }
        });

        return DOMElementProvider;
    });
    _registerModule(_modules, 'modules/accessibility/AccessibilityComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/EventProvider.js'], _modules['modules/accessibility/utils/DOMElementProvider.js']], function (H, U, HTMLUtilities, ChartUtilities, EventProvider, DOMElementProvider) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component class definition
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var win = H.win, doc = win.document, merge = H.merge, fireEvent = H.fireEvent;
        var extend = U.extend;
        var removeElement = HTMLUtilities.removeElement, getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT;
        /* eslint-disable valid-jsdoc */
        /** @lends Highcharts.AccessibilityComponent */
        var functionsToOverrideByDerivedClasses = {
            /**
             * Called on component initialization.
             */
            init: function () { },
            /**
             * Get keyboard navigation handler for this component.
             * @return {Highcharts.KeyboardNavigationHandler}
             */
            getKeyboardNavigation: function () { },
            /**
             * Called on updates to the chart, including options changes.
             * Note that this is also called on first render of chart.
             */
            onChartUpdate: function () { },
            /**
             * Called on every chart render.
             */
            onChartRender: function () { },
            /**
             * Called when accessibility is disabled or chart is destroyed.
             */
            destroy: function () { }
        };
        /**
         * The AccessibilityComponent base class, representing a part of the chart that
         * has accessibility logic connected to it. This class can be inherited from to
         * create a custom accessibility component for a chart.
         *
         * Components should take care to destroy added elements and unregister event
         * handlers on destroy. This is handled automatically if using this.addEvent and
         * this.createElement.
         *
         * @sample highcharts/accessibility/custom-component
         *         Custom accessibility component
         *
         * @requires module:modules/accessibility
         * @class
         * @name Highcharts.AccessibilityComponent
         */
        function AccessibilityComponent() { }
        /**
         * @lends Highcharts.AccessibilityComponent
         */
        AccessibilityComponent.prototype = {
            /**
             * Initialize the class
             * @private
             * @param {Highcharts.Chart} chart
             *        Chart object
             */
            initBase: function (chart) {
                this.chart = chart;
                this.eventProvider = new EventProvider();
                this.domElementProvider = new DOMElementProvider();
                // Key code enum for common keys
                this.keyCodes = {
                    left: 37,
                    right: 39,
                    up: 38,
                    down: 40,
                    enter: 13,
                    space: 32,
                    esc: 27,
                    tab: 9
                };
            },
            /**
             * Add an event to an element and keep track of it for later removal.
             * See EventProvider for details.
             * @private
             */
            addEvent: function () {
                return this.eventProvider.addEvent
                    .apply(this.eventProvider, arguments);
            },
            /**
             * Create an element and keep track of it for later removal.
             * See DOMElementProvider for details.
             * @private
             */
            createElement: function () {
                return this.domElementProvider.createElement.apply(this.domElementProvider, arguments);
            },
            /**
             * Fire an event on an element that is either wrapped by Highcharts,
             * or a DOM element
             * @private
             * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement|
             *  Highcharts.SVGDOMElement|Highcharts.SVGElement} el
             * @param {Event} eventObject
             */
            fireEventOnWrappedOrUnwrappedElement: function (el, eventObject) {
                var type = eventObject.type;
                if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
                    if (el.dispatchEvent) {
                        el.dispatchEvent(eventObject);
                    }
                    else {
                        el.fireEvent(type, eventObject);
                    }
                }
                else {
                    fireEvent(el, type, eventObject);
                }
            },
            /**
             * Utility function to attempt to fake a click event on an element.
             * @private
             * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element
             */
            fakeClickEvent: function (element) {
                if (element) {
                    var fakeEventObject = getFakeMouseEvent('click');
                    this.fireEventOnWrappedOrUnwrappedElement(element, fakeEventObject);
                }
            },
            /**
             * Add a new proxy group to the proxy container. Creates the proxy container
             * if it does not exist.
             * @private
             * @param {Highcharts.HTMLAttributes} [attrs]
             * The attributes to set on the new group div.
             * @return {Highcharts.HTMLDOMElement}
             * The new proxy group element.
             */
            addProxyGroup: function (attrs) {
                this.createOrUpdateProxyContainer();
                var groupDiv = this.createElement('div');
                Object.keys(attrs || {}).forEach(function (prop) {
                    if (attrs[prop] !== null) {
                        groupDiv.setAttribute(prop, attrs[prop]);
                    }
                });
                this.chart.a11yProxyContainer.appendChild(groupDiv);
                return groupDiv;
            },
            /**
             * Creates and updates DOM position of proxy container
             * @private
             */
            createOrUpdateProxyContainer: function () {
                var chart = this.chart, rendererSVGEl = chart.renderer.box;
                chart.a11yProxyContainer = chart.a11yProxyContainer ||
                    this.createProxyContainerElement();
                if (rendererSVGEl.nextSibling !== chart.a11yProxyContainer) {
                    chart.container.insertBefore(chart.a11yProxyContainer, rendererSVGEl.nextSibling);
                }
            },
            /**
             * @private
             * @return {Highcharts.HTMLDOMElement} element
             */
            createProxyContainerElement: function () {
                var pc = doc.createElement('div');
                pc.className = 'highcharts-a11y-proxy-container';
                return pc;
            },
            /**
             * Create an invisible proxy HTML button in the same position as an SVG
             * element
             * @private
             * @param {Highcharts.SVGElement} svgElement
             * The wrapped svg el to proxy.
             * @param {Highcharts.HTMLDOMElement} parentGroup
             * The proxy group element in the proxy container to add this button to.
             * @param {Highcharts.SVGAttributes} [attributes]
             * Additional attributes to set.
             * @param {Highcharts.SVGElement} [posElement]
             * Element to use for positioning instead of svgElement.
             * @param {Function} [preClickEvent]
             * Function to call before click event fires.
             *
             * @return {Highcharts.HTMLDOMElement} The proxy button.
             */
            createProxyButton: function (svgElement, parentGroup, attributes, posElement, preClickEvent) {
                var svgEl = svgElement.element, proxy = this.createElement('button'), attrs = merge({
                    'aria-label': svgEl.getAttribute('aria-label')
                }, attributes), bBox = this.getElementPosition(posElement || svgElement);
                Object.keys(attrs).forEach(function (prop) {
                    if (attrs[prop] !== null) {
                        proxy.setAttribute(prop, attrs[prop]);
                    }
                });
                proxy.className = 'highcharts-a11y-proxy-button';
                if (preClickEvent) {
                    this.addEvent(proxy, 'click', preClickEvent);
                }
                this.setProxyButtonStyle(proxy, bBox);
                this.proxyMouseEventsForButton(svgEl, proxy);
                // Add to chart div and unhide from screen readers
                parentGroup.appendChild(proxy);
                if (!attrs['aria-hidden']) {
                    unhideChartElementFromAT(this.chart, proxy);
                }
                return proxy;
            },
            /**
             * Get the position relative to chart container for a wrapped SVG element.
             * @private
             * @param {Highcharts.SVGElement} element
             * The element to calculate position for.
             * @return {Highcharts.BBoxObject}
             * Object with x and y props for the position.
             */
            getElementPosition: function (element) {
                var el = element.element, div = this.chart.renderTo;
                if (div && el && el.getBoundingClientRect) {
                    var rectEl = el.getBoundingClientRect(), rectDiv = div.getBoundingClientRect();
                    return {
                        x: rectEl.left - rectDiv.left,
                        y: rectEl.top - rectDiv.top,
                        width: rectEl.right - rectEl.left,
                        height: rectEl.bottom - rectEl.top
                    };
                }
                return { x: 0, y: 0, width: 1, height: 1 };
            },
            /**
             * @private
             * @param {Highcharts.HTMLElement} button
             * @param {Highcharts.BBoxObject} bBox
             */
            setProxyButtonStyle: function (button, bBox) {
                merge(true, button.style, {
                    'border-width': 0,
                    'background-color': 'transparent',
                    cursor: 'pointer',
                    outline: 'none',
                    opacity: 0.001,
                    filter: 'alpha(opacity=1)',
                    '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)',
                    zIndex: 999,
                    overflow: 'hidden',
                    padding: 0,
                    margin: 0,
                    display: 'block',
                    position: 'absolute',
                    width: (bBox.width || 1) + 'px',
                    height: (bBox.height || 1) + 'px',
                    left: (bBox.x || 0) + 'px',
                    top: (bBox.y || 0) + 'px'
                });
            },
            /**
             * @private
             * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement|
             *  Highcharts.SVGDOMElement|Highcharts.SVGElement} source
             * @param {Highcharts.HTMLElement} button
             */
            proxyMouseEventsForButton: function (source, button) {
                var component = this;
                [
                    'click', 'touchstart', 'touchend', 'touchcancel', 'touchmove',
                    'mouseover', 'mouseenter', 'mouseleave', 'mouseout'
                ].forEach(function (evtType) {
                    component.addEvent(button, evtType, function (e) {
                        var clonedEvent = component.cloneMouseEvent(e);
                        if (source) {
                            component.fireEventOnWrappedOrUnwrappedElement(source, clonedEvent);
                        }
                        e.stopPropagation();
                        e.preventDefault();
                    });
                });
            },
            /**
             * Utility function to clone a mouse event for re-dispatching.
             * @private
             * @param {global.MouseEvent} e The event to clone.
             * @return {global.MouseEvent} The cloned event
             */
            cloneMouseEvent: function (e) {
                if (typeof win.MouseEvent === 'function') {
                    return new win.MouseEvent(e.type, e);
                }
                // No MouseEvent support, try using initMouseEvent
                if (doc.createEvent) {
                    var evt = doc.createEvent('MouseEvent');
                    if (evt.initMouseEvent) {
                        evt.initMouseEvent(e.type, e.bubbles, // #10561, #12161
                        e.cancelable, e.view || win, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
                        return evt;
                    }
                }
                return getFakeMouseEvent(e.type);
            },
            /**
             * Remove traces of the component.
             * @private
             */
            destroyBase: function () {
                removeElement(this.chart.a11yProxyContainer);
                this.domElementProvider.destroyCreatedElements();
                this.eventProvider.removeAddedEvents();
            }
        };
        extend(AccessibilityComponent.prototype, functionsToOverrideByDerivedClasses);

        return AccessibilityComponent;
    });
    _registerModule(_modules, 'modules/accessibility/KeyboardNavigation.js', [_modules['parts/Globals.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/EventProvider.js']], function (H, HTMLUtilities, KeyboardNavigationHandler, EventProvider) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Main keyboard navigation handling.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var merge = H.merge, win = H.win, doc = win.document;
        var getElement = HTMLUtilities.getElement;
        /* eslint-disable valid-jsdoc */
        /**
         * The KeyboardNavigation class, containing the overall keyboard navigation
         * logic for the chart.
         *
         * @requires module:modules/accessibility
         *
         * @private
         * @class
         * @param {Highcharts.Chart} chart
         *        Chart object
         * @param {object} components
         *        Map of component names to AccessibilityComponent objects.
         * @name Highcharts.KeyboardNavigation
         */
        function KeyboardNavigation(chart, components) {
            this.init(chart, components);
        }
        KeyboardNavigation.prototype = {
            /**
             * Initialize the class
             * @private
             * @param {Highcharts.Chart} chart
             *        Chart object
             * @param {object} components
             *        Map of component names to AccessibilityComponent objects.
             */
            init: function (chart, components) {
                var keyboardNavigation = this, e = this.eventProvider = new EventProvider();
                this.chart = chart;
                this.components = components;
                this.modules = [];
                this.currentModuleIx = 0;
                // Add keydown event
                e.addEvent(chart.renderTo, 'keydown', function (e) {
                    keyboardNavigation.onKeydown(e);
                });
                // Add mouseup event on doc
                e.addEvent(doc, 'mouseup', function () {
                    keyboardNavigation.onMouseUp();
                });
                // Run an update to get all modules
                this.update();
                // Init first module
                if (this.modules.length) {
                    this.modules[0].init(1);
                }
            },
            /**
             * Update the modules for the keyboard navigation.
             * @param {Array<string>} [order]
             *        Array specifying the tab order of the components.
             */
            update: function (order) {
                var a11yOptions = this.chart.options.accessibility, keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, components = this.components;
                this.updateContainerTabindex();
                if (keyboardOptions &&
                    keyboardOptions.enabled &&
                    order &&
                    order.length) {
                    // We (still) have keyboard navigation. Update module list
                    this.modules = order.reduce(function (modules, componentName) {
                        var navModules = components[componentName].getKeyboardNavigation();
                        return modules.concat(navModules);
                    }, [
                        // Add an empty module at the start of list, to allow users to
                        // tab into the chart.
                        new KeyboardNavigationHandler(this.chart, {
                            init: function () { }
                        })
                    ]);
                    this.updateExitAnchor();
                }
                else {
                    this.modules = [];
                    this.currentModuleIx = 0;
                    this.removeExitAnchor();
                }
            },
            /**
             * Reset chart navigation state if we click outside the chart and it's
             * not already reset.
             * @private
             */
            onMouseUp: function () {
                if (!this.keyboardReset &&
                    !(this.chart.pointer && this.chart.pointer.chartPosition)) {
                    var chart = this.chart, curMod = this.modules &&
                        this.modules[this.currentModuleIx || 0];
                    if (curMod && curMod.terminate) {
                        curMod.terminate();
                    }
                    if (chart.focusElement) {
                        chart.focusElement.removeFocusBorder();
                    }
                    this.currentModuleIx = 0;
                    this.keyboardReset = true;
                }
            },
            /**
             * Function to run on keydown
             * @private
             * @param {global.KeyboardEvent} ev
             * Browser keydown event.
             */
            onKeydown: function (ev) {
                var e = ev || win.event, preventDefault, curNavModule = this.modules && this.modules.length &&
                    this.modules[this.currentModuleIx];
                // Used for resetting nav state when clicking outside chart
                this.keyboardReset = false;
                // If there is a nav module for the current index, run it.
                // Otherwise, we are outside of the chart in some direction.
                if (curNavModule) {
                    var response = curNavModule.run(e);
                    if (response === curNavModule.response.success) {
                        preventDefault = true;
                    }
                    else if (response === curNavModule.response.prev) {
                        preventDefault = this.prev();
                    }
                    else if (response === curNavModule.response.next) {
                        preventDefault = this.next();
                    }
                    if (preventDefault) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
                }
            },
            /**
             * Go to previous module.
             * @private
             */
            prev: function () {
                return this.move(-1);
            },
            /**
             * Go to next module.
             * @private
             */
            next: function () {
                return this.move(1);
            },
            /**
             * Move to prev/next module.
             * @private
             * @param {number} direction
             * Direction to move. +1 for next, -1 for prev.
             * @return {boolean}
             * True if there was a valid module in direction.
             */
            move: function (direction) {
                var curModule = this.modules && this.modules[this.currentModuleIx];
                if (curModule && curModule.terminate) {
                    curModule.terminate(direction);
                }
                // Remove existing focus border if any
                if (this.chart.focusElement) {
                    this.chart.focusElement.removeFocusBorder();
                }
                this.currentModuleIx += direction;
                var newModule = this.modules && this.modules[this.currentModuleIx];
                if (newModule) {
                    if (newModule.validate && !newModule.validate()) {
                        return this.move(direction); // Invalid module, recurse
                    }
                    if (newModule.init) {
                        newModule.init(direction); // Valid module, init it
                        return true;
                    }
                }
                // No module
                this.currentModuleIx = 0; // Reset counter
                // Set focus to chart or exit anchor depending on direction
                if (direction > 0) {
                    this.exiting = true;
                    this.exitAnchor.focus();
                }
                else {
                    this.chart.renderTo.focus();
                }
                return false;
            },
            /**
             * We use an exit anchor to move focus out of chart whenever we want, by
             * setting focus to this div and not preventing the default tab action. We
             * also use this when users come back into the chart by tabbing back, in
             * order to navigate from the end of the chart.
             * @private
             */
            updateExitAnchor: function () {
                var endMarkerId = 'highcharts-end-of-chart-marker-' + this.chart.index, endMarker = getElement(endMarkerId);
                this.removeExitAnchor();
                if (endMarker) {
                    this.makeElementAnExitAnchor(endMarker);
                    this.exitAnchor = endMarker;
                }
                else {
                    this.createExitAnchor();
                }
            },
            /**
             * Chart container should have tabindex if navigation is enabled.
             * @private
             */
            updateContainerTabindex: function () {
                var a11yOptions = this.chart.options.accessibility, keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, shouldHaveTabindex = !(keyboardOptions && keyboardOptions.enabled === false), container = this.chart.container, curTabindex = container.getAttribute('tabIndex');
                if (shouldHaveTabindex && !curTabindex) {
                    container.setAttribute('tabindex', '0');
                }
                else if (!shouldHaveTabindex && curTabindex === '0') {
                    container.removeAttribute('tabindex');
                }
            },
            /**
             * @private
             */
            makeElementAnExitAnchor: function (el) {
                el.setAttribute('class', 'highcharts-exit-anchor');
                el.setAttribute('tabindex', '0');
                el.setAttribute('aria-hidden', false);
                // Handle focus
                this.addExitAnchorEventsToEl(el);
            },
            /**
             * Add new exit anchor to the chart.
             *
             * @private
             */
            createExitAnchor: function () {
                var chart = this.chart, exitAnchor = this.exitAnchor = doc.createElement('div');
                // Hide exit anchor
                merge(true, exitAnchor.style, {
                    position: 'absolute',
                    width: '1px',
                    height: '1px',
                    zIndex: 0,
                    overflow: 'hidden',
                    outline: 'none'
                });
                chart.renderTo.appendChild(exitAnchor);
                this.makeElementAnExitAnchor(exitAnchor);
            },
            /**
             * @private
             */
            removeExitAnchor: function () {
                if (this.exitAnchor && this.exitAnchor.parentNode) {
                    this.exitAnchor.parentNode
                        .removeChild(this.exitAnchor);
                    delete this.exitAnchor;
                }
            },
            /**
             * @private
             */
            addExitAnchorEventsToEl: function (element) {
                var chart = this.chart, keyboardNavigation = this;
                this.eventProvider.addEvent(element, 'focus', function (ev) {
                    var e = ev || win.event, curModule, focusComesFromChart = (e.relatedTarget &&
                        chart.container.contains(e.relatedTarget)), comingInBackwards = !(focusComesFromChart || keyboardNavigation.exiting);
                    if (comingInBackwards) {
                        chart.renderTo.focus();
                        e.preventDefault();
                        // Move to last valid keyboard nav module
                        // Note the we don't run it, just set the index
                        if (keyboardNavigation.modules &&
                            keyboardNavigation.modules.length) {
                            keyboardNavigation.currentModuleIx =
                                keyboardNavigation.modules.length - 1;
                            curModule = keyboardNavigation.modules[keyboardNavigation.currentModuleIx];
                            // Validate the module
                            if (curModule &&
                                curModule.validate && !curModule.validate()) {
                                // Invalid. Try moving backwards to find next valid.
                                keyboardNavigation.prev();
                            }
                            else if (curModule) {
                                // We have a valid module, init it
                                curModule.init(-1);
                            }
                        }
                    }
                    else {
                        // Don't skip the next focus, we only skip once.
                        keyboardNavigation.exiting = false;
                    }
                });
            },
            /**
             * Remove all traces of keyboard navigation.
             * @private
             */
            destroy: function () {
                this.removeExitAnchor();
                this.eventProvider.removeAddedEvents();
                if (this.chart.container.getAttribute('tabindex') === '0') {
                    this.chart.container.removeAttribute('tabindex');
                }
            }
        };

        return KeyboardNavigation;
    });
    _registerModule(_modules, 'modules/accessibility/components/LegendComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for chart legend.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString, removeElement = HTMLUtilities.removeElement;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function scrollLegendToItem(legend, itemIx) {
            var itemPage = legend.allItems[itemIx].pageIx, curPage = legend.currentPage;
            if (typeof itemPage !== 'undefined' && itemPage + 1 !== curPage) {
                legend.scroll(1 + itemPage - curPage);
            }
        }
        /**
         * @private
         */
        function shouldDoLegendA11y(chart) {
            var items = chart.legend && chart.legend.allItems, legendA11yOptions = (chart.options.legend.accessibility || {});
            return !!(items && items.length &&
                !(chart.colorAxis && chart.colorAxis.length) &&
                legendA11yOptions.enabled !== false);
        }
        /**
         * Highlight legend item by index.
         *
         * @private
         * @function Highcharts.Chart#highlightLegendItem
         *
         * @param {number} ix
         *
         * @return {boolean}
         */
        H.Chart.prototype.highlightLegendItem = function (ix) {
            var items = this.legend.allItems, oldIx = this.highlightedLegendItemIx;
            if (items[ix]) {
                if (items[oldIx]) {
                    H.fireEvent(items[oldIx].legendGroup.element, 'mouseout');
                }
                scrollLegendToItem(this.legend, ix);
                this.setFocusToElement(items[ix].legendItem, items[ix].a11yProxyElement);
                H.fireEvent(items[ix].legendGroup.element, 'mouseover');
                return true;
            }
            return false;
        };
        // Keep track of pressed state for legend items
        H.addEvent(H.Legend, 'afterColorizeItem', function (e) {
            var chart = this.chart, a11yOptions = chart.options.accessibility, legendItem = e.item;
            if (a11yOptions.enabled && legendItem && legendItem.a11yProxyElement) {
                legendItem.a11yProxyElement.setAttribute('aria-pressed', e.visible ? 'false' : 'true');
            }
        });
        /**
         * The LegendComponent class
         *
         * @private
         * @class
         * @name Highcharts.LegendComponent
         */
        var LegendComponent = function () { };
        LegendComponent.prototype = new AccessibilityComponent();
        extend(LegendComponent.prototype, /** @lends Highcharts.LegendComponent */ {
            /**
             * Init the component
             * @private
             */
            init: function () {
                var component = this;
                this.addEvent(H.Legend, 'afterScroll', function () {
                    if (this.chart === component.chart) {
                        component.updateProxies();
                    }
                });
            },
            /**
             * @private
             */
            updateLegendItemProxyVisibility: function () {
                var legend = this.chart.legend, items = legend.allItems || [], curPage = legend.currentPage || 1;
                items.forEach(function (item) {
                    var itemPage = item.pageIx || 0, hide = itemPage !== curPage - 1;
                    if (item.a11yProxyElement) {
                        item.a11yProxyElement.style.visibility = hide ?
                            'hidden' : 'visible';
                    }
                });
            },
            /**
             * The legend needs updates on every render, in order to update positioning
             * of the proxy overlays.
             */
            onChartRender: function () {
                var component = this;
                // Ignore render after proxy clicked. No need to destroy it, and
                // destroying also kills focus.
                if (this.legendProxyButtonClicked) {
                    delete component.legendProxyButtonClicked;
                    return;
                }
                this.updateProxies();
            },
            /**
             * @private
             */
            updateProxies: function () {
                removeElement(this.legendProxyGroup);
                if (shouldDoLegendA11y(this.chart)) {
                    this.addLegendProxyGroup();
                    this.proxyLegendItems();
                    this.updateLegendItemProxyVisibility();
                }
            },
            /**
             * @private
             */
            addLegendProxyGroup: function () {
                var a11yOptions = this.chart.options.accessibility, groupLabel = this.chart.langFormat('accessibility.legend.legendLabel', {}), groupRole = a11yOptions.landmarkVerbosity === 'all' ?
                    'region' : null;
                this.legendProxyGroup = this.addProxyGroup({
                    'aria-label': groupLabel,
                    'role': groupRole
                });
            },
            /**
             * @private
             */
            proxyLegendItems: function () {
                var component = this, items = (this.chart.legend &&
                    this.chart.legend.allItems || []);
                items.forEach(function (item) {
                    if (item.legendItem && item.legendItem.element) {
                        component.proxyLegendItem(item);
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
             */
            proxyLegendItem: function (item) {
                var component = this, itemLabel = this.chart.langFormat('accessibility.legend.legendItem', {
                    chart: this.chart,
                    itemName: stripHTMLTags(item.name)
                }), attribs = {
                    tabindex: -1,
                    'aria-pressed': !item.visible,
                    'aria-label': itemLabel
                }, 
                // Keep track of when we should ignore next render
                preClickEvent = function () {
                    component.legendProxyButtonClicked = true;
                }, 
                // Considers useHTML
                proxyPositioningElement = item.legendGroup.div ?
                    item.legendItem : item.legendGroup;
                item.a11yProxyElement = this.createProxyButton(item.legendItem, this.legendProxyGroup, attribs, proxyPositioningElement, preClickEvent);
            },
            /**
             * Get keyboard navigation handler for this component.
             * @return {Highcharts.KeyboardNavigationHandler}
             */
            getKeyboardNavigation: function () {
                var keys = this.keyCodes, component = this, chart = this.chart;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [
                            [keys.left, keys.right, keys.up, keys.down],
                            function (keyCode) {
                                return component.onKbdArrowKey(this, keyCode);
                            }
                        ],
                        [
                            [keys.enter, keys.space],
                            function () {
                                return component.onKbdClick(this);
                            }
                        ]
                    ],
                    validate: function () {
                        return component.shouldHaveLegendNavigation();
                    },
                    init: function (direction) {
                        return component.onKbdNavigationInit(direction);
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @param {number} keyCode
             * @return {number}
             * Response code
             */
            onKbdArrowKey: function (keyboardNavigationHandler, keyCode) {
                var keys = this.keyCodes, response = keyboardNavigationHandler.response, chart = this.chart, a11yOptions = chart.options.accessibility, numItems = chart.legend.allItems.length, direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1;
                var res = chart.highlightLegendItem(this.highlightedLegendItemIx + direction);
                if (res) {
                    this.highlightedLegendItemIx += direction;
                    return response.success;
                }
                if (numItems > 1 &&
                    a11yOptions.keyboardNavigation.wrapAround) {
                    keyboardNavigationHandler.init(direction);
                    return response.success;
                }
                // No wrap, move
                return response[direction > 0 ? 'next' : 'prev'];
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @return {number}
             * Response code
             */
            onKbdClick: function (keyboardNavigationHandler) {
                var legendItem = this.chart.legend.allItems[this.highlightedLegendItemIx];
                if (legendItem && legendItem.a11yProxyElement) {
                    H.fireEvent(legendItem.a11yProxyElement, 'click');
                }
                return keyboardNavigationHandler.response.success;
            },
            /**
             * @private
             * @return {boolean|undefined}
             */
            shouldHaveLegendNavigation: function () {
                var chart = this.chart, legendOptions = chart.options.legend || {}, hasLegend = chart.legend && chart.legend.allItems, hasColorAxis = chart.colorAxis && chart.colorAxis.length, legendA11yOptions = (legendOptions.accessibility || {});
                return !!(hasLegend &&
                    chart.legend.display &&
                    !hasColorAxis &&
                    legendA11yOptions.enabled &&
                    legendA11yOptions.keyboardNavigation &&
                    legendA11yOptions.keyboardNavigation.enabled);
            },
            /**
             * @private
             * @param {number} direction
             */
            onKbdNavigationInit: function (direction) {
                var chart = this.chart, lastIx = chart.legend.allItems.length - 1, ixToHighlight = direction > 0 ? 0 : lastIx;
                chart.highlightLegendItem(ixToHighlight);
                this.highlightedLegendItemIx = ixToHighlight;
            }
        });

        return LegendComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/MenuComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for exporting menu.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT;
        var removeElement = HTMLUtilities.removeElement, getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * Show the export menu and focus the first item (if exists).
         *
         * @private
         * @function Highcharts.Chart#showExportMenu
         */
        H.Chart.prototype.showExportMenu = function () {
            if (this.exportSVGElements && this.exportSVGElements[0]) {
                var el = this.exportSVGElements[0].element;
                if (el.onclick) {
                    el.onclick(getFakeMouseEvent('click'));
                }
            }
        };
        /**
         * @private
         * @function Highcharts.Chart#hideExportMenu
         */
        H.Chart.prototype.hideExportMenu = function () {
            var chart = this, exportList = chart.exportDivElements;
            if (exportList && chart.exportContextMenu) {
                // Reset hover states etc.
                exportList.forEach(function (el) {
                    if (el.className === 'highcharts-menu-item' && el.onmouseout) {
                        el.onmouseout(getFakeMouseEvent('mouseout'));
                    }
                });
                chart.highlightedExportItemIx = 0;
                // Hide the menu div
                chart.exportContextMenu.hideMenu();
                // Make sure the chart has focus and can capture keyboard events
                chart.container.focus();
            }
        };
        /**
         * Highlight export menu item by index.
         *
         * @private
         * @function Highcharts.Chart#highlightExportItem
         *
         * @param {number} ix
         *
         * @return {boolean}
         */
        H.Chart.prototype.highlightExportItem = function (ix) {
            var listItem = this.exportDivElements && this.exportDivElements[ix], curHighlighted = this.exportDivElements &&
                this.exportDivElements[this.highlightedExportItemIx], hasSVGFocusSupport;
            if (listItem &&
                listItem.tagName === 'LI' &&
                !(listItem.children && listItem.children.length)) {
                // Test if we have focus support for SVG elements
                hasSVGFocusSupport = !!(this.renderTo.getElementsByTagName('g')[0] || {}).focus;
                // Only focus if we can set focus back to the elements after
                // destroying the menu (#7422)
                if (listItem.focus && hasSVGFocusSupport) {
                    listItem.focus();
                }
                if (curHighlighted && curHighlighted.onmouseout) {
                    curHighlighted.onmouseout(getFakeMouseEvent('mouseout'));
                }
                if (listItem.onmouseover) {
                    listItem.onmouseover(getFakeMouseEvent('mouseover'));
                }
                this.highlightedExportItemIx = ix;
                return true;
            }
            return false;
        };
        /**
         * Try to highlight the last valid export menu item.
         *
         * @private
         * @function Highcharts.Chart#highlightLastExportItem
         * @return {boolean}
         */
        H.Chart.prototype.highlightLastExportItem = function () {
            var chart = this, i;
            if (chart.exportDivElements) {
                i = chart.exportDivElements.length;
                while (i--) {
                    if (chart.highlightExportItem(i)) {
                        return true;
                    }
                }
            }
            return false;
        };
        /**
         * @private
         * @param {Highcharts.Chart} chart
         */
        function exportingShouldHaveA11y(chart) {
            var exportingOpts = chart.options.exporting;
            return !!(exportingOpts &&
                exportingOpts.enabled !== false &&
                exportingOpts.accessibility &&
                exportingOpts.accessibility.enabled &&
                chart.exportSVGElements &&
                chart.exportSVGElements[0] &&
                chart.exportSVGElements[0].element);
        }
        /**
         * The MenuComponent class
         *
         * @private
         * @class
         * @name Highcharts.MenuComponent
         */
        var MenuComponent = function () { };
        MenuComponent.prototype = new AccessibilityComponent();
        extend(MenuComponent.prototype, /** @lends Highcharts.MenuComponent */ {
            /**
             * Init the component
             */
            init: function () {
                var chart = this.chart, component = this;
                this.addEvent(chart, 'exportMenuShown', function () {
                    component.onMenuShown();
                });
                this.addEvent(chart, 'exportMenuHidden', function () {
                    component.onMenuHidden();
                });
            },
            /**
             * @private
             */
            onMenuHidden: function () {
                var menu = this.chart.exportContextMenu;
                if (menu) {
                    menu.setAttribute('aria-hidden', 'true');
                }
                this.setExportButtonExpandedState('false');
            },
            /**
             * @private
             */
            onMenuShown: function () {
                var chart = this.chart, menu = chart.exportContextMenu;
                if (menu) {
                    this.addAccessibleContextMenuAttribs();
                    unhideChartElementFromAT(chart, menu);
                }
                this.setExportButtonExpandedState('true');
            },
            /**
             * @private
             * @param {string} stateStr
             */
            setExportButtonExpandedState: function (stateStr) {
                var button = this.exportButtonProxy;
                if (button) {
                    button.setAttribute('aria-expanded', stateStr);
                }
            },
            /**
             * Called on each render of the chart. We need to update positioning of the
             * proxy overlay.
             */
            onChartRender: function () {
                var chart = this.chart, a11yOptions = chart.options.accessibility;
                // Always start with a clean slate
                removeElement(this.exportProxyGroup);
                // Set screen reader properties on export menu
                if (exportingShouldHaveA11y(chart)) {
                    // Proxy button and group
                    this.exportProxyGroup = this.addProxyGroup(
                    // Wrap in a region div if verbosity is high
                    a11yOptions.landmarkVerbosity === 'all' ? {
                        'aria-label': chart.langFormat('accessibility.exporting.exportRegionLabel', { chart: chart }),
                        'role': 'region'
                    } : {});
                    var button = (this.chart.exportSVGElements[0]);
                    this.exportButtonProxy = this.createProxyButton(button, this.exportProxyGroup, {
                        'aria-label': chart.langFormat('accessibility.exporting.menuButtonLabel', { chart: chart }),
                        'aria-expanded': 'false'
                    });
                }
            },
            /**
             * @private
             */
            addAccessibleContextMenuAttribs: function () {
                var chart = this.chart, exportList = chart.exportDivElements;
                if (exportList && exportList.length) {
                    // Set tabindex on the menu items to allow focusing by script
                    // Set role to give screen readers a chance to pick up the contents
                    exportList.forEach(function (item) {
                        if (item.tagName === 'LI' &&
                            !(item.children && item.children.length)) {
                            item.setAttribute('tabindex', -1);
                        }
                        else {
                            item.setAttribute('aria-hidden', 'true');
                        }
                    });
                    // Set accessibility properties on parent div
                    var parentDiv = exportList[0].parentNode;
                    parentDiv.removeAttribute('aria-hidden');
                    parentDiv.setAttribute('aria-label', chart.langFormat('accessibility.exporting.chartMenuLabel', { chart: chart }));
                }
            },
            /**
             * Get keyboard navigation handler for this component.
             * @return {Highcharts.KeyboardNavigationHandler}
             */
            getKeyboardNavigation: function () {
                var keys = this.keyCodes, chart = this.chart, component = this;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        // Arrow prev handler
                        [
                            [keys.left, keys.up],
                            function () {
                                return component.onKbdPrevious(this);
                            }
                        ],
                        // Arrow next handler
                        [
                            [keys.right, keys.down],
                            function () {
                                return component.onKbdNext(this);
                            }
                        ],
                        // Click handler
                        [
                            [keys.enter, keys.space],
                            function () {
                                return component.onKbdClick(this);
                            }
                        ],
                        // ESC handler
                        [
                            [keys.esc],
                            function () {
                                return this.response.prev;
                            }
                        ]
                    ],
                    // Only run exporting navigation if exporting support exists and is
                    // enabled on chart
                    validate: function () {
                        return chart.exportChart &&
                            chart.options.exporting.enabled !== false &&
                            chart.options.exporting.accessibility.enabled !==
                                false;
                    },
                    // Show export menu
                    init: function (direction) {
                        chart.showExportMenu();
                        if (direction < 0) {
                            chart.highlightLastExportItem();
                        }
                        else {
                            chart.highlightExportItem(0);
                        }
                    },
                    // Hide the menu
                    terminate: function () {
                        chart.hideExportMenu();
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @return {number}
             * Response code
             */
            onKbdPrevious: function (keyboardNavigationHandler) {
                var chart = this.chart, a11yOptions = chart.options.accessibility, response = keyboardNavigationHandler.response, i = chart.highlightedExportItemIx || 0;
                // Try to highlight prev item in list. Highlighting e.g.
                // separators will fail.
                while (i--) {
                    if (chart.highlightExportItem(i)) {
                        return response.success;
                    }
                }
                // We failed, so wrap around or move to prev module
                if (a11yOptions.keyboardNavigation.wrapAround) {
                    chart.highlightLastExportItem();
                    return response.success;
                }
                return response.prev;
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @return {number}
             * Response code
             */
            onKbdNext: function (keyboardNavigationHandler) {
                var chart = this.chart, a11yOptions = chart.options.accessibility, response = keyboardNavigationHandler.response, i = (chart.highlightedExportItemIx || 0) + 1;
                // Try to highlight next item in list. Highlighting e.g.
                // separators will fail.
                for (; i < chart.exportDivElements.length; ++i) {
                    if (chart.highlightExportItem(i)) {
                        return response.success;
                    }
                }
                // We failed, so wrap around or move to next module
                if (a11yOptions.keyboardNavigation.wrapAround) {
                    chart.highlightExportItem(0);
                    return response.success;
                }
                return response.next;
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @return {number}
             * Response code
             */
            onKbdClick: function (keyboardNavigationHandler) {
                var chart = this.chart;
                this.fakeClickEvent(chart.exportDivElements[chart.highlightedExportItemIx]);
                return keyboardNavigationHandler.response.success;
            }
        });

        return MenuComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesKeyboardNavigation.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/EventProvider.js'], _modules['modules/accessibility/utils/chartUtilities.js']], function (H, U, KeyboardNavigationHandler, EventProvider, ChartUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Handle keyboard navigation for series.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend, defined = U.defined;
        var getPointFromXY = ChartUtilities.getPointFromXY, getSeriesFromName = ChartUtilities.getSeriesFromName;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /*
         * Set for which series types it makes sense to move to the closest point with
         * up/down arrows, and which series types should just move to next series.
         */
        H.Series.prototype.keyboardMoveVertical = true;
        ['column', 'pie'].forEach(function (type) {
            if (H.seriesTypes[type]) {
                H.seriesTypes[type].prototype.keyboardMoveVertical = false;
            }
        });
        /**
         * Get the index of a point in a series. This is needed when using e.g. data
         * grouping.
         *
         * @private
         * @function getPointIndex
         *
         * @param {Highcharts.AccessibilityPoint} point
         *        The point to find index of.
         *
         * @return {number|undefined}
         *         The index in the series.points array of the point.
         */
        function getPointIndex(point) {
            var index = point.index, points = point.series.points, i = points.length;
            if (points[index] !== point) {
                while (i--) {
                    if (points[i] === point) {
                        return i;
                    }
                }
            }
            else {
                return index;
            }
        }
        /**
         * Determine if series navigation should be skipped
         *
         * @private
         * @function isSkipSeries
         *
         * @param {Highcharts.Series} series
         *
         * @return {boolean|number|undefined}
         */
        function isSkipSeries(series) {
            var a11yOptions = series.chart.options.accessibility, seriesNavOptions = a11yOptions.keyboardNavigation.seriesNavigation, seriesA11yOptions = series.options.accessibility || {}, seriesKbdNavOptions = seriesA11yOptions.keyboardNavigation;
            return seriesKbdNavOptions && seriesKbdNavOptions.enabled === false ||
                seriesA11yOptions.enabled === false ||
                series.options.enableMouseTracking === false || // #8440
                !series.visible ||
                // Skip all points in a series where pointNavigationEnabledThreshold is
                // reached
                (seriesNavOptions.pointNavigationEnabledThreshold &&
                    seriesNavOptions.pointNavigationEnabledThreshold <=
                        series.points.length);
        }
        /**
         * Determine if navigation for a point should be skipped
         *
         * @private
         * @function isSkipPoint
         *
         * @param {Highcharts.Point} point
         *
         * @return {boolean|number|undefined}
         */
        function isSkipPoint(point) {
            var a11yOptions = point.series.chart.options.accessibility;
            return point.isNull &&
                a11yOptions.keyboardNavigation.seriesNavigation.skipNullPoints ||
                point.visible === false ||
                isSkipSeries(point.series);
        }
        /**
         * Get the point in a series that is closest (in pixel distance) to a reference
         * point. Optionally supply weight factors for x and y directions.
         *
         * @private
         * @function getClosestPoint
         *
         * @param {Highcharts.Point} point
         * @param {Highcharts.Series} series
         * @param {number} [xWeight]
         * @param {number} [yWeight]
         *
         * @return {Highcharts.Point|undefined}
         */
        function getClosestPoint(point, series, xWeight, yWeight) {
            var minDistance = Infinity, dPoint, minIx, distance, i = series.points.length, hasUndefinedPosition = function (point) {
                return !(defined(point.plotX) && defined(point.plotY));
            };
            if (hasUndefinedPosition(point)) {
                return;
            }
            while (i--) {
                dPoint = series.points[i];
                if (hasUndefinedPosition(dPoint)) {
                    continue;
                }
                distance = (point.plotX - dPoint.plotX) *
                    (point.plotX - dPoint.plotX) *
                    (xWeight || 1) +
                    (point.plotY - dPoint.plotY) *
                        (point.plotY - dPoint.plotY) *
                        (yWeight || 1);
                if (distance < minDistance) {
                    minDistance = distance;
                    minIx = i;
                }
            }
            return defined(minIx) ? series.points[minIx] : void 0;
        }
        /**
         * Highlights a point (show tooltip and display hover state).
         *
         * @private
         * @function Highcharts.Point#highlight
         *
         * @return {Highcharts.Point}
         *         This highlighted point.
         */
        H.Point.prototype.highlight = function () {
            var chart = this.series.chart;
            if (!this.isNull) {
                this.onMouseOver(); // Show the hover marker and tooltip
            }
            else {
                if (chart.tooltip) {
                    chart.tooltip.hide(0);
                }
                // Don't call blur on the element, as it messes up the chart div's focus
            }
            // We focus only after calling onMouseOver because the state change can
            // change z-index and mess up the element.
            if (this.graphic) {
                chart.setFocusToElement(this.graphic);
            }
            chart.highlightedPoint = this;
            return this;
        };
        /**
         * Function to highlight next/previous point in chart.
         *
         * @private
         * @function Highcharts.Chart#highlightAdjacentPoint
         *
         * @param {boolean} next
         *        Flag for the direction.
         *
         * @return {Highcharts.Point|boolean}
         *         Returns highlighted point on success, false on failure (no adjacent
         *         point to highlight in chosen direction).
         */
        H.Chart.prototype.highlightAdjacentPoint = function (next) {
            var chart = this, series = chart.series, curPoint = chart.highlightedPoint, curPointIndex = curPoint && getPointIndex(curPoint) || 0, curPoints = (curPoint && curPoint.series.points), lastSeries = chart.series && chart.series[chart.series.length - 1], lastPoint = lastSeries && lastSeries.points &&
                lastSeries.points[lastSeries.points.length - 1], newSeries, newPoint;
            // If no points, return false
            if (!series[0] || !series[0].points) {
                return false;
            }
            if (!curPoint) {
                // No point is highlighted yet. Try first/last point depending on move
                // direction
                newPoint = next ? series[0].points[0] : lastPoint;
            }
            else {
                // We have a highlighted point.
                // Grab next/prev point & series
                newSeries = series[curPoint.series.index + (next ? 1 : -1)];
                newPoint = curPoints[curPointIndex + (next ? 1 : -1)];
                if (!newPoint && newSeries) {
                    // Done with this series, try next one
                    newPoint = newSeries.points[next ? 0 : newSeries.points.length - 1];
                }
                // If there is no adjacent point, we return false
                if (!newPoint) {
                    return false;
                }
            }
            // Recursively skip points
            if (isSkipPoint(newPoint)) {
                // If we skip this whole series, move to the end of the series before we
                // recurse, just to optimize
                newSeries = newPoint.series;
                if (isSkipSeries(newSeries)) {
                    chart.highlightedPoint = next ?
                        newSeries.points[newSeries.points.length - 1] :
                        newSeries.points[0];
                }
                else {
                    // Otherwise, just move one point
                    chart.highlightedPoint = newPoint;
                }
                // Retry
                return chart.highlightAdjacentPoint(next);
            }
            // There is an adjacent point, highlight it
            return newPoint.highlight();
        };
        /**
         * Highlight first valid point in a series. Returns the point if successfully
         * highlighted, otherwise false. If there is a highlighted point in the series,
         * use that as starting point.
         *
         * @private
         * @function Highcharts.Series#highlightFirstValidPoint
         *
         * @return {boolean|Highcharts.Point}
         */
        H.Series.prototype.highlightFirstValidPoint = function () {
            var curPoint = this.chart.highlightedPoint, start = (curPoint && curPoint.series) === this ?
                getPointIndex(curPoint) :
                0, points = this.points, len = points.length;
            if (points && len) {
                for (var i = start; i < len; ++i) {
                    if (!isSkipPoint(points[i])) {
                        return points[i].highlight();
                    }
                }
                for (var j = start; j >= 0; --j) {
                    if (!isSkipPoint(points[j])) {
                        return points[j].highlight();
                    }
                }
            }
            return false;
        };
        /**
         * Highlight next/previous series in chart. Returns false if no adjacent series
         * in the direction, otherwise returns new highlighted point.
         *
         * @private
         * @function Highcharts.Chart#highlightAdjacentSeries
         *
         * @param {boolean} down
         *
         * @return {Highcharts.Point|boolean}
         */
        H.Chart.prototype.highlightAdjacentSeries = function (down) {
            var chart = this, newSeries, newPoint, adjacentNewPoint, curPoint = chart.highlightedPoint, lastSeries = chart.series && chart.series[chart.series.length - 1], lastPoint = lastSeries && lastSeries.points &&
                lastSeries.points[lastSeries.points.length - 1];
            // If no point is highlighted, highlight the first/last point
            if (!chart.highlightedPoint) {
                newSeries = down ? (chart.series && chart.series[0]) : lastSeries;
                newPoint = down ?
                    (newSeries && newSeries.points && newSeries.points[0]) : lastPoint;
                return newPoint ? newPoint.highlight() : false;
            }
            newSeries = chart.series[curPoint.series.index + (down ? -1 : 1)];
            if (!newSeries) {
                return false;
            }
            // We have a new series in this direction, find the right point
            // Weigh xDistance as counting much higher than Y distance
            newPoint = getClosestPoint(curPoint, newSeries, 4);
            if (!newPoint) {
                return false;
            }
            // New series and point exists, but we might want to skip it
            if (isSkipSeries(newSeries)) {
                // Skip the series
                newPoint.highlight();
                adjacentNewPoint = chart.highlightAdjacentSeries(down); // Try recurse
                if (!adjacentNewPoint) {
                    // Recurse failed
                    curPoint.highlight();
                    return false;
                }
                // Recurse succeeded
                return adjacentNewPoint;
            }
            // Highlight the new point or any first valid point back or forwards from it
            newPoint.highlight();
            return newPoint.series.highlightFirstValidPoint();
        };
        /**
         * Highlight the closest point vertically.
         *
         * @private
         * @function Highcharts.Chart#highlightAdjacentPointVertical
         *
         * @param {boolean} down
         *
         * @return {Highcharts.Point|boolean}
         */
        H.Chart.prototype.highlightAdjacentPointVertical = function (down) {
            var curPoint = this.highlightedPoint, minDistance = Infinity, bestPoint;
            if (!defined(curPoint.plotX) || !defined(curPoint.plotY)) {
                return false;
            }
            this.series.forEach(function (series) {
                if (isSkipSeries(series)) {
                    return;
                }
                series.points.forEach(function (point) {
                    if (!defined(point.plotY) || !defined(point.plotX) ||
                        point === curPoint) {
                        return;
                    }
                    var yDistance = point.plotY - curPoint.plotY, width = Math.abs(point.plotX - curPoint.plotX), distance = Math.abs(yDistance) * Math.abs(yDistance) +
                        width * width * 4; // Weigh horizontal distance highly
                    // Reverse distance number if axis is reversed
                    if (series.yAxis.reversed) {
                        yDistance *= -1;
                    }
                    if (yDistance <= 0 && down || yDistance >= 0 && !down || // Chk dir
                        distance < 5 || // Points in same spot => infinite loop
                        isSkipPoint(point)) {
                        return;
                    }
                    if (distance < minDistance) {
                        minDistance = distance;
                        bestPoint = point;
                    }
                });
            });
            return bestPoint ? bestPoint.highlight() : false;
        };
        /**
         * @private
         * @param {Highcharts.Chart} chart
         * @return {Highcharts.Point|boolean}
         */
        function highlightFirstValidPointInChart(chart) {
            var res = false;
            delete chart.highlightedPoint;
            res = chart.series.reduce(function (acc, cur) {
                return acc || cur.highlightFirstValidPoint();
            }, false);
            return res;
        }
        /**
         * @private
         * @param {Highcharts.Chart} chart
         * @return {Highcharts.Point|boolean}
         */
        function highlightLastValidPointInChart(chart) {
            var numSeries = chart.series.length, i = numSeries, res = false;
            while (i--) {
                chart.highlightedPoint = chart.series[i].points[chart.series[i].points.length - 1];
                // Highlight first valid point in the series will also
                // look backwards. It always starts from currently
                // highlighted point.
                res = chart.series[i].highlightFirstValidPoint();
                if (res) {
                    break;
                }
            }
            return res;
        }
        /**
         * @private
         * @param {Highcharts.Chart} chart
         */
        function updateChartFocusAfterDrilling(chart) {
            highlightFirstValidPointInChart(chart);
            if (chart.focusElement) {
                chart.focusElement.removeFocusBorder();
            }
        }
        /**
         * @private
         * @class
         * @name Highcharts.SeriesKeyboardNavigation
         */
        function SeriesKeyboardNavigation(chart, keyCodes) {
            this.keyCodes = keyCodes;
            this.chart = chart;
        }
        extend(SeriesKeyboardNavigation.prototype, /** @lends Highcharts.SeriesKeyboardNavigation */ {
            /**
             * Init the keyboard navigation
             */
            init: function () {
                var keyboardNavigation = this, chart = this.chart, e = this.eventProvider = new EventProvider();
                e.addEvent(H.Series, 'destroy', function () {
                    return keyboardNavigation.onSeriesDestroy(this);
                });
                e.addEvent(chart, 'afterDrilldown', function () {
                    updateChartFocusAfterDrilling(this);
                });
                e.addEvent(chart, 'drilldown', function (e) {
                    var point = e.point, series = point.series;
                    keyboardNavigation.lastDrilledDownPoint = {
                        x: point.x,
                        y: point.y,
                        seriesName: series ? series.name : ''
                    };
                });
                e.addEvent(chart, 'drillupall', function () {
                    setTimeout(function () {
                        keyboardNavigation.onDrillupAll();
                    }, 10);
                });
            },
            onDrillupAll: function () {
                // After drillup we want to find the point that was drilled down to and
                // highlight it.
                var last = this.lastDrilledDownPoint, chart = this.chart, series = last && getSeriesFromName(chart, last.seriesName), point;
                if (last && series && defined(last.x) && defined(last.y)) {
                    point = getPointFromXY(series, last.x, last.y);
                }
                // Container focus can be lost on drillup due to deleted elements.
                if (chart.container) {
                    chart.container.focus();
                }
                if (point && point.highlight) {
                    point.highlight();
                }
                if (chart.focusElement) {
                    chart.focusElement.removeFocusBorder();
                }
            },
            /**
             * @return {Highcharts.KeyboardNavigationHandler}
             */
            getKeyboardNavigationHandler: function () {
                var keyboardNavigation = this, keys = this.keyCodes, chart = this.chart, inverted = chart.inverted;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [inverted ? [keys.up, keys.down] : [keys.left, keys.right],
                            function (keyCode) {
                                return keyboardNavigation.onKbdSideways(this, keyCode);
                            }],
                        [inverted ? [keys.left, keys.right] : [keys.up, keys.down],
                            function (keyCode) {
                                return keyboardNavigation.onKbdVertical(this, keyCode);
                            }],
                        [[keys.enter, keys.space],
                            function () {
                                if (chart.highlightedPoint) {
                                    chart.highlightedPoint.firePointEvent('click');
                                }
                                return this.response.success;
                            }]
                    ],
                    init: function (dir) {
                        return keyboardNavigation.onHandlerInit(this, dir);
                    },
                    terminate: function () {
                        return keyboardNavigation.onHandlerTerminate();
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} handler
             * @param {number} keyCode
             * @return {number}
             * response
             */
            onKbdSideways: function (handler, keyCode) {
                var keys = this.keyCodes, isNext = keyCode === keys.right || keyCode === keys.down;
                return this.attemptHighlightAdjacentPoint(handler, isNext);
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} handler
             * @param {number} keyCode
             * @return {number}
             * response
             */
            onKbdVertical: function (handler, keyCode) {
                var chart = this.chart, keys = this.keyCodes, isNext = keyCode === keys.down || keyCode === keys.right, navOptions = chart.options.accessibility.keyboardNavigation
                    .seriesNavigation;
                // Handle serialized mode, act like left/right
                if (navOptions.mode && navOptions.mode === 'serialize') {
                    return this.attemptHighlightAdjacentPoint(handler, isNext);
                }
                // Normal mode, move between series
                var highlightMethod = (chart.highlightedPoint &&
                    chart.highlightedPoint.series.keyboardMoveVertical) ?
                    'highlightAdjacentPointVertical' :
                    'highlightAdjacentSeries';
                chart[highlightMethod](isNext);
                return handler.response.success;
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} handler
             * @param {number} initDirection
             * @return {number}
             * response
             */
            onHandlerInit: function (handler, initDirection) {
                var chart = this.chart;
                if (initDirection > 0) {
                    highlightFirstValidPointInChart(chart);
                }
                else {
                    highlightLastValidPointInChart(chart);
                }
                return handler.response.success;
            },
            /**
             * @private
             */
            onHandlerTerminate: function () {
                var chart = this.chart;
                if (chart.tooltip) {
                    chart.tooltip.hide(0);
                }
                delete chart.highlightedPoint;
            },
            /**
             * Function that attempts to highlight next/prev point. Handles wrap around.
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} handler
             * @param {boolean} directionIsNext
             * @return {number}
             * response
             */
            attemptHighlightAdjacentPoint: function (handler, directionIsNext) {
                var chart = this.chart, wrapAround = chart.options.accessibility.keyboardNavigation
                    .wrapAround, highlightSuccessful = chart.highlightAdjacentPoint(directionIsNext);
                if (!highlightSuccessful) {
                    if (wrapAround) {
                        return handler.init(directionIsNext ? 1 : -1);
                    }
                    return handler.response[directionIsNext ? 'next' : 'prev'];
                }
                return handler.response.success;
            },
            /**
             * @private
             */
            onSeriesDestroy: function (series) {
                var chart = this.chart, currentHighlightedPointDestroyed = chart.highlightedPoint &&
                    chart.highlightedPoint.series === series;
                if (currentHighlightedPointDestroyed) {
                    delete chart.highlightedPoint;
                    if (chart.focusElement) {
                        chart.focusElement.removeFocusBorder();
                    }
                }
            },
            /**
             * @private
             */
            destroy: function () {
                this.eventProvider.removeAddedEvents();
            }
        });

        return SeriesKeyboardNavigation;
    });
    _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesDescriber.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js']], function (H, U, HTMLUtilities, ChartUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Place desriptions on a series and its points.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var numberFormat = H.numberFormat, find = H.find;
        var isNumber = U.isNumber, pick = U.pick, defined = U.defined;
        var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString, reverseChildNodes = HTMLUtilities.reverseChildNodes;
        var getAxisDescription = ChartUtilities.getAxisDescription, getSeriesFirstPointElement = ChartUtilities.getSeriesFirstPointElement, getSeriesA11yElement = ChartUtilities.getSeriesA11yElement, unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT;
        /* eslint-disable valid-jsdoc */
        /**
         * @private
         */
        function findFirstPointWithGraphic(point) {
            var sourcePointIndex = point.index;
            if (!point.series || !point.series.data || !defined(sourcePointIndex)) {
                return null;
            }
            return find(point.series.data, function (p) {
                return !!(p &&
                    typeof p.index !== 'undefined' &&
                    p.index > sourcePointIndex &&
                    p.graphic &&
                    p.graphic.element);
            }) || null;
        }
        /**
         * @private
         */
        function makeDummyElement(point, pos) {
            var renderer = point.series.chart.renderer, dummy = renderer.rect(pos.x, pos.y, 1, 1);
            dummy.attr({
                'class': 'highcharts-a11y-dummy-point',
                fill: 'none',
                'fill-opacity': 0,
                'stroke-opacity': 0,
                opacity: 0
            });
            return dummy;
        }
        /**
         * @private
         * @param {Highcharts.Point} point
         * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined}
         */
        function addDummyPointElement(point) {
            var series = point.series, firstPointWithGraphic = findFirstPointWithGraphic(point), firstGraphic = firstPointWithGraphic && firstPointWithGraphic.graphic, parentGroup = firstGraphic ?
                firstGraphic.parentGroup :
                series.graph || series.group, dummyPos = firstPointWithGraphic ? {
                x: pick(point.plotX, firstPointWithGraphic.plotX, 0),
                y: pick(point.plotY, firstPointWithGraphic.plotY, 0)
            } : {
                x: pick(point.plotX, 0),
                y: pick(point.plotY, 0)
            }, dummyElement = makeDummyElement(point, dummyPos);
            if (parentGroup && parentGroup.element) {
                point.graphic = dummyElement;
                dummyElement.add(parentGroup);
                // Move to correct pos in DOM
                parentGroup.element.insertBefore(dummyElement.element, firstGraphic ? firstGraphic.element : null);
                return dummyElement.element;
            }
        }
        /**
         * @private
         * @param {Highcharts.Series} series
         * @return {boolean}
         */
        function hasMorePointsThanDescriptionThreshold(series) {
            var chartA11yOptions = series.chart.options.accessibility, threshold = (chartA11yOptions.series.pointDescriptionEnabledThreshold);
            return !!(threshold !== false &&
                series.points &&
                series.points.length >= threshold);
        }
        /**
         * @private
         * @param {Highcharts.Series} series
         * @return {boolean}
         */
        function shouldSetScreenReaderPropsOnPoints(series) {
            var seriesA11yOptions = series.options.accessibility || {};
            return !hasMorePointsThanDescriptionThreshold(series) &&
                !seriesA11yOptions.exposeAsGroupOnly;
        }
        /**
         * @private
         * @param {Highcharts.Series} series
         * @return {boolean}
         */
        function shouldSetKeyboardNavPropsOnPoints(series) {
            var chartA11yOptions = series.chart.options.accessibility, seriesNavOptions = chartA11yOptions.keyboardNavigation.seriesNavigation;
            return !!(series.points && (series.points.length <
                seriesNavOptions.pointNavigationEnabledThreshold ||
                seriesNavOptions.pointNavigationEnabledThreshold === false));
        }
        /**
         * @private
         * @param {Highcharts.Series} series
         * @return {boolean}
         */
        function shouldDescribeSeriesElement(series) {
            var chart = series.chart, chartOptions = chart.options.chart || {}, chartHas3d = chartOptions.options3d && chartOptions.options3d.enabled, hasMultipleSeries = chart.series.length > 1, describeSingleSeriesOption = chart.options.accessibility.series.describeSingleSeries, exposeAsGroupOnlyOption = (series.options.accessibility || {}).exposeAsGroupOnly, noDescribe3D = chartHas3d && hasMultipleSeries;
            return !noDescribe3D && (hasMultipleSeries || describeSingleSeriesOption ||
                exposeAsGroupOnlyOption || hasMorePointsThanDescriptionThreshold(series));
        }
        /**
         * @private
         * @param {Highcharts.Point} point
         * @param {number} value
         * @return {string}
         */
        function pointNumberToString(point, value) {
            var chart = point.series.chart, a11yPointOptions = chart.options.accessibility.point || {}, tooltipOptions = point.series.tooltipOptions || {}, lang = chart.options.lang;
            if (isNumber(value)) {
                return numberFormat(value, a11yPointOptions.valueDecimals ||
                    tooltipOptions.valueDecimals ||
                    -1, lang.decimalPoint, lang.accessibility.thousandsSep || lang.thousandsSep);
            }
            return value;
        }
        /**
         * @private
         * @param {Highcharts.Series} series
         * @return {string}
         */
        function getSeriesDescriptionText(series) {
            var seriesA11yOptions = series.options.accessibility || {}, descOpt = seriesA11yOptions.description;
            return descOpt && series.chart.langFormat('accessibility.series.description', {
                description: descOpt,
                series: series
            }) || '';
        }
        /**
         * @private
         * @param {Highcharts.series} series
         * @param {string} axisCollection
         * @return {string}
         */
        function getSeriesAxisDescriptionText(series, axisCollection) {
            var axis = series[axisCollection];
            return series.chart.langFormat('accessibility.series.' + axisCollection + 'Description', {
                name: getAxisDescription(axis),
                series: series
            });
        }
        /**
         * Get accessible time description for a point on a datetime axis.
         *
         * @private
         * @function Highcharts.Point#getTimeDescription
         * @param {Highcharts.Point} point
         * @return {string|undefined}
         * The description as string.
         */
        function getPointA11yTimeDescription(point) {
            var series = point.series, chart = series.chart, a11yOptions = chart.options.accessibility.point || {}, hasDateXAxis = series.xAxis && series.xAxis.isDatetimeAxis;
            if (hasDateXAxis) {
                var tooltipDateFormat = H.Tooltip.prototype.getXDateFormat.call({
                    getDateFormat: H.Tooltip.prototype.getDateFormat,
                    chart: chart
                }, point, chart.options.tooltip, series.xAxis), dateFormat = a11yOptions.dateFormatter &&
                    a11yOptions.dateFormatter(point) ||
                    a11yOptions.dateFormat ||
                    tooltipDateFormat;
                return chart.time.dateFormat(dateFormat, point.x, void 0);
            }
        }
        /**
         * @private
         * @param {Highcharts.Point} point
         * @return {string}
         */
        function getPointXDescription(point) {
            var timeDesc = getPointA11yTimeDescription(point), xAxis = point.series.xAxis || {}, pointCategory = xAxis.categories && defined(point.category) &&
                ('' + point.category).replace('<br/>', ' '), canUseId = point.id && point.id.indexOf('highcharts-') < 0, fallback = 'x, ' + point.x;
            return point.name || timeDesc || pointCategory ||
                (canUseId ? point.id : fallback);
        }
        /**
         * @private
         * @param {Highcharts.Point} point
         * @param {string} prefix
         * @param {string} suffix
         * @return {string}
         */
        function getPointArrayMapValueDescription(point, prefix, suffix) {
            var pre = prefix || '', suf = suffix || '', keyToValStr = function (key) {
                var num = pointNumberToString(point, pick(point[key], point.options[key]));
                return key + ': ' + pre + num + suf;
            }, pointArrayMap = point.series.pointArrayMap;
            return pointArrayMap.reduce(function (desc, key) {
                return desc + (desc.length ? ', ' : '') + keyToValStr(key);
            }, '');
        }
        /**
         * @private
         * @param {Highcharts.Point} point
         * @return {string}
         */
        function getPointValueDescription(point) {
            var series = point.series, a11yPointOpts = series.chart.options.accessibility.point || {}, tooltipOptions = series.tooltipOptions || {}, valuePrefix = a11yPointOpts.valuePrefix ||
                tooltipOptions.valuePrefix || '', valueSuffix = a11yPointOpts.valueSuffix ||
                tooltipOptions.valueSuffix || '', fallbackKey = (typeof point.value !==
                'undefined' ?
                'value' : 'y'), fallbackDesc = pointNumberToString(point, point[fallbackKey]);
            if (point.isNull) {
                return series.chart.langFormat('accessibility.series.nullPointValue', {
                    point: point
                });
            }
            if (series.pointArrayMap) {
                return getPointArrayMapValueDescription(point, valuePrefix, valueSuffix);
            }
            return valuePrefix + fallbackDesc + valueSuffix;
        }
        /**
         * Return string with information about point.
         * @private
         * @return {string}
         */
        function defaultPointDescriptionFormatter(point) {
            var series = point.series, chart = series.chart, description = point.options && point.options.accessibility &&
                point.options.accessibility.description, showXDescription = pick(series.xAxis &&
                series.xAxis.options.accessibility &&
                series.xAxis.options.accessibility.enabled, !chart.angular), xDesc = getPointXDescription(point), valueDesc = getPointValueDescription(point), indexText = defined(point.index) ? (point.index + 1) + '. ' : '', xDescText = showXDescription ? xDesc + ', ' : '', valText = valueDesc + '.', userDescText = description ? ' ' + description : '', seriesNameText = chart.series.length > 1 && series.name ?
                ' ' + series.name + '.' : '';
            return indexText + xDescText + valText + userDescText + seriesNameText;
        }
        /**
         * Set a11y props on a point element
         * @private
         * @param {Highcharts.Point} point
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} pointElement
         */
        function setPointScreenReaderAttribs(point, pointElement) {
            var series = point.series, a11yPointOptions = series.chart.options.accessibility.point || {}, seriesA11yOptions = series.options.accessibility || {}, label = stripHTMLTags(seriesA11yOptions.pointDescriptionFormatter &&
                seriesA11yOptions.pointDescriptionFormatter(point) ||
                a11yPointOptions.descriptionFormatter &&
                    a11yPointOptions.descriptionFormatter(point) ||
                defaultPointDescriptionFormatter(point));
            pointElement.setAttribute('role', 'img');
            pointElement.setAttribute('aria-label', label);
        }
        /**
         * Add accessible info to individual point elements of a series
         * @private
         * @param {Highcharts.Series} series
         */
        function describePointsInSeries(series) {
            var setScreenReaderProps = shouldSetScreenReaderPropsOnPoints(series), setKeyboardProps = shouldSetKeyboardNavPropsOnPoints(series);
            if (setScreenReaderProps || setKeyboardProps) {
                series.points.forEach(function (point) {
                    var shouldAddDummyPoint = point.isNull, pointEl = point.graphic && point.graphic.element ||
                        shouldAddDummyPoint && addDummyPointElement(point);
                    if (pointEl) {
                        // We always set tabindex, as long as we are setting
                        // props.
                        pointEl.setAttribute('tabindex', '-1');
                        if (setScreenReaderProps) {
                            setPointScreenReaderAttribs(point, pointEl);
                        }
                        else {
                            pointEl.setAttribute('aria-hidden', true);
                        }
                    }
                });
            }
        }
        /**
         * Return string with information about series.
         * @private
         * @return {string}
         */
        function defaultSeriesDescriptionFormatter(series) {
            var chart = series.chart, chartTypes = chart.types || [], description = getSeriesDescriptionText(series), shouldDescribeAxis = function (coll) {
                return chart[coll] && chart[coll].length > 1 && series[coll];
            }, xAxisInfo = getSeriesAxisDescriptionText(series, 'xAxis'), yAxisInfo = getSeriesAxisDescriptionText(series, 'yAxis'), summaryContext = {
                name: series.name || '',
                ix: series.index + 1,
                numSeries: chart.series && chart.series.length,
                numPoints: series.points && series.points.length,
                series: series
            }, combinationSuffix = chartTypes.length > 1 ? 'Combination' : '', summary = chart.langFormat('accessibility.series.summary.' + series.type + combinationSuffix, summaryContext) || chart.langFormat('accessibility.series.summary.default' + combinationSuffix, summaryContext);
            return summary + (description ? ' ' + description : '') + (shouldDescribeAxis('yAxis') ? ' ' + yAxisInfo : '') + (shouldDescribeAxis('xAxis') ? ' ' + xAxisInfo : '');
        }
        /**
         * Set a11y props on a series element
         * @private
         * @param {Highcharts.Series} series
         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} seriesElement
         */
        function describeSeriesElement(series, seriesElement) {
            var seriesA11yOptions = series.options.accessibility || {}, a11yOptions = series.chart.options.accessibility, landmarkVerbosity = a11yOptions.landmarkVerbosity;
            // Handle role attribute
            if (seriesA11yOptions.exposeAsGroupOnly) {
                seriesElement.setAttribute('role', 'img');
            }
            else if (landmarkVerbosity === 'all') {
                seriesElement.setAttribute('role', 'region');
            } /* else do not add role */
            seriesElement.setAttribute('tabindex', '-1');
            seriesElement.setAttribute('aria-label', stripHTMLTags(a11yOptions.series.descriptionFormatter &&
                a11yOptions.series.descriptionFormatter(series) ||
                defaultSeriesDescriptionFormatter(series)));
        }
        /**
         * Put accessible info on series and points of a series.
         * @param {Highcharts.Series} series The series to add info on.
         */
        function describeSeries(series) {
            var chart = series.chart, firstPointEl = getSeriesFirstPointElement(series), seriesEl = getSeriesA11yElement(series);
            if (seriesEl) {
                // For some series types the order of elements do not match the
                // order of points in series. In that case we have to reverse them
                // in order for AT to read them out in an understandable order
                if (seriesEl.lastChild === firstPointEl) {
                    reverseChildNodes(seriesEl);
                }
                describePointsInSeries(series);
                unhideChartElementFromAT(chart, seriesEl);
                if (shouldDescribeSeriesElement(series)) {
                    describeSeriesElement(series, seriesEl);
                }
                else {
                    seriesEl.setAttribute('aria-label', '');
                }
            }
        }
        var SeriesDescriber = {
            describeSeries: describeSeries,
            defaultPointDescriptionFormatter: defaultPointDescriptionFormatter,
            defaultSeriesDescriptionFormatter: defaultSeriesDescriptionFormatter,
            getPointA11yTimeDescription: getPointA11yTimeDescription,
            getPointXDescription: getPointXDescription,
            getPointValueDescription: getPointValueDescription
        };

        return SeriesDescriber;
    });
    _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/NewDataAnnouncer.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesDescriber.js'], _modules['modules/accessibility/utils/EventProvider.js'], _modules['modules/accessibility/utils/DOMElementProvider.js']], function (H, U, HTMLUtilities, ChartUtilities, SeriesDescriber, EventProvider, DOMElementProvider) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Handle announcing new data for a chart.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend, defined = U.defined;
        var visuallyHideElement = HTMLUtilities.visuallyHideElement;
        var getChartTitle = ChartUtilities.getChartTitle;
        var defaultPointDescriptionFormatter = SeriesDescriber
            .defaultPointDescriptionFormatter, defaultSeriesDescriptionFormatter = SeriesDescriber
            .defaultSeriesDescriptionFormatter;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function chartHasAnnounceEnabled(chart) {
            return !!chart.options.accessibility.announceNewData.enabled;
        }
        /**
         * @private
         */
        function findPointInDataArray(point) {
            var candidates = point.series.data.filter(function (candidate) {
                return point.x === candidate.x && point.y === candidate.y;
            });
            return candidates.length === 1 ? candidates[0] : point;
        }
        /**
         * Get array of unique series from two arrays
         * @private
         */
        function getUniqueSeries(arrayA, arrayB) {
            var uniqueSeries = (arrayA || []).concat(arrayB || [])
                .reduce(function (acc, cur) {
                acc[cur.name + cur.index] = cur;
                return acc;
            }, {});
            return Object.keys(uniqueSeries).map(function (ix) {
                return uniqueSeries[ix];
            });
        }
        /**
         * @private
         * @class
         */
        var NewDataAnnouncer = function (chart) {
            this.chart = chart;
        };
        extend(NewDataAnnouncer.prototype, {
            /**
             * Initialize the new data announcer.
             */
            init: function () {
                this.lastAnnouncementTime = 0;
                this.dirty = {
                    allSeries: {}
                };
                this.eventProvider = new EventProvider();
                this.domElementProvider = new DOMElementProvider();
                this.announceRegion = this.addAnnounceRegion();
                this.addEventListeners();
            },
            /**
             * Remove traces of announcer.
             */
            destroy: function () {
                this.eventProvider.removeAddedEvents();
                this.domElementProvider.destroyCreatedElements();
            },
            /**
             * Add the announcement live region to the DOM.
             * @private
             */
            addAnnounceRegion: function () {
                var chart = this.chart, div = this.domElementProvider.createElement('div'), announceOptions = (chart.options.accessibility.announceNewData);
                div.setAttribute('aria-hidden', false);
                div.setAttribute('aria-live', announceOptions.interruptUser ? 'assertive' : 'polite');
                visuallyHideElement(div);
                chart.renderTo.insertBefore(div, chart.renderTo.firstChild);
                return div;
            },
            /**
             * Add event listeners for the announcer
             * @private
             */
            addEventListeners: function () {
                var announcer = this, chart = this.chart, e = this.eventProvider;
                e.addEvent(chart, 'afterDrilldown', function () {
                    announcer.lastAnnouncementTime = 0;
                });
                e.addEvent(H.Series, 'updatedData', function () {
                    announcer.onSeriesUpdatedData(this);
                });
                e.addEvent(chart, 'afterAddSeries', function (e) {
                    announcer.onSeriesAdded(e.series);
                });
                e.addEvent(H.Series, 'addPoint', function (e) {
                    announcer.onPointAdded(e.point);
                });
                e.addEvent(chart, 'redraw', function () {
                    announcer.announceDirtyData();
                });
            },
            /**
             * On new data in the series, make sure we add it to the dirty list.
             * @private
             * @param {Highcharts.Series} series
             */
            onSeriesUpdatedData: function (series) {
                var chart = this.chart;
                if (series.chart === chart && chartHasAnnounceEnabled(chart)) {
                    this.dirty.hasDirty = true;
                    this.dirty.allSeries[series.name + series.index] = series;
                }
            },
            /**
             * On new data series added, update dirty list.
             * @private
             * @param {Highcharts.Series} series
             */
            onSeriesAdded: function (series) {
                if (chartHasAnnounceEnabled(this.chart)) {
                    this.dirty.hasDirty = true;
                    this.dirty.allSeries[series.name + series.index] = series;
                    // Add it to newSeries storage unless we already have one
                    this.dirty.newSeries = defined(this.dirty.newSeries) ?
                        void 0 : series;
                }
            },
            /**
             * On new point added, update dirty list.
             * @private
             * @param {Highcharts.Point} point
             */
            onPointAdded: function (point) {
                var chart = point.series.chart;
                if (this.chart === chart && chartHasAnnounceEnabled(chart)) {
                    // Add it to newPoint storage unless we already have one
                    this.dirty.newPoint = defined(this.dirty.newPoint) ?
                        void 0 : point;
                }
            },
            /**
             * Gather what we know and announce the data to user.
             * @private
             */
            announceDirtyData: function () {
                var chart = this.chart, announcer = this;
                if (chart.options.accessibility.announceNewData &&
                    this.dirty.hasDirty) {
                    var newPoint = this.dirty.newPoint;
                    // If we have a single new point, see if we can find it in the
                    // data array. Otherwise we can only pass through options to
                    // the description builder, and it is a bit sparse in info.
                    if (newPoint) {
                        newPoint = findPointInDataArray(newPoint);
                    }
                    this.queueAnnouncement(Object.keys(this.dirty.allSeries).map(function (ix) {
                        return announcer.dirty.allSeries[ix];
                    }), this.dirty.newSeries, newPoint);
                    // Reset
                    this.dirty = {
                        allSeries: {}
                    };
                }
            },
            /**
             * Announce to user that there is new data.
             * @private
             * @param {Array<Highcharts.Series>} dirtySeries
             *          Array of series with new data.
             * @param {Highcharts.Series} [newSeries]
             *          If a single new series was added, a reference to this series.
             * @param {Highcharts.Point} [newPoint]
             *          If a single point was added, a reference to this point.
             */
            queueAnnouncement: function (dirtySeries, newSeries, newPoint) {
                var chart = this.chart, annOptions = (chart.options.accessibility.announceNewData);
                if (annOptions.enabled) {
                    var announcer = this, now = +new Date(), dTime = now - this.lastAnnouncementTime, time = Math.max(0, annOptions.minAnnounceInterval - dTime), 
                    // Add series from previously queued announcement.
                    allSeries = getUniqueSeries(this.queuedAnnouncement && this.queuedAnnouncement.series, dirtySeries);
                    // Build message and announce
                    var message = this.buildAnnouncementMessage(allSeries, newSeries, newPoint);
                    if (message) {
                        // Is there already one queued?
                        if (this.queuedAnnouncement) {
                            clearTimeout(this.queuedAnnouncementTimer);
                        }
                        // Build the announcement
                        this.queuedAnnouncement = {
                            time: now,
                            message: message,
                            series: allSeries
                        };
                        // Queue the announcement
                        announcer.queuedAnnouncementTimer = setTimeout(function () {
                            if (announcer && announcer.announceRegion) {
                                announcer.lastAnnouncementTime = +new Date();
                                announcer.liveRegionSpeak(announcer.queuedAnnouncement.message);
                                delete announcer.queuedAnnouncement;
                                delete announcer.queuedAnnouncementTimer;
                            }
                        }, time);
                    }
                }
            },
            /**
             * Speak a message using the announcer live region.
             * @private
             * @param {string} message
             */
            liveRegionSpeak: function (message) {
                var announcer = this;
                this.announceRegion.innerHTML = message;
                // Delete contents after a little while to avoid user finding the live
                // region in the DOM.
                if (this.clearAnnouncementContainerTimer) {
                    clearTimeout(this.clearAnnouncementContainerTimer);
                }
                this.clearAnnouncementContainerTimer = setTimeout(function () {
                    announcer.announceRegion.innerHTML = '';
                    delete announcer.clearAnnouncementContainerTimer;
                }, 1000);
            },
            /**
             * Get announcement message for new data.
             * @private
             * @param {Array<Highcharts.Series>} dirtySeries
             *          Array of series with new data.
             * @param {Highcharts.Series} [newSeries]
             *          If a single new series was added, a reference to this series.
             * @param {Highcharts.Point} [newPoint]
             *          If a single point was added, a reference to this point.
             *
             * @return {string|null}
             * The announcement message to give to user.
             */
            buildAnnouncementMessage: function (dirtySeries, newSeries, newPoint) {
                var chart = this.chart, annOptions = chart.options.accessibility.announceNewData;
                // User supplied formatter?
                if (annOptions.announcementFormatter) {
                    var formatterRes = annOptions.announcementFormatter(dirtySeries, newSeries, newPoint);
                    if (formatterRes !== false) {
                        return formatterRes.length ? formatterRes : null;
                    }
                }
                // Default formatter - use lang options
                var multiple = H.charts && H.charts.length > 1 ? 'Multiple' : 'Single', langKey = newSeries ? 'newSeriesAnnounce' + multiple :
                    newPoint ? 'newPointAnnounce' + multiple : 'newDataAnnounce', chartTitle = getChartTitle(chart);
                return chart.langFormat('accessibility.announceNewData.' + langKey, {
                    chartTitle: chartTitle,
                    seriesDesc: newSeries ?
                        defaultSeriesDescriptionFormatter(newSeries) :
                        null,
                    pointDesc: newPoint ?
                        defaultPointDescriptionFormatter(newPoint) :
                        null,
                    point: newPoint,
                    series: newSeries
                });
            }
        });

        return NewDataAnnouncer;
    });
    _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/forcedMarkers.js', [_modules['parts/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Handle forcing series markers.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var merge = H.merge;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function isWithinDescriptionThreshold(series) {
            var a11yOptions = series.chart.options.accessibility;
            return series.points.length <
                a11yOptions.series.pointDescriptionEnabledThreshold ||
                a11yOptions.series.pointDescriptionEnabledThreshold === false;
        }
        /**
         * @private
         */
        function isWithinNavigationThreshold(series) {
            var navOptions = series.chart.options.accessibility
                .keyboardNavigation.seriesNavigation;
            return series.points.length <
                navOptions.pointNavigationEnabledThreshold ||
                navOptions.pointNavigationEnabledThreshold === false;
        }
        /**
         * @private
         */
        function shouldForceMarkers(series) {
            var chartA11yEnabled = series.chart.options.accessibility.enabled, seriesA11yEnabled = (series.options.accessibility &&
                series.options.accessibility.enabled) !== false, withinDescriptionThreshold = isWithinDescriptionThreshold(series), withinNavigationThreshold = isWithinNavigationThreshold(series);
            return chartA11yEnabled && seriesA11yEnabled &&
                (withinDescriptionThreshold || withinNavigationThreshold);
        }
        /**
         * @private
         */
        function unforceMarkerOptions(series) {
            var resetMarkerOptions = series.resetA11yMarkerOptions;
            merge(true, series.options, {
                marker: {
                    enabled: resetMarkerOptions.enabled,
                    states: {
                        normal: {
                            opacity: resetMarkerOptions.states &&
                                resetMarkerOptions.states.normal &&
                                resetMarkerOptions.states.normal.opacity
                        }
                    }
                }
            });
        }
        /**
         * @private
         */
        function forceZeroOpacityMarkerOptions(options) {
            merge(true, options, {
                marker: {
                    enabled: true,
                    states: {
                        normal: {
                            opacity: 0
                        }
                    }
                }
            });
        }
        /**
         * @private
         */
        function getPointMarkerOpacity(pointOptions) {
            return pointOptions.marker.states &&
                pointOptions.marker.states.normal &&
                pointOptions.marker.states.normal.opacity || 1;
        }
        /**
         * @private
         */
        function forceDisplayPointMarker(pointOptions) {
            merge(true, pointOptions.marker, {
                states: {
                    normal: {
                        opacity: getPointMarkerOpacity(pointOptions)
                    }
                }
            });
        }
        /**
         * @private
         */
        function handleForcePointMarkers(points) {
            var i = points.length;
            while (i--) {
                var pointOptions = points[i].options;
                if (pointOptions.marker) {
                    if (pointOptions.marker.enabled) {
                        forceDisplayPointMarker(pointOptions);
                    }
                    else {
                        forceZeroOpacityMarkerOptions(pointOptions);
                    }
                }
            }
        }
        /**
         * @private
         */
        function addForceMarkersEvents() {
            /**
             * Keep track of forcing markers.
             * @private
             */
            H.addEvent(H.Series, 'render', function () {
                var series = this, options = series.options;
                if (shouldForceMarkers(series)) {
                    if (options.marker && options.marker.enabled === false) {
                        series.a11yMarkersForced = true;
                        forceZeroOpacityMarkerOptions(series.options);
                    }
                    if (series._hasPointMarkers && series.points && series.points.length) {
                        handleForcePointMarkers(series.points);
                    }
                }
                else if (series.a11yMarkersForced && series.resetMarkerOptions) {
                    delete series.a11yMarkersForced;
                    unforceMarkerOptions(series);
                }
            });
            /**
             * Keep track of options to reset markers to if no longer forced.
             * @private
             */
            H.addEvent(H.Series, 'afterSetOptions', function (e) {
                this.resetA11yMarkerOptions = merge(e.options.marker || {}, this.userOptions.marker || {});
            });
        }

        return addForceMarkersEvents;
    });
    _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesKeyboardNavigation.js'], _modules['modules/accessibility/components/SeriesComponent/NewDataAnnouncer.js'], _modules['modules/accessibility/components/SeriesComponent/forcedMarkers.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesDescriber.js']], function (H, U, AccessibilityComponent, SeriesKeyboardNavigation, NewDataAnnouncer, addForceMarkersEvents, ChartUtilities, SeriesDescriber) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for series and points.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        var hideSeriesFromAT = ChartUtilities.hideSeriesFromAT;
        var describeSeries = SeriesDescriber.describeSeries;
        // Expose functionality to users
        H.SeriesAccessibilityDescriber = SeriesDescriber;
        // Handle forcing markers
        addForceMarkersEvents();
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * The SeriesComponent class
         *
         * @private
         * @class
         * @name Highcharts.SeriesComponent
         */
        var SeriesComponent = function () { };
        SeriesComponent.prototype = new AccessibilityComponent();
        extend(SeriesComponent.prototype, /** @lends Highcharts.SeriesComponent */ {
            /**
             * Init the component.
             */
            init: function () {
                this.newDataAnnouncer = new NewDataAnnouncer(this.chart);
                this.newDataAnnouncer.init();
                this.keyboardNavigation = new SeriesKeyboardNavigation(this.chart, this.keyCodes);
                this.keyboardNavigation.init();
                this.hideTooltipFromATWhenShown();
                this.hideSeriesLabelsFromATWhenShown();
            },
            /**
             * @private
             */
            hideTooltipFromATWhenShown: function () {
                var component = this;
                this.addEvent(H.Tooltip, 'refresh', function () {
                    if (this.chart === component.chart &&
                        this.label &&
                        this.label.element) {
                        this.label.element.setAttribute('aria-hidden', true);
                    }
                });
            },
            /**
             * @private
             */
            hideSeriesLabelsFromATWhenShown: function () {
                this.addEvent(this.chart, 'afterDrawSeriesLabels', function () {
                    this.series.forEach(function (series) {
                        if (series.labelBySeries) {
                            series.labelBySeries.attr('aria-hidden', true);
                        }
                    });
                });
            },
            /**
             * Called on chart render. It is necessary to do this for render in case
             * markers change on zoom/pixel density.
             */
            onChartRender: function () {
                var chart = this.chart;
                chart.series.forEach(function (series) {
                    var shouldDescribeSeries = (series.options.accessibility &&
                        series.options.accessibility.enabled) !== false &&
                        series.visible;
                    if (shouldDescribeSeries) {
                        describeSeries(series);
                    }
                    else {
                        hideSeriesFromAT(series);
                    }
                });
            },
            /**
             * Get keyboard navigation handler for this component.
             * @return {Highcharts.KeyboardNavigationHandler}
             */
            getKeyboardNavigation: function () {
                return this.keyboardNavigation.getKeyboardNavigationHandler();
            },
            /**
             * Remove traces
             */
            destroy: function () {
                this.newDataAnnouncer.destroy();
                this.keyboardNavigation.destroy();
            }
        });

        return SeriesComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/ZoomComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for chart zoom.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend, pick = U.pick;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT;
        var setElAttrs = HTMLUtilities.setElAttrs, removeElement = HTMLUtilities.removeElement;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function chartHasMapZoom(chart) {
            return !!(chart.mapZoom &&
                chart.mapNavButtons &&
                chart.mapNavButtons.length);
        }
        /**
         * Pan along axis in a direction (1 or -1), optionally with a defined
         * granularity (number of steps it takes to walk across current view)
         *
         * @private
         * @function Highcharts.Axis#panStep
         *
         * @param {number} direction
         * @param {number} [granularity]
         */
        H.Axis.prototype.panStep = function (direction, granularity) {
            var gran = granularity || 3, extremes = this.getExtremes(), step = (extremes.max - extremes.min) / gran * direction, newMax = extremes.max + step, newMin = extremes.min + step, size = newMax - newMin;
            if (direction < 0 && newMin < extremes.dataMin) {
                newMin = extremes.dataMin;
                newMax = newMin + size;
            }
            else if (direction > 0 && newMax > extremes.dataMax) {
                newMax = extremes.dataMax;
                newMin = newMax - size;
            }
            this.setExtremes(newMin, newMax);
        };
        /**
         * The ZoomComponent class
         *
         * @private
         * @class
         * @name Highcharts.ZoomComponent
         */
        var ZoomComponent = function () { };
        ZoomComponent.prototype = new AccessibilityComponent();
        extend(ZoomComponent.prototype, /** @lends Highcharts.ZoomComponent */ {
            /**
             * Initialize the component
             */
            init: function () {
                var component = this, chart = this.chart;
                [
                    'afterShowResetZoom', 'afterDrilldown', 'drillupall'
                ].forEach(function (eventType) {
                    component.addEvent(chart, eventType, function () {
                        component.updateProxyOverlays();
                    });
                });
            },
            /**
             * Called when chart is updated
             */
            onChartUpdate: function () {
                var chart = this.chart, component = this;
                // Make map zoom buttons accessible
                if (chart.mapNavButtons) {
                    chart.mapNavButtons.forEach(function (button, i) {
                        unhideChartElementFromAT(chart, button.element);
                        component.setMapNavButtonAttrs(button.element, 'accessibility.zoom.mapZoom' + (i ? 'Out' : 'In'));
                    });
                }
            },
            /**
             * @private
             * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} button
             * @param {string} labelFormatKey
             */
            setMapNavButtonAttrs: function (button, labelFormatKey) {
                var chart = this.chart, label = chart.langFormat(labelFormatKey, { chart: chart });
                setElAttrs(button, {
                    tabindex: -1,
                    role: 'button',
                    'aria-label': label
                });
            },
            /**
             * Update the proxy overlays on every new render to ensure positions are
             * correct.
             */
            onChartRender: function () {
                this.updateProxyOverlays();
            },
            /**
             * Update proxy overlays, recreating the buttons.
             */
            updateProxyOverlays: function () {
                var chart = this.chart;
                // Always start with a clean slate
                removeElement(this.drillUpProxyGroup);
                removeElement(this.resetZoomProxyGroup);
                if (chart.resetZoomButton) {
                    this.recreateProxyButtonAndGroup(chart.resetZoomButton, 'resetZoomProxyButton', 'resetZoomProxyGroup', chart.langFormat('accessibility.zoom.resetZoomButton', { chart: chart }));
                }
                if (chart.drillUpButton) {
                    this.recreateProxyButtonAndGroup(chart.drillUpButton, 'drillUpProxyButton', 'drillUpProxyGroup', chart.langFormat('accessibility.drillUpButton', {
                        chart: chart,
                        buttonText: chart.getDrilldownBackText()
                    }));
                }
            },
            /**
             * @private
             * @param {Highcharts.SVGElement} buttonEl
             * @param {string} buttonProp
             * @param {string} groupProp
             * @param {string} label
             */
            recreateProxyButtonAndGroup: function (buttonEl, buttonProp, groupProp, label) {
                removeElement(this[groupProp]);
                this[groupProp] = this.addProxyGroup();
                this[buttonProp] = this.createProxyButton(buttonEl, this[groupProp], { 'aria-label': label, tabindex: -1 });
            },
            /**
             * Get keyboard navigation handler for map zoom.
             * @private
             * @return {Highcharts.KeyboardNavigationHandler} The module object
             */
            getMapZoomNavigation: function () {
                var keys = this.keyCodes, chart = this.chart, component = this;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [
                            [keys.up, keys.down, keys.left, keys.right],
                            function (keyCode) {
                                return component.onMapKbdArrow(this, keyCode);
                            }
                        ],
                        [
                            [keys.tab],
                            function (_keyCode, e) {
                                return component.onMapKbdTab(this, e);
                            }
                        ],
                        [
                            [keys.space, keys.enter],
                            function () {
                                return component.onMapKbdClick(this);
                            }
                        ]
                    ],
                    validate: function () {
                        return chartHasMapZoom(chart);
                    },
                    init: function (direction) {
                        return component.onMapNavInit(direction);
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @param {number} keyCode
             * @return {number} Response code
             */
            onMapKbdArrow: function (keyboardNavigationHandler, keyCode) {
                var keys = this.keyCodes, panAxis = (keyCode === keys.up || keyCode === keys.down) ?
                    'yAxis' : 'xAxis', stepDirection = (keyCode === keys.left || keyCode === keys.up) ?
                    -1 : 1;
                this.chart[panAxis][0].panStep(stepDirection);
                return keyboardNavigationHandler.response.success;
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @param {global.KeyboardEvent} event
             * @return {number} Response code
             */
            onMapKbdTab: function (keyboardNavigationHandler, event) {
                var button, chart = this.chart, response = keyboardNavigationHandler.response, isBackwards = event.shiftKey, isMoveOutOfRange = isBackwards && !this.focusedMapNavButtonIx ||
                    !isBackwards && this.focusedMapNavButtonIx;
                // Deselect old
                chart.mapNavButtons[this.focusedMapNavButtonIx].setState(0);
                if (isMoveOutOfRange) {
                    chart.mapZoom(); // Reset zoom
                    return response[isBackwards ? 'prev' : 'next'];
                }
                // Select other button
                this.focusedMapNavButtonIx += isBackwards ? -1 : 1;
                button = chart.mapNavButtons[this.focusedMapNavButtonIx];
                chart.setFocusToElement(button.box, button.element);
                button.setState(2);
                return response.success;
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @return {number} Response code
             */
            onMapKbdClick: function (keyboardNavigationHandler) {
                this.fakeClickEvent(this.chart.mapNavButtons[this.focusedMapNavButtonIx]
                    .element);
                return keyboardNavigationHandler.response.success;
            },
            /**
             * @private
             * @param {number} direction
             */
            onMapNavInit: function (direction) {
                var chart = this.chart, zoomIn = chart.mapNavButtons[0], zoomOut = chart.mapNavButtons[1], initialButton = direction > 0 ? zoomIn : zoomOut;
                chart.setFocusToElement(initialButton.box, initialButton.element);
                initialButton.setState(2);
                this.focusedMapNavButtonIx = direction > 0 ? 0 : 1;
            },
            /**
             * Get keyboard navigation handler for a simple chart button. Provide the
             * button reference for the chart, and a function to call on click.
             *
             * @private
             * @param {string} buttonProp The property on chart referencing the button.
             * @return {Highcharts.KeyboardNavigationHandler} The module object
             */
            simpleButtonNavigation: function (buttonProp, proxyProp, onClick) {
                var keys = this.keyCodes, component = this, chart = this.chart;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [
                            [keys.tab, keys.up, keys.down, keys.left, keys.right],
                            function (keyCode, e) {
                                var isBackwards = keyCode === keys.tab && e.shiftKey ||
                                    keyCode === keys.left || keyCode === keys.up;
                                // Arrow/tab => just move
                                return this.response[isBackwards ? 'prev' : 'next'];
                            }
                        ],
                        [
                            [keys.space, keys.enter],
                            function () {
                                var res = onClick(this, chart);
                                return pick(res, this.response.success);
                            }
                        ]
                    ],
                    validate: function () {
                        var hasButton = (chart[buttonProp] &&
                            chart[buttonProp].box &&
                            component[proxyProp]);
                        return hasButton;
                    },
                    init: function () {
                        chart.setFocusToElement(chart[buttonProp].box, component[proxyProp]);
                    }
                });
            },
            /**
             * Get keyboard navigation handlers for this component.
             * @return {Array<Highcharts.KeyboardNavigationHandler>}
             *         List of module objects
             */
            getKeyboardNavigation: function () {
                return [
                    this.simpleButtonNavigation('resetZoomButton', 'resetZoomProxyButton', function (_handler, chart) {
                        chart.zoomOut();
                    }),
                    this.simpleButtonNavigation('drillUpButton', 'drillUpProxyButton', function (handler, chart) {
                        chart.drillUp();
                        return handler.response.prev;
                    }),
                    this.getMapZoomNavigation()
                ];
            }
        });

        return ZoomComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/RangeSelectorComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for the range selector.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT;
        var setElAttrs = HTMLUtilities.setElAttrs;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function shouldRunInputNavigation(chart) {
            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 range selector button by index.
         *
         * @private
         * @function Highcharts.Chart#highlightRangeSelectorButton
         *
         * @param {number} ix
         *
         * @return {boolean}
         */
        H.Chart.prototype.highlightRangeSelectorButton = function (ix) {
            var buttons = this.rangeSelector.buttons, curSelectedIx = this.highlightedRangeSelectorItemIx;
            // Deselect old
            if (typeof curSelectedIx !== 'undefined' && buttons[curSelectedIx]) {
                buttons[curSelectedIx].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
         */
        var RangeSelectorComponent = function () { };
        RangeSelectorComponent.prototype = new AccessibilityComponent();
        extend(RangeSelectorComponent.prototype, /** @lends Highcharts.RangeSelectorComponent */ {
            /**
             * Called on first render/updates to the chart, including options changes.
             */
            onChartUpdate: function () {
                var chart = this.chart, component = this, rangeSelector = chart.rangeSelector;
                if (!rangeSelector) {
                    return;
                }
                if (rangeSelector.buttons && rangeSelector.buttons.length) {
                    rangeSelector.buttons.forEach(function (button) {
                        unhideChartElementFromAT(chart, button.element);
                        component.setRangeButtonAttrs(button);
                    });
                }
                // Make sure input boxes are accessible and focusable
                if (rangeSelector.maxInput && rangeSelector.minInput) {
                    ['minInput', 'maxInput'].forEach(function (key, i) {
                        var input = rangeSelector[key];
                        if (input) {
                            unhideChartElementFromAT(chart, input);
                            component.setRangeInputAttrs(input, 'accessibility.rangeSelector.' + (i ? 'max' : 'min') +
                                'InputLabel');
                        }
                    });
                }
            },
            /**
             * @private
             * @param {Highcharts.SVGElement} button
             */
            setRangeButtonAttrs: function (button) {
                var chart = this.chart, label = chart.langFormat('accessibility.rangeSelector.buttonText', {
                    chart: chart,
                    buttonText: button.text && button.text.textStr
                });
                setElAttrs(button.element, {
                    tabindex: -1,
                    role: 'button',
                    'aria-label': label
                });
            },
            /**
             * @private
             */
            setRangeInputAttrs: function (input, langKey) {
                var chart = this.chart;
                setElAttrs(input, {
                    tabindex: -1,
                    role: 'textbox',
                    'aria-label': chart.langFormat(langKey, { chart: chart })
                });
            },
            /**
             * Get navigation for the range selector buttons.
             * @private
             * @return {Highcharts.KeyboardNavigationHandler} The module object.
             */
            getRangeSelectorButtonNavigation: function () {
                var chart = this.chart, keys = this.keyCodes, component = this;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [
                            [keys.left, keys.right, keys.up, keys.down],
                            function (keyCode) {
                                return component.onButtonNavKbdArrowKey(this, keyCode);
                            }
                        ],
                        [
                            [keys.enter, keys.space],
                            function () {
                                return component.onButtonNavKbdClick(this);
                            }
                        ]
                    ],
                    validate: function () {
                        var hasRangeSelector = chart.rangeSelector &&
                            chart.rangeSelector.buttons &&
                            chart.rangeSelector.buttons.length;
                        return hasRangeSelector;
                    },
                    init: function (direction) {
                        var lastButtonIx = (chart.rangeSelector.buttons.length - 1);
                        chart.highlightRangeSelectorButton(direction > 0 ? 0 : lastButtonIx);
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @param {number} keyCode
             * @return {number} Response code
             */
            onButtonNavKbdArrowKey: function (keyboardNavigationHandler, keyCode) {
                var response = keyboardNavigationHandler.response, keys = this.keyCodes, chart = this.chart, wrapAround = chart.options.accessibility
                    .keyboardNavigation.wrapAround, direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1, didHighlight = chart.highlightRangeSelectorButton(chart.highlightedRangeSelectorItemIx + direction);
                if (!didHighlight) {
                    if (wrapAround) {
                        keyboardNavigationHandler.init(direction);
                        return response.success;
                    }
                    return response[direction > 0 ? 'next' : 'prev'];
                }
                return response.success;
            },
            /**
             * @private
             */
            onButtonNavKbdClick: function (keyboardNavigationHandler) {
                var response = keyboardNavigationHandler.response, chart = this.chart, wasDisabled = chart.oldRangeSelectorItemState === 3;
                if (!wasDisabled) {
                    this.fakeClickEvent(chart.rangeSelector.buttons[chart.highlightedRangeSelectorItemIx].element);
                }
                return response.success;
            },
            /**
             * Get navigation for the range selector input boxes.
             * @private
             * @return {Highcharts.KeyboardNavigationHandler}
             *         The module object.
             */
            getRangeSelectorInputNavigation: function () {
                var chart = this.chart, keys = this.keyCodes, component = this;
                return new KeyboardNavigationHandler(chart, {
                    keyCodeMap: [
                        [
                            [
                                keys.tab, keys.up, keys.down
                            ], function (keyCode, e) {
                                var direction = (keyCode === keys.tab && e.shiftKey ||
                                    keyCode === keys.up) ? -1 : 1;
                                return component.onInputKbdMove(this, direction);
                            }
                        ]
                    ],
                    validate: function () {
                        return shouldRunInputNavigation(chart);
                    },
                    init: function (direction) {
                        component.onInputNavInit(direction);
                    },
                    terminate: function () {
                        component.onInputNavTerminate();
                    }
                });
            },
            /**
             * @private
             * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
             * @param {number} direction
             * @return {number} Response code
             */
            onInputKbdMove: function (keyboardNavigationHandler, direction) {
                var chart = this.chart, response = keyboardNavigationHandler.response, newIx = chart.highlightedInputRangeIx =
                    chart.highlightedInputRangeIx + direction, newIxOutOfRange = newIx > 1 || newIx < 0;
                if (newIxOutOfRange) {
                    return response[direction > 0 ? 'next' : 'prev'];
                }
                chart.rangeSelector[newIx ? 'maxInput' : 'minInput'].focus();
                return response.success;
            },
            /**
             * @private
             * @param {number} direction
             */
            onInputNavInit: function (direction) {
                var chart = this.chart, buttonIxToHighlight = direction > 0 ? 0 : 1;
                chart.highlightedInputRangeIx = buttonIxToHighlight;
                chart.rangeSelector[buttonIxToHighlight ? 'maxInput' : 'minInput'].focus();
            },
            /**
             * @private
             */
            onInputNavTerminate: function () {
                var rangeSel = (this.chart.rangeSelector || {});
                if (rangeSel.maxInput) {
                    rangeSel.hideInput('max');
                }
                if (rangeSel.minInput) {
                    rangeSel.hideInput('min');
                }
            },
            /**
             * Get keyboard navigation handlers for this component.
             * @return {Array<Highcharts.KeyboardNavigationHandler>}
             *         List of module objects.
             */
            getKeyboardNavigation: function () {
                return [
                    this.getRangeSelectorButtonNavigation(),
                    this.getRangeSelectorInputNavigation()
                ];
            }
        });

        return RangeSelectorComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/InfoRegionsComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, ChartUtilities, HTMLUtilities) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for chart info region and table.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var doc = H.win.document, format = H.format;
        var extend = U.extend, pick = U.pick;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, getChartTitle = ChartUtilities.getChartTitle, getAxisDescription = ChartUtilities.getAxisDescription;
        var addClass = HTMLUtilities.addClass, setElAttrs = HTMLUtilities.setElAttrs, escapeStringForHTML = HTMLUtilities.escapeStringForHTML, stripHTMLTagsFromString = HTMLUtilities.stripHTMLTagsFromString, getElement = HTMLUtilities.getElement, visuallyHideElement = HTMLUtilities.visuallyHideElement;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * @private
         */
        function getTypeDescForMapChart(chart, formatContext) {
            return formatContext.mapTitle ?
                chart.langFormat('accessibility.chartTypes.mapTypeDescription', formatContext) :
                chart.langFormat('accessibility.chartTypes.unknownMap', formatContext);
        }
        /**
         * @private
         */
        function getTypeDescForCombinationChart(chart, formatContext) {
            return chart.langFormat('accessibility.chartTypes.combinationChart', formatContext);
        }
        /**
         * @private
         */
        function getTypeDescForEmptyChart(chart, formatContext) {
            return chart.langFormat('accessibility.chartTypes.emptyChart', formatContext);
        }
        /**
         * @private
         */
        function buildTypeDescriptionFromSeries(chart, types, context) {
            var firstType = types[0], typeExplaination = chart.langFormat('accessibility.seriesTypeDescriptions.' + firstType, context), multi = chart.series && chart.series.length < 2 ? 'Single' : 'Multiple';
            return (chart.langFormat('accessibility.chartTypes.' + firstType + multi, context) ||
                chart.langFormat('accessibility.chartTypes.default' + multi, context)) + (typeExplaination ? ' ' + typeExplaination : '');
        }
        /**
         * @private
         */
        function getTableSummary(chart) {
            return chart.langFormat('accessibility.table.tableSummary', { chart: chart });
        }
        /**
         * @private
         */
        function stripEmptyHTMLTags(str) {
            return str.replace(/<(\w+)[^>]*?>\s*<\/\1>/g, '');
        }
        /**
         * @private
         */
        function enableSimpleHTML(str) {
            return str
                .replace(/&lt;(h[1-7]|p|div)&gt;/g, '<$1>')
                .replace(/&lt;&#x2F;(h[1-7]|p|div|a|button)&gt;/g, '</$1>')
                .replace(/&lt;(div|a|button) id=&quot;([a-zA-Z\-0-9#]*?)&quot;&gt;/g, '<$1 id="$2">');
        }
        /**
         * @private
         */
        function stringToSimpleHTML(str) {
            return stripEmptyHTMLTags(enableSimpleHTML(escapeStringForHTML(str)));
        }
        /**
         * Return simplified explaination of chart type. Some types will not be familiar
         * to most users, but in those cases we try to add an explaination of the type.
         *
         * @private
         * @function Highcharts.Chart#getTypeDescription
         * @param {Array<string>} types The series types in this chart.
         * @return {string} The text description of the chart type.
         */
        H.Chart.prototype.getTypeDescription = function (types) {
            var firstType = types[0], firstSeries = this.series && this.series[0] || {}, formatContext = {
                numSeries: this.series.length,
                numPoints: firstSeries.points && firstSeries.points.length,
                chart: this,
                mapTitle: firstSeries.mapTitle
            };
            if (!firstType) {
                return getTypeDescForEmptyChart(this, formatContext);
            }
            if (firstType === 'map') {
                return getTypeDescForMapChart(this, formatContext);
            }
            if (this.types.length > 1) {
                return getTypeDescForCombinationChart(this, formatContext);
            }
            return buildTypeDescriptionFromSeries(this, types, formatContext);
        };
        /**
         * The InfoRegionsComponent class
         *
         * @private
         * @class
         * @name Highcharts.InfoRegionsComponent
         */
        var InfoRegionsComponent = function () { };
        InfoRegionsComponent.prototype = new AccessibilityComponent();
        extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponent */ {
            /**
             * Init the component
             * @private
             */
            init: function () {
                var chart = this.chart, component = this;
                this.initRegionsDefinitions();
                this.addEvent(chart, 'afterGetTable', function (e) {
                    component.onDataTableCreated(e);
                });
                this.addEvent(chart, 'afterViewData', function (tableDiv) {
                    component.dataTableDiv = tableDiv;
                    // Use small delay to give browsers & AT time to register new table
                    setTimeout(function () {
                        component.focusDataTable();
                    }, 300);
                });
            },
            /**
             * @private
             */
            initRegionsDefinitions: function () {
                var component = this;
                this.screenReaderSections = {
                    before: {
                        element: null,
                        buildContent: function (chart) {
                            var formatter = chart.options.accessibility
                                .screenReaderSection.beforeChartFormatter;
                            return formatter ? formatter(chart) :
                                component.defaultBeforeChartFormatter(chart);
                        },
                        insertIntoDOM: function (el, chart) {
                            chart.renderTo.insertBefore(el, chart.renderTo.firstChild);
                        },
                        afterInserted: function () {
                            if (typeof component.dataTableButtonId !== 'undefined') {
                                component.initDataTableButton(component.dataTableButtonId);
                            }
                        }
                    },
                    after: {
                        element: null,
                        buildContent: function (chart) {
                            var formatter = chart.options.accessibility.screenReaderSection
                                .afterChartFormatter;
                            return formatter ? formatter(chart) :
                                component.defaultAfterChartFormatter();
                        },
                        insertIntoDOM: function (el, chart) {
                            chart.renderTo.insertBefore(el, chart.container.nextSibling);
                        }
                    }
                };
            },
            /**
             * Called on first render/updates to the chart, including options changes.
             */
            onChartUpdate: function () {
                var component = this;
                this.linkedDescriptionElement = this.getLinkedDescriptionElement();
                this.setLinkedDescriptionAttrs();
                Object.keys(this.screenReaderSections).forEach(function (regionKey) {
                    component.updateScreenReaderSection(regionKey);
                });
            },
            /**
             * @private
             */
            getLinkedDescriptionElement: function () {
                var chartOptions = this.chart.options, linkedDescOption = chartOptions.accessibility.linkedDescription;
                if (!linkedDescOption) {
                    return;
                }
                if (typeof linkedDescOption !== 'string') {
                    return linkedDescOption;
                }
                var query = format(linkedDescOption, this.chart), queryMatch = doc.querySelectorAll(query);
                if (queryMatch.length === 1) {
                    return queryMatch[0];
                }
            },
            /**
             * @private
             */
            setLinkedDescriptionAttrs: function () {
                var el = this.linkedDescriptionElement;
                if (el) {
                    el.setAttribute('aria-hidden', 'true');
                    addClass(el, 'highcharts-linked-description');
                }
            },
            /**
             * @private
             * @param {string} regionKey The name/key of the region to update
             */
            updateScreenReaderSection: function (regionKey) {
                var chart = this.chart, region = this.screenReaderSections[regionKey], content = region.buildContent(chart), sectionDiv = region.element = (region.element || this.createElement('div')), hiddenDiv = (sectionDiv.firstChild || this.createElement('div'));
                this.setScreenReaderSectionAttribs(sectionDiv, regionKey);
                hiddenDiv.innerHTML = content;
                sectionDiv.appendChild(hiddenDiv);
                region.insertIntoDOM(sectionDiv, chart);
                visuallyHideElement(hiddenDiv);
                unhideChartElementFromAT(chart, hiddenDiv);
                if (region.afterInserted) {
                    region.afterInserted();
                }
            },
            /**
             * @private
             * @param {Highcharts.HTMLDOMElement} sectionDiv The section element
             * @param {string} regionKey Name/key of the region we are setting attrs for
             */
            setScreenReaderSectionAttribs: function (sectionDiv, regionKey) {
                var labelLangKey = ('accessibility.screenReaderSection.' + regionKey + 'RegionLabel'), chart = this.chart, labelText = chart.langFormat(labelLangKey, { chart: chart }), sectionId = 'highcharts-screen-reader-region-' + regionKey + '-' +
                    chart.index;
                setElAttrs(sectionDiv, {
                    id: sectionId,
                    'aria-label': labelText
                });
                // Sections are wrapped to be positioned relatively to chart in case
                // elements inside are tabbed to.
                sectionDiv.style.position = 'relative';
                if (chart.options.accessibility.landmarkVerbosity === 'all' &&
                    labelText) {
                    sectionDiv.setAttribute('role', 'region');
                }
            },
            /**
             * @private
             * @return {string}
             */
            defaultBeforeChartFormatter: function () {
                var chart = this.chart, format = chart.options.accessibility
                    .screenReaderSection.beforeChartFormat, axesDesc = this.getAxesDescription(), dataTableButtonId = 'hc-linkto-highcharts-data-table-' +
                    chart.index, context = {
                    chartTitle: getChartTitle(chart),
                    typeDescription: this.getTypeDescriptionText(),
                    chartSubtitle: this.getSubtitleText(),
                    chartLongdesc: this.getLongdescText(),
                    xAxisDescription: axesDesc.xAxis,
                    yAxisDescription: axesDesc.yAxis,
                    viewTableButton: chart.getCSV ?
                        this.getDataTableButtonText(dataTableButtonId) : ''
                }, formattedString = H.i18nFormat(format, context, chart);
                this.dataTableButtonId = dataTableButtonId;
                return stringToSimpleHTML(formattedString);
            },
            /**
             * @private
             * @return {string}
             */
            defaultAfterChartFormatter: function () {
                var chart = this.chart, format = chart.options.accessibility
                    .screenReaderSection.afterChartFormat, context = {
                    endOfChartMarker: this.getEndOfChartMarkerText()
                }, formattedString = H.i18nFormat(format, context, chart);
                return stringToSimpleHTML(formattedString);
            },
            /**
             * @private
             * @return {string}
             */
            getLinkedDescription: function () {
                var el = this.linkedDescriptionElement, content = el && el.innerHTML || '';
                return stripHTMLTagsFromString(content);
            },
            /**
             * @private
             * @return {string}
             */
            getLongdescText: function () {
                var chartOptions = this.chart.options, captionOptions = chartOptions.caption, captionText = captionOptions && captionOptions.text, linkedDescription = this.getLinkedDescription();
                return (chartOptions.accessibility.description ||
                    linkedDescription ||
                    captionText ||
                    '');
            },
            /**
             * @private
             * @return {string}
             */
            getTypeDescriptionText: function () {
                var chart = this.chart;
                return chart.types ?
                    chart.options.accessibility.typeDescription ||
                        chart.getTypeDescription(chart.types) : '';
            },
            /**
             * @private
             * @param {string} buttonId
             * @return {string}
             */
            getDataTableButtonText: function (buttonId) {
                var chart = this.chart, buttonText = chart.langFormat('accessibility.table.viewAsDataTableButtonText', { chart: chart, chartTitle: getChartTitle(chart) });
                return '<a id="' + buttonId + '">' + buttonText + '</a>';
            },
            /**
             * @private
             * @return {string}
             */
            getSubtitleText: function () {
                var subtitle = (this.chart.options.subtitle);
                return stripHTMLTagsFromString(subtitle && subtitle.text || '');
            },
            /**
             * @private
             * @return {string}
             */
            getEndOfChartMarkerText: function () {
                var chart = this.chart, markerText = chart.langFormat('accessibility.screenReaderSection.endOfChartMarker', { chart: chart }), id = 'highcharts-end-of-chart-marker-' + chart.index;
                return '<div id="' + id + '">' + markerText + '</div>';
            },
            /**
             * @private
             * @param {Highcharts.Dictionary<string>} e
             */
            onDataTableCreated: function (e) {
                var chart = this.chart;
                if (chart.options.accessibility.enabled) {
                    if (this.viewDataTableButton) {
                        this.viewDataTableButton.setAttribute('aria-expanded', 'true');
                    }
                    e.html = e.html.replace('<table ', '<table tabindex="0" summary="' + getTableSummary(chart) + '"');
                }
            },
            /**
             * @private
             */
            focusDataTable: function () {
                var tableDiv = this.dataTableDiv, table = tableDiv && tableDiv.getElementsByTagName('table')[0];
                if (table && table.focus) {
                    table.focus();
                }
            },
            /**
             * Set attribs and handlers for default viewAsDataTable button if exists.
             * @private
             * @param {string} tableButtonId
             */
            initDataTableButton: function (tableButtonId) {
                var el = this.viewDataTableButton = getElement(tableButtonId), chart = this.chart, tableId = tableButtonId.replace('hc-linkto-', '');
                if (el) {
                    setElAttrs(el, {
                        role: 'button',
                        tabindex: '-1',
                        'aria-expanded': !!getElement(tableId),
                        href: '#' + tableId
                    });
                    el.onclick = chart.options.accessibility
                        .screenReaderSection.onViewDataTableClick ||
                        function () {
                            chart.viewData();
                        };
                }
            },
            /**
             * Return object with text description of each of the chart's axes.
             * @private
             * @return {Highcharts.Dictionary<string>}
             */
            getAxesDescription: function () {
                var chart = this.chart, shouldDescribeColl = function (collectionKey, defaultCondition) {
                    var axes = chart[collectionKey];
                    return axes.length > 1 || axes[0] &&
                        pick(axes[0].options.accessibility &&
                            axes[0].options.accessibility.enabled, defaultCondition);
                }, hasNoMap = !!chart.types && chart.types.indexOf('map') < 0, hasCartesian = !!chart.hasCartesianSeries, showXAxes = shouldDescribeColl('xAxis', !chart.angular && hasCartesian && hasNoMap), showYAxes = shouldDescribeColl('yAxis', hasCartesian && hasNoMap), desc = {};
                if (showXAxes) {
                    desc.xAxis = this.getAxisDescriptionText('xAxis');
                }
                if (showYAxes) {
                    desc.yAxis = this.getAxisDescriptionText('yAxis');
                }
                return desc;
            },
            /**
             * @private
             * @param {string} collectionKey
             * @return {string}
             */
            getAxisDescriptionText: function (collectionKey) {
                var component = this, chart = this.chart, axes = chart[collectionKey];
                return chart.langFormat('accessibility.axis.' + collectionKey + 'Description' + (axes.length > 1 ? 'Plural' : 'Singular'), {
                    chart: chart,
                    names: axes.map(function (axis) {
                        return getAxisDescription(axis);
                    }),
                    ranges: axes.map(function (axis) {
                        return component.getAxisRangeDescription(axis);
                    }),
                    numAxes: axes.length
                });
            },
            /**
             * Return string with text description of the axis range.
             * @private
             * @param {Highcharts.Axis} axis The axis to get range desc of.
             * @return {string} A string with the range description for the axis.
             */
            getAxisRangeDescription: function (axis) {
                var axisOptions = axis.options || {};
                // Handle overridden range description
                if (axisOptions.accessibility &&
                    typeof axisOptions.accessibility.rangeDescription !== 'undefined') {
                    return axisOptions.accessibility.rangeDescription;
                }
                // Handle category axes
                if (axis.categories) {
                    return this.getCategoryAxisRangeDesc(axis);
                }
                // Use time range, not from-to?
                if (axis.isDatetimeAxis && (axis.min === 0 || axis.dataMin === 0)) {
                    return this.getAxisTimeLengthDesc(axis);
                }
                // Just use from and to.
                // We have the range and the unit to use, find the desc format
                return this.getAxisFromToDescription(axis);
            },
            /**
             * @private
             * @param {Highcharts.Axis} axis
             * @return {string}
             */
            getCategoryAxisRangeDesc: function (axis) {
                var chart = this.chart;
                if (axis.dataMax && axis.dataMin) {
                    return chart.langFormat('accessibility.axis.rangeCategories', {
                        chart: chart,
                        axis: axis,
                        numCategories: axis.dataMax - axis.dataMin + 1
                    });
                }
                return '';
            },
            /**
             * @private
             * @param {Highcharts.Axis} axis
             * @return {string}
             */
            getAxisTimeLengthDesc: function (axis) {
                var chart = this.chart, range = {}, rangeUnit = 'Seconds';
                range.Seconds = ((axis.max || 0) - (axis.min || 0)) / 1000;
                range.Minutes = range.Seconds / 60;
                range.Hours = range.Minutes / 60;
                range.Days = range.Hours / 24;
                ['Minutes', 'Hours', 'Days'].forEach(function (unit) {
                    if (range[unit] > 2) {
                        rangeUnit = unit;
                    }
                });
                var rangeValue = range[rangeUnit].toFixed(rangeUnit !== 'Seconds' &&
                    rangeUnit !== 'Minutes' ? 1 : 0 // Use decimals for days/hours
                );
                // We have the range and the unit to use, find the desc format
                return chart.langFormat('accessibility.axis.timeRange' + rangeUnit, {
                    chart: chart,
                    axis: axis,
                    range: rangeValue.replace('.0', '')
                });
            },
            /**
             * @private
             * @param {Highcharts.Axis} axis
             * @return {string}
             */
            getAxisFromToDescription: function (axis) {
                var chart = this.chart, dateRangeFormat = chart.options.accessibility
                    .screenReaderSection.axisRangeDateFormat, format = function (axisKey) {
                    return axis.isDatetimeAxis ? chart.time.dateFormat(dateRangeFormat, axis[axisKey]) : axis[axisKey];
                };
                return chart.langFormat('accessibility.axis.rangeFromTo', {
                    chart: chart,
                    axis: axis,
                    rangeFrom: format('min'),
                    rangeTo: format('max')
                });
            }
        });

        return InfoRegionsComponent;
    });
    _registerModule(_modules, 'modules/accessibility/components/ContainerComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/AccessibilityComponent.js']], function (H, U, HTMLUtilities, ChartUtilities, AccessibilityComponent) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility component for chart container.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var doc = H.win.document;
        var extend = U.extend;
        var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString;
        var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, getChartTitle = ChartUtilities.getChartTitle;
        /* eslint-disable valid-jsdoc */
        /**
         * The ContainerComponent class
         *
         * @private
         * @class
         * @name Highcharts.ContainerComponent
         */
        var ContainerComponent = function () { };
        ContainerComponent.prototype = new AccessibilityComponent();
        extend(ContainerComponent.prototype, /** @lends Highcharts.ContainerComponent */ {
            /**
             * Called on first render/updates to the chart, including options changes.
             */
            onChartUpdate: function () {
                this.handleSVGTitleElement();
                this.setSVGContainerLabel();
                this.setGraphicContainerAttrs();
                this.setRenderToAttrs();
                this.makeCreditsAccessible();
            },
            /**
             * @private
             */
            handleSVGTitleElement: function () {
                var chart = this.chart, titleId = 'highcharts-title-' + chart.index, titleContents = stripHTMLTags(chart.langFormat('accessibility.svgContainerTitle', {
                    chartTitle: getChartTitle(chart)
                }));
                if (titleContents.length) {
                    var titleElement = this.svgTitleElement =
                        this.svgTitleElement || doc.createElementNS('http://www.w3.org/2000/svg', 'title');
                    titleElement.textContent = titleContents;
                    titleElement.id = titleId;
                    chart.renderTo.insertBefore(titleElement, chart.renderTo.firstChild);
                }
            },
            /**
             * @private
             */
            setSVGContainerLabel: function () {
                var chart = this.chart, svgContainerLabel = stripHTMLTags(chart.langFormat('accessibility.svgContainerLabel', {
                    chartTitle: getChartTitle(chart)
                }));
                if (chart.renderer.box && svgContainerLabel.length) {
                    chart.renderer.box.setAttribute('aria-label', svgContainerLabel);
                }
            },
            /**
             * @private
             */
            setGraphicContainerAttrs: function () {
                var chart = this.chart, label = chart.langFormat('accessibility.graphicContainerLabel', {
                    chartTitle: getChartTitle(chart)
                });
                if (label.length) {
                    chart.container.setAttribute('aria-label', label);
                }
            },
            /**
             * @private
             */
            setRenderToAttrs: function () {
                var chart = this.chart;
                if (chart.options.accessibility.landmarkVerbosity !== 'disabled') {
                    chart.renderTo.setAttribute('role', 'region');
                }
                else {
                    chart.renderTo.removeAttribute('role');
                }
                chart.renderTo.setAttribute('aria-label', chart.langFormat('accessibility.chartContainerLabel', {
                    title: getChartTitle(chart),
                    chart: chart
                }));
            },
            /**
             * @private
             */
            makeCreditsAccessible: function () {
                var chart = this.chart, credits = chart.credits;
                if (credits) {
                    if (credits.textStr) {
                        credits.element.setAttribute('aria-label', stripHTMLTags(chart.langFormat('accessibility.credits', { creditsStr: credits.textStr })));
                    }
                    unhideChartElementFromAT(chart, credits.element);
                }
            },
            /**
             * Accessibility disabled/chart destroyed.
             */
            destroy: function () {
                this.chart.renderTo.setAttribute('aria-hidden', true);
            }
        });

        return ContainerComponent;
    });
    _registerModule(_modules, 'modules/accessibility/high-contrast-mode.js', [_modules['parts/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Handling for Windows High Contrast Mode.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var isMS = H.isMS, win = H.win, doc = win.document;
        var whcm = {
            /**
             * Detect WHCM in the browser.
             *
             * @function Highcharts#isHighContrastModeActive
             * @private
             * @return {boolean} Returns true if the browser is in High Contrast mode.
             */
            isHighContrastModeActive: function () {
                if (win.matchMedia &&
                    isMS &&
                    /Edge\/\d./i.test(win.navigator.userAgent)) {
                    // Use media query for Edge
                    return win.matchMedia('(-ms-high-contrast: active)').matches;
                }
                if (isMS && win.getComputedStyle) {
                    // Test BG image for IE
                    var testDiv = doc.createElement('div');
                    testDiv.style.backgroundImage = 'url(#)';
                    doc.body.appendChild(testDiv);
                    var bi = (testDiv.currentStyle ||
                        win.getComputedStyle(testDiv)).backgroundImage;
                    doc.body.removeChild(testDiv);
                    return bi === 'none';
                }
                // Not used for other browsers
                return false;
            },
            /**
             * Force high contrast theme for the chart. The default theme is defined in
             * a separate file.
             *
             * @function Highcharts#setHighContrastTheme
             * @private
             * @param {Highcharts.AccessibilityChart} chart The chart to set the theme of.
             * @return {void}
             */
            setHighContrastTheme: function (chart) {
                // We might want to add additional functionality here in the future for
                // storing the old state so that we can reset the theme if HC mode is
                // disabled. For now, the user will have to reload the page.
                chart.highContrastModeActive = true;
                // Apply theme to chart
                var theme = (chart.options.accessibility.highContrastTheme);
                chart.update(theme, false);
                // Force series colors (plotOptions is not enough)
                chart.series.forEach(function (s) {
                    var plotOpts = theme.plotOptions[s.type] || {};
                    s.update({
                        color: plotOpts.color || 'windowText',
                        colors: [plotOpts.color || 'windowText'],
                        borderColor: plotOpts.borderColor || 'window'
                    });
                    // Force point colors if existing
                    s.points.forEach(function (p) {
                        if (p.options && p.options.color) {
                            p.update({
                                color: plotOpts.color || 'windowText',
                                borderColor: plotOpts.borderColor || 'window'
                            }, false);
                        }
                    });
                });
                // The redraw for each series and after is required for 3D pie
                // (workaround)
                chart.redraw();
            }
        };

        return whcm;
    });
    _registerModule(_modules, 'modules/accessibility/high-contrast-theme.js', [], function () {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Default theme for Windows High Contrast Mode.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var theme = {
            chart: {
                backgroundColor: 'window'
            },
            title: {
                style: {
                    color: 'windowText'
                }
            },
            subtitle: {
                style: {
                    color: 'windowText'
                }
            },
            colorAxis: {
                minColor: 'windowText',
                maxColor: 'windowText',
                stops: []
            },
            colors: ['windowText'],
            xAxis: {
                gridLineColor: 'windowText',
                labels: {
                    style: {
                        color: 'windowText'
                    }
                },
                lineColor: 'windowText',
                minorGridLineColor: 'windowText',
                tickColor: 'windowText',
                title: {
                    style: {
                        color: 'windowText'
                    }
                }
            },
            yAxis: {
                gridLineColor: 'windowText',
                labels: {
                    style: {
                        color: 'windowText'
                    }
                },
                lineColor: 'windowText',
                minorGridLineColor: 'windowText',
                tickColor: 'windowText',
                title: {
                    style: {
                        color: 'windowText'
                    }
                }
            },
            tooltip: {
                backgroundColor: 'window',
                borderColor: 'windowText',
                style: {
                    color: 'windowText'
                }
            },
            plotOptions: {
                series: {
                    lineColor: 'windowText',
                    fillColor: 'window',
                    borderColor: 'windowText',
                    edgeColor: 'windowText',
                    borderWidth: 1,
                    dataLabels: {
                        connectorColor: 'windowText',
                        color: 'windowText',
                        style: {
                            color: 'windowText',
                            textOutline: 'none'
                        }
                    },
                    marker: {
                        lineColor: 'windowText',
                        fillColor: 'windowText'
                    }
                },
                pie: {
                    color: 'window',
                    colors: ['window'],
                    borderColor: 'windowText',
                    borderWidth: 1
                },
                boxplot: {
                    fillColor: 'window'
                },
                candlestick: {
                    lineColor: 'windowText',
                    fillColor: 'window'
                },
                errorbar: {
                    fillColor: 'window'
                }
            },
            legend: {
                backgroundColor: 'window',
                itemStyle: {
                    color: 'windowText'
                },
                itemHoverStyle: {
                    color: 'windowText'
                },
                itemHiddenStyle: {
                    color: '#555'
                },
                title: {
                    style: {
                        color: 'windowText'
                    }
                }
            },
            credits: {
                style: {
                    color: 'windowText'
                }
            },
            labels: {
                style: {
                    color: 'windowText'
                }
            },
            drilldown: {
                activeAxisLabelStyle: {
                    color: 'windowText'
                },
                activeDataLabelStyle: {
                    color: 'windowText'
                }
            },
            navigation: {
                buttonOptions: {
                    symbolStroke: 'windowText',
                    theme: {
                        fill: 'window'
                    }
                }
            },
            rangeSelector: {
                buttonTheme: {
                    fill: 'window',
                    stroke: 'windowText',
                    style: {
                        color: 'windowText'
                    },
                    states: {
                        hover: {
                            fill: 'window',
                            stroke: 'windowText',
                            style: {
                                color: 'windowText'
                            }
                        },
                        select: {
                            fill: '#444',
                            stroke: 'windowText',
                            style: {
                                color: 'windowText'
                            }
                        }
                    }
                },
                inputBoxBorderColor: 'windowText',
                inputStyle: {
                    backgroundColor: 'window',
                    color: 'windowText'
                },
                labelStyle: {
                    color: 'windowText'
                }
            },
            navigator: {
                handles: {
                    backgroundColor: 'window',
                    borderColor: 'windowText'
                },
                outlineColor: 'windowText',
                maskFill: 'transparent',
                series: {
                    color: 'windowText',
                    lineColor: 'windowText'
                },
                xAxis: {
                    gridLineColor: 'windowText'
                }
            },
            scrollbar: {
                barBackgroundColor: '#444',
                barBorderColor: 'windowText',
                buttonArrowColor: 'windowText',
                buttonBackgroundColor: 'window',
                buttonBorderColor: 'windowText',
                rifleColor: 'windowText',
                trackBackgroundColor: 'window',
                trackBorderColor: 'windowText'
            }
        };

        return theme;
    });
    _registerModule(_modules, 'modules/accessibility/options/options.js', [], function () {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Default options for accessibility.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        /**
         * Formatter callback for the accessibility announcement.
         *
         * @callback Highcharts.AccessibilityAnnouncementFormatter
         *
         * @param {Array<Highcharts.Series>} updatedSeries
         * Array of all series that received updates. If an announcement is already
         * queued, the series that received updates for that announcement are also
         * included in this array.
         *
         * @param {Highcharts.Series} [addedSeries]
         * This is provided if {@link Highcharts.Chart#addSeries} was called, and there
         * is a new series. In that case, this argument is a reference to the new
         * series.
         *
         * @param {Highcharts.Point} [addedPoint]
         * This is provided if {@link Highcharts.Series#addPoint} was called, and there
         * is a new point. In that case, this argument is a reference to the new point.
         *
         * @return {false|string}
         * The function should return a string with the text to announce to the user.
         * Return empty string to not announce anything. Return `false` to use the
         * default announcement format.
         */
        /**
         * @interface Highcharts.PointAccessibilityOptionsObject
         */ /**
        * Provide a description of the data point, announced to screen readers.
        * @name Highcharts.PointAccessibilityOptionsObject#description
        * @type {string|undefined}
        * @requires modules/accessibility
        * @since 7.1.0
        */
        /* *
         * @interface Highcharts.PointOptionsObject in parts/Point.ts
         */ /**
        * @name Highcharts.PointOptionsObject#accessibility
        * @type {Highcharts.PointAccessibilityOptionsObject|undefined}
        * @requires modules/accessibility
        * @since 7.1.0
        */
        /**
         * @callback Highcharts.ScreenReaderClickCallbackFunction
         *
         * @param {global.MouseEvent} evt
         *        Mouse click event
         *
         * @return {void}
         */
        /**
         * Creates a formatted string for the screen reader module.
         *
         * @callback Highcharts.ScreenReaderFormatterCallbackFunction<T>
         *
         * @param {T} context
         *        Context to format
         *
         * @return {string}
         *         Formatted string for the screen reader module.
         */
        var options = {
            /**
             * Options for configuring accessibility for the chart. Requires the
             * [accessibility module](https://code.highcharts.com/modules/accessibility.js)
             * to be loaded. For a description of the module and information
             * on its features, see
             * [Highcharts Accessibility](http://www.highcharts.com/docs/chart-concepts/accessibility).
             *
             * @since        5.0.0
             * @requires     modules/accessibility
             * @optionparent accessibility
             */
            accessibility: {
                /**
                 * Enable accessibility functionality for the chart.
                 *
                 * @since 5.0.0
                 */
                enabled: true,
                /**
                 * Accessibility options for the screen reader information sections
                 * added before and after the chart.
                 *
                 * @since 8.0.0
                 */
                screenReaderSection: {
                    /**
                     * Function to run upon clicking the "View as Data Table" link in
                     * the screen reader region.
                     *
                     * By default Highcharts will insert and set focus to a data table
                     * representation of the chart.
                     *
                     * @type      {Highcharts.ScreenReaderClickCallbackFunction}
                     * @since 8.0.0
                     * @apioption accessibility.screenReaderSection.onViewDataTableClick
                     */
                    /**
                     * A formatter function to create the HTML contents of the hidden
                     * screen reader information region before the chart. Receives one
                     * argument, `chart`, referring to the chart object. Should return a
                     * string with the HTML content of the region. By default this
                     * returns an automatic description of the chart based on
                     * [beforeChartFormat](#accessibility.screenReaderSection.beforeChartFormat).
                     *
                     * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Chart>}
                     * @since 8.0.0
                     * @apioption accessibility.screenReaderSection.beforeChartFormatter
                     */
                    /**
                     * Format for the screen reader information region before the chart.
                     * Supported HTML tags are `<h1-7>`, `<p>`, `<div>`, `<a>`, and
                     * `<button>`. Attributes are not supported, except for id on
                     * `<div>`, `<a>`, and `<button>`. Id is required on `<a>` and
                     * `<button>` in the format `<tag id="abcd">`. Numbers, lower- and
                     * uppercase letters, "-" and "#" are valid characters in IDs.
                     *
                     * @since 8.0.0
                     */
                    beforeChartFormat: '<h5>{chartTitle}</h5>' +
                        '<div>{typeDescription}</div>' +
                        '<div>{chartSubtitle}</div>' +
                        '<div>{chartLongdesc}</div>' +
                        '<div>{xAxisDescription}</div>' +
                        '<div>{yAxisDescription}</div>' +
                        '<div>{viewTableButton}</div>',
                    /**
                     * A formatter function to create the HTML contents of the hidden
                     * screen reader information region after the chart. Analogous to
                     * [beforeChartFormatter](#accessibility.screenReaderSection.beforeChartFormatter).
                     *
                     * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Chart>}
                     * @since 8.0.0
                     * @apioption accessibility.screenReaderSection.afterChartFormatter
                     */
                    /**
                     * Format for the screen reader information region after the chart.
                     * Analogous to [beforeChartFormat](#accessibility.screenReaderSection.beforeChartFormat).
                     *
                     * @since 8.0.0
                     */
                    afterChartFormat: '{endOfChartMarker}',
                    /**
                     * Date format to use to describe range of datetime axes.
                     *
                     * For an overview of the replacement codes, see
                     * [dateFormat](/class-reference/Highcharts#dateFormat).
                     *
                     * @see [point.dateFormat](#accessibility.point.dateFormat)
                     *
                     * @since 8.0.0
                     */
                    axisRangeDateFormat: '%Y-%m-%d %H:%M:%S'
                },
                /**
                 * Accessibility options global to all data series. Individual series
                 * can also have specific [accessibility options](#plotOptions.series.accessibility)
                 * set.
                 *
                 * @since 8.0.0
                 */
                series: {
                    /**
                     * Formatter function to use instead of the default for series
                     * descriptions. Receives one argument, `series`, referring to the
                     * series to describe. Should return a string with the description
                     * of the series for a screen reader user. If `false` is returned,
                     * the default formatter will be used for that series.
                     *
                     * @see [series.description](#plotOptions.series.description)
                     *
                     * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Series>}
                     * @since 8.0.0
                     * @apioption accessibility.series.descriptionFormatter
                     */
                    /**
                     * Whether or not to add series descriptions to charts with a single
                     * series.
                     *
                     * @since 8.0.0
                     */
                    describeSingleSeries: false,
                    /**
                     * When a series contains more points than this, we no longer expose
                     * information about individual points to screen readers.
                     *
                     * Set to `false` to disable.
                     *
                     * @type  {boolean|number}
                     * @since 8.0.0
                     */
                    pointDescriptionEnabledThreshold: 200
                },
                /**
                 * Amount of landmarks/regions to create for screen reader users. More
                 * landmarks can make navigation with screen readers easier, but can
                 * be distracting if there are lots of charts on the page. Three modes
                 * are available:
                 *  - `all`: Adds regions for all series, legend, menu, information
                 *      region.
                 *  - `one`: Adds a single landmark per chart.
                 *  - `disabled`: No landmarks are added.
                 *
                 * @since 7.1.0
                 * @validvalue ["all", "one", "disabled"]
                 */
                landmarkVerbosity: 'all',
                /**
                 * Link the chart to an HTML element describing the contents of the
                 * chart.
                 *
                 * It is always recommended to describe charts using visible text, to
                 * improve SEO as well as accessibility for users with disabilities.
                 * This option lets an HTML element with a description be linked to the
                 * chart, so that screen reader users can connect the two.
                 *
                 * By setting this option to a string, Highcharts runs the string as an
                 * HTML selector query on the entire document. If there is only a single
                 * match, this element is linked to the chart. The content of the linked
                 * element will be included in the chart description for screen reader
                 * users.
                 *
                 * By default, the chart looks for an adjacent sibling element with the
                 * `highcharts-description` class.
                 *
                 * The feature can be disabled by setting the option to an empty string,
                 * or overridden by providing the
                 * [accessibility.description](#accessibility.description) option.
                 * Alternatively, the HTML element to link can be passed in directly as
                 * an HTML node.
                 *
                 * If you need the description to be part of the exported image,
                 * consider using the [caption](#caption) feature.
                 *
                 * If you need the description to be hidden visually, use the
                 * [accessibility.description](#accessibility.description) option.
                 *
                 * @see [caption](#caption)
                 * @see [description](#accessibility.description)
                 * @see [typeDescription](#accessibility.typeDescription)
                 *
                 * @sample highcharts/accessibility/accessible-line
                 *         Accessible line chart
                 *
                 * @type  {string|Highcharts.HTMLDOMElement}
                 * @since 8.0.0
                 */
                linkedDescription: '*[data-highcharts-chart="{index}"] + .highcharts-description',
                /**
                 * A hook for adding custom components to the accessibility module.
                 * Should be an object mapping component names to instances of classes
                 * inheriting from the Highcharts.AccessibilityComponent base class.
                 * Remember to add the component to the
                 * [keyboardNavigation.order](#accessibility.keyboardNavigation.order)
                 * for the keyboard navigation to be usable.
                 *
                 * @sample highcharts/accessibility/custom-component
                 *         Custom accessibility component
                 *
                 * @type      {*}
                 * @since     7.1.0
                 * @apioption accessibility.customComponents
                 */
                /**
                 * Theme to apply to the chart when Windows High Contrast Mode is
                 * detected. By default, a high contrast theme matching the high
                 * contrast system system colors is used.
                 *
                 * @type      {*}
                 * @since     7.1.3
                 * @apioption accessibility.highContrastTheme
                 */
                /**
                 * A text description of the chart.
                 *
                 * **Note: Prefer using [linkedDescription](#accessibility.linkedDescription)
                 * or [caption](#caption.text) instead.**
                 *
                 * If the Accessibility module is loaded, this option is included by
                 * default as a long description of the chart in the hidden screen
                 * reader information region.
                 *
                 * Note: Since Highcharts now supports captions and linked descriptions,
                 * it is preferred to define the description using those methods, as a
                 * visible caption/description benefits all users. If the
                 * `accessibility.description` option is defined, the linked description
                 * is ignored, and the caption is hidden from screen reader users.
                 *
                 * @see [linkedDescription](#accessibility.linkedDescription)
                 * @see [caption](#caption)
                 * @see [typeDescription](#accessibility.typeDescription)
                 *
                 * @type      {string}
                 * @since     5.0.0
                 * @apioption accessibility.description
                 */
                /**
                 * A text description of the chart type.
                 *
                 * If the Accessibility module is loaded, this will be included in the
                 * description of the chart in the screen reader information region.
                 *
                 * Highcharts will by default attempt to guess the chart type, but for
                 * more complex charts it is recommended to specify this property for
                 * clarity.
                 *
                 * @type      {string}
                 * @since     5.0.0
                 * @apioption accessibility.typeDescription
                 */
                /**
                 * Options for descriptions of individual data points.
                 *
                 * @since 8.0.0
                 * @apioption accessibility.point
                 */
                /**
                 * Date format to use for points on datetime axes when describing them
                 * to screen reader users.
                 *
                 * Defaults to the same format as in tooltip.
                 *
                 * For an overview of the replacement codes, see
                 * [dateFormat](/class-reference/Highcharts#dateFormat).
                 *
                 * @see [dateFormatter](#accessibility.point.dateFormatter)
                 *
                 * @type      {string}
                 * @since 8.0.0
                 * @apioption accessibility.point.dateFormat
                 */
                /**
                 * Formatter function to determine the date/time format used with
                 * points on datetime axes when describing them to screen reader users.
                 * Receives one argument, `point`, referring to the point to describe.
                 * Should return a date format string compatible with
                 * [dateFormat](/class-reference/Highcharts#dateFormat).
                 *
                 * @see [dateFormat](#accessibility.point.dateFormat)
                 *
                 * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Point>}
                 * @since 8.0.0
                 * @apioption accessibility.point.dateFormatter
                 */
                /**
                 * Prefix to add to the values in the point descriptions. Uses
                 * [tooltip.valuePrefix](#tooltip.valuePrefix) if not defined.
                 *
                 * @type        {string}
                 * @since 8.0.0
                 * @apioption   accessibility.point.valuePrefix
                 */
                /**
                 * Suffix to add to the values in the point descriptions. Uses
                 * [tooltip.valueSuffix](#tooltip.valueSuffix) if not defined.
                 *
                 * @type        {string}
                 * @since 8.0.0
                 * @apioption   accessibility.point.valueSuffix
                 */
                /**
                 * Decimals to use for the values in the point descriptions. Uses
                 * [tooltip.valueDecimals](#tooltip.valueDecimals) if not defined.
                 *
                 * @type        {number}
                 * @since 8.0.0
                 * @apioption   accessibility.point.valueDecimals
                 */
                /**
                 * Formatter function to use instead of the default for point
                 * descriptions.
                 * Receives one argument, `point`, referring to the point to describe.
                 * Should return a string with the description of the point for a screen
                 * reader user. If `false` is returned, the default formatter will be
                 * used for that point.
                 *
                 * @see [point.accessibility.description](#series.line.data.accessibility.description)
                 *
                 * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Point>}
                 * @since 8.0.0
                 * @apioption accessibility.point.descriptionFormatter
                 */
                /**
                 * Options for keyboard navigation.
                 *
                 * @declare Highcharts.KeyboardNavigationOptionsObject
                 * @since   5.0.0
                 */
                keyboardNavigation: {
                    /**
                     * Enable keyboard navigation for the chart.
                     *
                     * @since 5.0.0
                     */
                    enabled: true,
                    /**
                     * Options for the focus border drawn around elements while
                     * navigating through them.
                     *
                     * @sample highcharts/accessibility/custom-focus
                     *         Custom focus ring
                     *
                     * @declare Highcharts.KeyboardNavigationFocusBorderOptionsObject
                     * @since   6.0.3
                     */
                    focusBorder: {
                        /**
                         * Enable/disable focus border for chart.
                         *
                         * @since 6.0.3
                         */
                        enabled: true,
                        /**
                         * Hide the browser's default focus indicator.
                         *
                         * @since 6.0.4
                         */
                        hideBrowserFocusOutline: true,
                        /**
                         * Style options for the focus border drawn around elements
                         * while navigating through them. Note that some browsers in
                         * addition draw their own borders for focused elements. These
                         * automatic borders can not be styled by Highcharts.
                         *
                         * In styled mode, the border is given the
                         * `.highcharts-focus-border` class.
                         *
                         * @type    {Highcharts.CSSObject}
                         * @since   6.0.3
                         */
                        style: {
                            /** @internal */
                            color: '#335cad',
                            /** @internal */
                            lineWidth: 2,
                            /** @internal */
                            borderRadius: 3
                        },
                        /**
                         * Focus border margin around the elements.
                         *
                         * @since 6.0.3
                         */
                        margin: 2
                    },
                    /**
                     * Order of tab navigation in the chart. Determines which elements
                     * are tabbed to first. Available elements are: `series`, `zoom`,
                     * `rangeSelector`, `chartMenu`, `legend`. In addition, any custom
                     * components can be added here.
                     *
                     * @type  {Array<string>}
                     * @since 7.1.0
                     */
                    order: ['series', 'zoom', 'rangeSelector', 'legend', 'chartMenu'],
                    /**
                     * Whether or not to wrap around when reaching the end of arrow-key
                     * navigation for an element in the chart.
                     * @since 7.1.0
                     */
                    wrapAround: true,
                    /**
                     * Options for the keyboard navigation of data points and series.
                     *
                     * @declare Highcharts.KeyboardNavigationSeriesNavigationOptionsObject
                     * @since 8.0.0
                     */
                    seriesNavigation: {
                        /**
                         * Set the keyboard navigation mode for the chart. Can be
                         * "normal" or "serialize". In normal mode, left/right arrow
                         * keys move between points in a series, while up/down arrow
                         * keys move between series. Up/down navigation acts
                         * intelligently to figure out which series makes sense to move
                         * to from any given point.
                         *
                         * In "serialize" mode, points are instead navigated as a single
                         * list. Left/right behaves as in "normal" mode. Up/down arrow
                         * keys will behave like left/right. This can be useful for
                         * unifying navigation behavior with/without screen readers
                         * enabled.
                         *
                         * @type       {string}
                         * @default    normal
                         * @since 8.0.0
                         * @validvalue ["normal", "serialize"]
                         * @apioption  accessibility.keyboardNavigation.seriesNavigation.mode
                         */
                        /**
                         * Skip null points when navigating through points with the
                         * keyboard.
                         *
                         * @since 8.0.0
                         */
                        skipNullPoints: true,
                        /**
                         * When a series contains more points than this, we no longer
                         * allow keyboard navigation for it.
                         *
                         * Set to `false` to disable.
                         *
                         * @type  {boolean|number}
                         * @since 8.0.0
                         */
                        pointNavigationEnabledThreshold: false
                    }
                },
                /**
                 * Options for announcing new data to screen reader users. Useful
                 * for dynamic data applications and drilldown.
                 *
                 * Keep in mind that frequent announcements will not be useful to
                 * users, as they won't have time to explore the new data. For these
                 * applications, consider making snapshots of the data accessible, and
                 * do the announcements in batches.
                 *
                 * @declare Highcharts.AccessibilityAnnounceNewDataOptionsObject
                 * @since   7.1.0
                 */
                announceNewData: {
                    /**
                     * Optional formatter callback for the announcement. Receives
                     * up to three arguments. The first argument is always an array
                     * of all series that received updates. If an announcement is
                     * already queued, the series that received updates for that
                     * announcement are also included in this array. The second
                     * argument is provided if `chart.addSeries` was called, and
                     * there is a new series. In that case, this argument is a
                     * reference to the new series. The third argument, similarly,
                     * is provided if `series.addPoint` was called, and there is a
                     * new point. In that case, this argument is a reference to the
                     * new point.
                     *
                     * The function should return a string with the text to announce
                     * to the user. Return empty string to not announce anything.
                     * Return `false` to use the default announcement format.
                     *
                     * @sample highcharts/accessibility/custom-dynamic
                     *         High priority live alerts
                     *
                     * @type      {Highcharts.AccessibilityAnnouncementFormatter}
                     * @apioption accessibility.announceNewData.announcementFormatter
                     */
                    /**
                     * Enable announcing new data to screen reader users
                     * @sample highcharts/accessibility/accessible-dynamic
                     *         Dynamic data accessible
                     */
                    enabled: false,
                    /**
                     * Minimum interval between announcements in milliseconds. If
                     * new data arrives before this amount of time has passed, it is
                     * queued for announcement. If another new data event happens
                     * while an announcement is queued, the queued announcement is
                     * dropped, and the latest announcement is queued instead. Set
                     * to 0 to allow all announcements, but be warned that frequent
                     * announcements are disturbing to users.
                     */
                    minAnnounceInterval: 5000,
                    /**
                     * Choose whether or not the announcements should interrupt the
                     * screen reader. If not enabled, the user will be notified once
                     * idle. It is recommended not to enable this setting unless
                     * there is a specific reason to do so.
                     */
                    interruptUser: false
                }
            },
            /**
             * Accessibility options for a data point.
             *
             * @declare   Highcharts.PointAccessibilityOptionsObject
             * @since     7.1.0
             * @apioption series.line.data.accessibility
             */
            /**
             * Provide a description of the data point, announced to screen readers.
             *
             * @type      {string}
             * @since     7.1.0
             * @apioption series.line.data.accessibility.description
             */
            /**
             * Accessibility options for a series.
             *
             * @declare    Highcharts.SeriesAccessibilityOptionsObject
             * @since      7.1.0
             * @requires   modules/accessibility
             * @apioption  plotOptions.series.accessibility
             */
            /**
             * Enable/disable accessibility functionality for a specific series.
             *
             * @type       {boolean}
             * @since      7.1.0
             * @apioption  plotOptions.series.accessibility.enabled
             */
            /**
             * Provide a description of the series, announced to screen readers.
             *
             * @type       {string}
             * @since      7.1.0
             * @apioption  plotOptions.series.accessibility.description
             */
            /**
             * Formatter function to use instead of the default for point
             * descriptions. Same as `accessibility.point.descriptionFormatter`, but for
             * a single series.
             *
             * @see [accessibility.point.descriptionFormatter](#accessibility.point.descriptionFormatter)
             *
             * @type      {Highcharts.ScreenReaderFormatterCallbackFunction<Highcharts.Point>}
             * @since     7.1.0
             * @apioption plotOptions.series.accessibility.pointDescriptionFormatter
             */
            /**
             * Expose only the series element to screen readers, not its points.
             *
             * @type       {boolean}
             * @since      7.1.0
             * @apioption  plotOptions.series.accessibility.exposeAsGroupOnly
             */
            /**
             * Keyboard navigation for a series
             *
             * @declare    Highcharts.SeriesAccessibilityKeyboardNavigationOptionsObject
             * @since      7.1.0
             * @apioption  plotOptions.series.accessibility.keyboardNavigation
             */
            /**
             * Enable/disable keyboard navigation support for a specific series.
             *
             * @type       {boolean}
             * @since      7.1.0
             * @apioption  plotOptions.series.accessibility.keyboardNavigation.enabled
             */
            /**
             * Accessibility options for an axis. Requires the accessibility module.
             *
             * @declare    Highcharts.AxisAccessibilityOptionsObject
             * @since      7.1.0
             * @requires   modules/accessibility
             * @apioption  xAxis.accessibility
             */
            /**
             * Enable axis accessibility features, including axis information in the
             * screen reader information region. If this is disabled on the xAxis, the
             * x values are not exposed to screen readers for the individual data points
             * by default.
             *
             * @type       {boolean}
             * @since      7.1.0
             * @apioption  xAxis.accessibility.enabled
             */
            /**
             * Description for an axis to expose to screen reader users.
             *
             * @type       {string}
             * @since      7.1.0
             * @apioption  xAxis.accessibility.description
             */
            /**
             * Range description for an axis. Overrides the default range description.
             * Set to empty to disable range description for this axis.
             *
             * @type       {string}
             * @since      7.1.0
             * @apioption  xAxis.accessibility.rangeDescription
             */
            legend: {
                /**
                 * Accessibility options for the legend. Requires the Accessibility
                 * module.
                 *
                 * @since     7.1.0
                 * @requires  modules/accessibility
                 * @apioption legend.accessibility
                 */
                accessibility: {
                    /**
                     * Enable accessibility support for the legend.
                     *
                     * @since     7.1.0
                     * @apioption legend.accessibility.enabled
                     */
                    enabled: true,
                    /**
                     * Options for keyboard navigation for the legend.
                     *
                     * @since     7.1.0
                     * @requires  modules/accessibility
                     * @apioption legend.accessibility.keyboardNavigation
                     */
                    keyboardNavigation: {
                        /**
                         * Enable keyboard navigation for the legend.
                         *
                         * @see [accessibility.keyboardNavigation](#accessibility.keyboardNavigation.enabled)
                         *
                         * @since     7.1.0
                         * @apioption legend.accessibility.keyboardNavigation.enabled
                         */
                        enabled: true
                    }
                }
            },
            exporting: {
                /**
                 * Accessibility options for the exporting menu. Requires the
                 * Accessibility module.
                 *
                 * @since     7.1.0
                 * @requires  modules/accessibility
                 * @apioption exporting.accessibility
                 */
                accessibility: {
                    /**
                     * Enable accessibility support for the export menu.
                     *
                     * @since     7.1.0
                     * @apioption exporting.accessibility.enabled
                     */
                    enabled: true
                }
            }
        };

        return options;
    });
    _registerModule(_modules, 'modules/accessibility/options/langOptions.js', [], function () {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Default lang/i18n options for accessibility.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var langOptions = {
            /**
             * Configure the accessibility strings in the chart. Requires the
             * [accessibility module](https://code.highcharts.com/modules/accessibility.js)
             * to be loaded. For a description of the module and information on its
             * features, see
             * [Highcharts Accessibility](https://www.highcharts.com/docs/chart-concepts/accessibility).
             *
             * For more dynamic control over the accessibility functionality, see
             * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter),
             * [accessibility.seriesDescriptionFormatter](#accessibility.seriesDescriptionFormatter),
             * and
             * [accessibility.screenReaderSectionFormatter](#accessibility.screenReaderSectionFormatter).
             *
             * @since        6.0.6
             * @optionparent lang.accessibility
             */
            accessibility: {
                defaultChartTitle: 'Chart',
                chartContainerLabel: '{title}. Highcharts interactive chart.',
                svgContainerLabel: 'Interactive chart',
                drillUpButton: '{buttonText}',
                credits: 'Chart credits: {creditsStr}',
                /**
                 * Thousands separator to use when formatting numbers for screen
                 * readers. Note that many screen readers will not handle space as a
                 * thousands separator, and will consider "11 700" as two numbers.
                 *
                 * Set to `null` to use the separator defined in
                 * [lang.thousandsSep](lang.thousandsSep).
                 *
                 * @since 7.1.0
                 */
                thousandsSep: ',',
                /**
                 * Title element text for the chart SVG element. Leave this
                 * empty to disable adding the title element. Browsers will display
                 * this content when hovering over elements in the chart. Assistive
                 * technology may use this element to label the chart.
                 *
                 * @since 6.0.8
                 */
                svgContainerTitle: '',
                /**
                 * Set a label on the container wrapping the SVG.
                 *
                 * @see [chartContainerLabel](#lang.accessibility.chartContainerLabel)
                 *
                 * @since 8.0.0
                 */
                graphicContainerLabel: '',
                /**
                 * Language options for the screen reader information sections added
                 * before and after the charts.
                 *
                 * @since 8.0.0
                 */
                screenReaderSection: {
                    beforeRegionLabel: 'Chart screen reader information.',
                    afterRegionLabel: '',
                    /**
                     * Label for the end of the chart. Announced by screen readers.
                     *
                     * @since 8.0.0
                     */
                    endOfChartMarker: 'End of interactive chart.'
                },
                /**
                 * Language options for accessibility of the legend.
                 *
                 * @since 8.0.0
                 */
                legend: {
                    legendLabel: 'Toggle series visibility',
                    legendItem: 'Toggle visibility of {itemName}'
                },
                /**
                 * Chart and map zoom accessibility language options.
                 *
                 * @since 8.0.0
                 */
                zoom: {
                    mapZoomIn: 'Zoom chart',
                    mapZoomOut: 'Zoom out chart',
                    resetZoomButton: 'Reset zoom'
                },
                /**
                 * Range selector language options for accessibility.
                 *
                 * @since 8.0.0
                 */
                rangeSelector: {
                    minInputLabel: 'Select start date.',
                    maxInputLabel: 'Select end date.',
                    buttonText: 'Select range {buttonText}'
                },
                /**
                 * Accessibility language options for the data table.
                 *
                 * @since 8.0.0
                 */
                table: {
                    viewAsDataTableButtonText: 'View as data table. {chartTitle}',
                    tableSummary: 'Table representation of chart.'
                },
                /**
                 * Default announcement for new data in charts. If addPoint or
                 * addSeries is used, and only one series/point is added, the
                 * `newPointAnnounce` and `newSeriesAnnounce` strings are used.
                 * The `...Single` versions will be used if there is only one chart
                 * on the page, and the `...Multiple` versions will be used if there
                 * are multiple charts on the page. For all other new data events,
                 * the `newDataAnnounce` string will be used.
                 *
                 * @since 7.1.0
                 */
                announceNewData: {
                    newDataAnnounce: 'Updated data for chart {chartTitle}',
                    newSeriesAnnounceSingle: 'New data series: {seriesDesc}',
                    newPointAnnounceSingle: 'New data point: {pointDesc}',
                    newSeriesAnnounceMultiple: 'New data series in chart {chartTitle}: {seriesDesc}',
                    newPointAnnounceMultiple: 'New data point in chart {chartTitle}: {pointDesc}'
                },
                /**
                 * Descriptions of lesser known series types. The relevant
                 * description is added to the screen reader information region
                 * when these series types are used.
                 *
                 * @since 6.0.6
                 */
                seriesTypeDescriptions: {
                    boxplot: 'Box plot charts are typically used to display ' +
                        'groups of statistical data. Each data point in the ' +
                        'chart can have up to 5 values: minimum, lower quartile, ' +
                        'median, upper quartile, and maximum.',
                    arearange: 'Arearange charts are line charts displaying a ' +
                        'range between a lower and higher value for each point.',
                    areasplinerange: 'These charts are line charts displaying a ' +
                        'range between a lower and higher value for each point.',
                    bubble: 'Bubble charts are scatter charts where each data ' +
                        'point also has a size value.',
                    columnrange: 'Columnrange charts are column charts ' +
                        'displaying a range between a lower and higher value for ' +
                        'each point.',
                    errorbar: 'Errorbar series are used to display the ' +
                        'variability of the data.',
                    funnel: 'Funnel charts are used to display reduction of data ' +
                        'in stages.',
                    pyramid: 'Pyramid charts consist of a single pyramid with ' +
                        'item heights corresponding to each point value.',
                    waterfall: 'A waterfall chart is a column chart where each ' +
                        'column contributes towards a total end value.'
                },
                /**
                 * Chart type description strings. This is added to the chart
                 * information region.
                 *
                 * If there is only a single series type used in the chart, we use
                 * the format string for the series type, or default if missing.
                 * There is one format string for cases where there is only a single
                 * series in the chart, and one for multiple series of the same
                 * type.
                 *
                 * @since 6.0.6
                 */
                chartTypes: {
                    /* eslint-disable max-len */
                    emptyChart: 'Empty chart',
                    mapTypeDescription: 'Map of {mapTitle} with {numSeries} data series.',
                    unknownMap: 'Map of unspecified region with {numSeries} data series.',
                    combinationChart: 'Combination chart with {numSeries} data series.',
                    defaultSingle: 'Chart with {numPoints} data {#plural(numPoints, points, point)}.',
                    defaultMultiple: 'Chart with {numSeries} data series.',
                    splineSingle: 'Line chart with {numPoints} data {#plural(numPoints, points, point)}.',
                    splineMultiple: 'Line chart with {numSeries} lines.',
                    lineSingle: 'Line chart with {numPoints} data {#plural(numPoints, points, point)}.',
                    lineMultiple: 'Line chart with {numSeries} lines.',
                    columnSingle: 'Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.',
                    columnMultiple: 'Bar chart with {numSeries} data series.',
                    barSingle: 'Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.',
                    barMultiple: 'Bar chart with {numSeries} data series.',
                    pieSingle: 'Pie chart with {numPoints} {#plural(numPoints, slices, slice)}.',
                    pieMultiple: 'Pie chart with {numSeries} pies.',
                    scatterSingle: 'Scatter chart with {numPoints} {#plural(numPoints, points, point)}.',
                    scatterMultiple: 'Scatter chart with {numSeries} data series.',
                    boxplotSingle: 'Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.',
                    boxplotMultiple: 'Boxplot with {numSeries} data series.',
                    bubbleSingle: 'Bubble chart with {numPoints} {#plural(numPoints, bubbles, bubble)}.',
                    bubbleMultiple: 'Bubble chart with {numSeries} data series.'
                },
                /**
                 * Axis description format strings.
                 *
                 * @since 6.0.6
                 */
                axis: {
                    /* eslint-disable max-len */
                    xAxisDescriptionSingular: 'The chart has 1 X axis displaying {names[0]}. {ranges[0]}',
                    xAxisDescriptionPlural: 'The chart has {numAxes} X axes displaying {#each(names, -1) }and {names[-1]}.',
                    yAxisDescriptionSingular: 'The chart has 1 Y axis displaying {names[0]}. {ranges[0]}',
                    yAxisDescriptionPlural: 'The chart has {numAxes} Y axes displaying {#each(names, -1) }and {names[-1]}.',
                    timeRangeDays: 'Range: {range} days.',
                    timeRangeHours: 'Range: {range} hours.',
                    timeRangeMinutes: 'Range: {range} minutes.',
                    timeRangeSeconds: 'Range: {range} seconds.',
                    rangeFromTo: 'Range: {rangeFrom} to {rangeTo}.',
                    rangeCategories: 'Range: {numCategories} categories.'
                },
                /**
                 * Exporting menu format strings for accessibility module.
                 *
                 * @since 6.0.6
                 */
                exporting: {
                    chartMenuLabel: 'Chart menu',
                    menuButtonLabel: 'View chart menu',
                    exportRegionLabel: 'Chart menu'
                },
                /**
                 * Lang configuration for different series types. For more dynamic
                 * control over the series element descriptions, see
                 * [accessibility.seriesDescriptionFormatter](#accessibility.seriesDescriptionFormatter).
                 *
                 * @since 6.0.6
                 */
                series: {
                    /**
                     * Lang configuration for the series main summary. Each series
                     * type has two modes:
                     *
                     * 1. This series type is the only series type used in the
                     *    chart
                     *
                     * 2. This is a combination chart with multiple series types
                     *
                     * If a definition does not exist for the specific series type
                     * and mode, the 'default' lang definitions are used.
                     *
                     * @since 6.0.6
                     */
                    summary: {
                        /* eslint-disable max-len */
                        'default': '{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.',
                        defaultCombination: '{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.',
                        line: '{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.',
                        lineCombination: '{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.',
                        spline: '{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.',
                        splineCombination: '{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.',
                        column: '{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.',
                        columnCombination: '{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.',
                        bar: '{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.',
                        barCombination: '{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.',
                        pie: '{name}, pie {ix} of {numSeries} with {numPoints} {#plural(numPoints, slices, slice)}.',
                        pieCombination: '{name}, series {ix} of {numSeries}. Pie with {numPoints} {#plural(numPoints, slices, slice)}.',
                        scatter: '{name}, scatter plot {ix} of {numSeries} with {numPoints} {#plural(numPoints, points, point)}.',
                        scatterCombination: '{name}, series {ix} of {numSeries}, scatter plot with {numPoints} {#plural(numPoints, points, point)}.',
                        boxplot: '{name}, boxplot {ix} of {numSeries} with {numPoints} {#plural(numPoints, boxes, box)}.',
                        boxplotCombination: '{name}, series {ix} of {numSeries}. Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.',
                        bubble: '{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.',
                        bubbleCombination: '{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}.',
                        map: '{name}, map {ix} of {numSeries} with {numPoints} {#plural(numPoints, areas, area)}.',
                        mapCombination: '{name}, series {ix} of {numSeries}. Map with {numPoints} {#plural(numPoints, areas, area)}.',
                        mapline: '{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.',
                        maplineCombination: '{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.',
                        mapbubble: '{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.',
                        mapbubbleCombination: '{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}.'
                    },
                    /**
                     * User supplied description text. This is added after the main
                     * summary if present.
                     *
                     * @since 6.0.6
                     */
                    description: '{description}',
                    /**
                     * xAxis description for series if there are multiple xAxes in
                     * the chart.
                     *
                     * @since 6.0.6
                     */
                    xAxisDescription: 'X axis, {name}',
                    /**
                     * yAxis description for series if there are multiple yAxes in
                     * the chart.
                     *
                     * @since 6.0.6
                     */
                    yAxisDescription: 'Y axis, {name}',
                    /**
                     * Description for the value of null points.
                     *
                     * @since 8.0.0
                     */
                    nullPointValue: 'No value'
                }
            }
        };

        return langOptions;
    });
    _registerModule(_modules, 'modules/accessibility/options/deprecatedOptions.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Default options for accessibility.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        /* eslint-disable max-len */
        /*
         *  List of deprecated options:
         *
         *  chart.description -> accessibility.description
         *  chart.typeDescription -> accessibility.typeDescription
         *  series.description -> series.accessibility.description
         *  series.exposeElementToA11y -> series.accessibility.exposeAsGroupOnly
         *  series.pointDescriptionFormatter ->
         *      series.accessibility.pointDescriptionFormatter
         *  series.skipKeyboardNavigation ->
         *      series.accessibility.keyboardNavigation.enabled
         *  point.description -> point.accessibility.description !!!! WARNING: No longer deprecated and handled, removed for HC8.
         *  axis.description -> axis.accessibility.description
         *
         *  accessibility.pointDateFormat -> accessibility.point.dateFormat
         *  accessibility.addTableShortcut -> Handled by screenReaderSection.beforeChartFormat
         *  accessibility.pointDateFormatter -> accessibility.point.dateFormatter
         *  accessibility.pointDescriptionFormatter -> accessibility.point.descriptionFormatter
         *  accessibility.pointDescriptionThreshold -> accessibility.series.pointDescriptionEnabledThreshold
         *  accessibility.pointNavigationThreshold -> accessibility.keyboardNavigation.seriesNavigation.pointNavigationEnabledThreshold
         *  accessibility.pointValueDecimals -> accessibility.point.valueDecimals
         *  accessibility.pointValuePrefix -> accessibility.point.valuePrefix
         *  accessibility.pointValueSuffix -> accessibility.point.valueSuffix
         *  accessibility.screenReaderSectionFormatter -> accessibility.screenReaderSection.beforeChartFormatter
         *  accessibility.describeSingleSeries -> accessibility.series.describeSingleSeries
         *  accessibility.seriesDescriptionFormatter -> accessibility.series.descriptionFormatter
         *  accessibility.onTableAnchorClick -> accessibility.screenReaderSection.onViewDataTableClick
         *  accessibility.axisRangeDateFormat -> accessibility.screenReaderSection.axisRangeDateFormat
         *  accessibility.keyboardNavigation.skipNullPoints -> accessibility.keyboardNavigation.seriesNavigation.skipNullPoints
         *  accessibility.keyboardNavigation.mode -> accessibility.keyboardNavigation.seriesNavigation.mode
         *
         *  lang.accessibility.chartHeading -> no longer used, remove
         *  lang.accessibility.legendItem -> lang.accessibility.legend.legendItem
         *  lang.accessibility.legendLabel -> lang.accessibility.legend.legendLabel
         *  lang.accessibility.mapZoomIn -> lang.accessibility.zoom.mapZoomIn
         *  lang.accessibility.mapZoomOut -> lang.accessibility.zoom.mapZoomOut
         *  lang.accessibility.resetZoomButton -> lang.accessibility.zoom.resetZoomButton
         *  lang.accessibility.screenReaderRegionLabel -> lang.accessibility.screenReaderSection.beforeRegionLabel
         *  lang.accessibility.rangeSelectorButton -> lang.accessibility.rangeSelector.buttonText
         *  lang.accessibility.rangeSelectorMaxInput -> lang.accessibility.rangeSelector.maxInputLabel
         *  lang.accessibility.rangeSelectorMinInput -> lang.accessibility.rangeSelector.minInputLabel
         *  lang.accessibility.svgContainerEnd -> lang.accessibility.screenReaderSection.endOfChartMarker
         *  lang.accessibility.viewAsDataTable -> lang.accessibility.table.viewAsDataTableButtonText
         *  lang.accessibility.tableSummary -> lang.accessibility.table.tableSummary
         *
         */
        /* eslint-enable max-len */
        var error = H.error;
        var pick = U.pick;
        /* eslint-disable valid-jsdoc */
        /**
         * Warn user that a deprecated option was used.
         * @private
         * @param {Highcharts.Chart} chart
         * @param {string} oldOption
         * @param {string} newOption
         * @return {void}
         */
        function warn(chart, oldOption, newOption) {
            error('Highcharts: Deprecated option ' + oldOption +
                ' used. This will be removed from future versions of Highcharts. Use ' +
                newOption + ' instead.', false, chart);
        }
        /**
         * Set a new option on a root prop, where the option is defined as an array of
         * suboptions.
         * @private
         * @param root
         * @param {Array<string>} optionAsArray
         * @param {*} val
         * @return {void}
         */
        function traverseSetOption(root, optionAsArray, val) {
            var opt = root, prop, i = 0;
            for (; i < optionAsArray.length - 1; ++i) {
                prop = optionAsArray[i];
                opt = opt[prop] = pick(opt[prop], {});
            }
            opt[optionAsArray[optionAsArray.length - 1]] = val;
        }
        /**
         * If we have a clear root option node for old and new options and a mapping
         * between, we can use this generic function for the copy and warn logic.
         */
        function deprecateFromOptionsMap(chart, rootOldAsArray, rootNewAsArray, mapToNewOptions) {
            /**
             * @private
             */
            function getChildProp(root, propAsArray) {
                return propAsArray.reduce(function (acc, cur) {
                    return acc[cur];
                }, root);
            }
            var rootOld = getChildProp(chart.options, rootOldAsArray), rootNew = getChildProp(chart.options, rootNewAsArray);
            Object.keys(mapToNewOptions).forEach(function (oldOptionKey) {
                var val = rootOld[oldOptionKey];
                if (typeof val !== 'undefined') {
                    traverseSetOption(rootNew, mapToNewOptions[oldOptionKey], val);
                    warn(chart, rootOldAsArray.join('.') + '.' + oldOptionKey, rootNewAsArray.join('.') + '.' +
                        mapToNewOptions[oldOptionKey].join('.'));
                }
            });
        }
        /**
         * @private
         */
        function copyDeprecatedChartOptions(chart) {
            var chartOptions = chart.options.chart || {}, a11yOptions = chart.options.accessibility || {};
            ['description', 'typeDescription'].forEach(function (prop) {
                if (chartOptions[prop]) {
                    a11yOptions[prop] = chartOptions[prop];
                    warn(chart, 'chart.' + prop, 'accessibility.' + prop);
                }
            });
        }
        /**
         * @private
         */
        function copyDeprecatedAxisOptions(chart) {
            chart.axes.forEach(function (axis) {
                var opts = axis.options;
                if (opts && opts.description) {
                    opts.accessibility = opts.accessibility || {};
                    opts.accessibility.description = opts.description;
                    warn(chart, 'axis.description', 'axis.accessibility.description');
                }
            });
        }
        /**
         * @private
         */
        function copyDeprecatedSeriesOptions(chart) {
            // Map of deprecated series options. New options are defined as
            // arrays of paths under series.options.
            var oldToNewSeriesOptions = {
                description: ['accessibility', 'description'],
                exposeElementToA11y: ['accessibility', 'exposeAsGroupOnly'],
                pointDescriptionFormatter: [
                    'accessibility', 'pointDescriptionFormatter'
                ],
                skipKeyboardNavigation: [
                    'accessibility', 'keyboardNavigation', 'enabled'
                ]
            };
            chart.series.forEach(function (series) {
                // Handle series wide options
                Object.keys(oldToNewSeriesOptions).forEach(function (oldOption) {
                    var optionVal = series.options[oldOption];
                    if (typeof optionVal !== 'undefined') {
                        // Set the new option
                        traverseSetOption(series.options, oldToNewSeriesOptions[oldOption], 
                        // Note that skipKeyboardNavigation has inverted option
                        // value, since we set enabled rather than disabled
                        oldOption === 'skipKeyboardNavigation' ?
                            !optionVal : optionVal);
                        warn(chart, 'series.' + oldOption, 'series.' +
                            oldToNewSeriesOptions[oldOption].join('.'));
                    }
                });
            });
        }
        /**
         * @private
         */
        function copyDeprecatedTopLevelAccessibilityOptions(chart) {
            deprecateFromOptionsMap(chart, ['accessibility'], ['accessibility'], {
                pointDateFormat: ['point', 'dateFormat'],
                pointDateFormatter: ['point', 'dateFormatter'],
                pointDescriptionFormatter: ['point', 'descriptionFormatter'],
                pointDescriptionThreshold: ['series',
                    'pointDescriptionEnabledThreshold'],
                pointNavigationThreshold: ['keyboardNavigation', 'seriesNavigation',
                    'pointNavigationEnabledThreshold'],
                pointValueDecimals: ['point', 'valueDecimals'],
                pointValuePrefix: ['point', 'valuePrefix'],
                pointValueSuffix: ['point', 'valueSuffix'],
                screenReaderSectionFormatter: ['screenReaderSection',
                    'beforeChartFormatter'],
                describeSingleSeries: ['series', 'describeSingleSeries'],
                seriesDescriptionFormatter: ['series', 'descriptionFormatter'],
                onTableAnchorClick: ['screenReaderSection', 'onViewDataTableClick'],
                axisRangeDateFormat: ['screenReaderSection', 'axisRangeDateFormat']
            });
        }
        /**
         * @private
         */
        function copyDeprecatedKeyboardNavigationOptions(chart) {
            deprecateFromOptionsMap(chart, ['accessibility', 'keyboardNavigation'], ['accessibility', 'keyboardNavigation', 'seriesNavigation'], {
                skipNullPoints: ['skipNullPoints'],
                mode: ['mode']
            });
        }
        /**
         * @private
         */
        function copyDeprecatedLangOptions(chart) {
            deprecateFromOptionsMap(chart, ['lang', 'accessibility'], ['lang', 'accessibility'], {
                legendItem: ['legend', 'legendItem'],
                legendLabel: ['legend', 'legendLabel'],
                mapZoomIn: ['zoom', 'mapZoomIn'],
                mapZoomOut: ['zoom', 'mapZoomOut'],
                resetZoomButton: ['zoom', 'resetZoomButton'],
                screenReaderRegionLabel: ['screenReaderSection',
                    'beforeRegionLabel'],
                rangeSelectorButton: ['rangeSelector', 'buttonText'],
                rangeSelectorMaxInput: ['rangeSelector', 'maxInputLabel'],
                rangeSelectorMinInput: ['rangeSelector', 'minInputLabel'],
                svgContainerEnd: ['screenReaderSection', 'endOfChartMarker'],
                viewAsDataTable: ['table', 'viewAsDataTableButtonText'],
                tableSummary: ['table', 'tableSummary']
            });
        }
        /**
         * Copy options that are deprecated over to new options. Logs warnings to
         * console if deprecated options are used.
         *
         * @private
         */
        function copyDeprecatedOptions(chart) {
            copyDeprecatedChartOptions(chart);
            copyDeprecatedAxisOptions(chart);
            if (chart.series) {
                copyDeprecatedSeriesOptions(chart);
            }
            copyDeprecatedTopLevelAccessibilityOptions(chart);
            copyDeprecatedKeyboardNavigationOptions(chart);
            copyDeprecatedLangOptions(chart);
        }

        return copyDeprecatedOptions;
    });
    _registerModule(_modules, 'modules/accessibility/a11y-i18n.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
        /* *
         *
         *  Accessibility module - internationalization support
         *
         *  (c) 2010-2019 Highsoft AS
         *  Author: Øystein Moseng
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var pick = U.pick;
        /* eslint-disable valid-jsdoc */
        /**
         * String trim that works for IE6-8 as well.
         *
         * @private
         * @function stringTrim
         *
         * @param {string} str
         *        The input string
         *
         * @return {string}
         *         The trimmed string
         */
        function stringTrim(str) {
            return str.trim && str.trim() || str.replace(/^\s+|\s+$/g, '');
        }
        /**
         * i18n utility function. Format a single array or plural statement in a format
         * string. If the statement is not an array or plural statement, returns the
         * statement within brackets. Invalid array statements return an empty string.
         *
         * @private
         * @function formatExtendedStatement
         *
         * @param {string} statement
         *
         * @param {Highcharts.Dictionary<*>} ctx
         *        Context to apply to the format string.
         *
         * @return {string}
         */
        function formatExtendedStatement(statement, ctx) {
            var eachStart = statement.indexOf('#each('), pluralStart = statement.indexOf('#plural('), indexStart = statement.indexOf('['), indexEnd = statement.indexOf(']'), arr, result;
            // Dealing with an each-function?
            if (eachStart > -1) {
                var eachEnd = statement.slice(eachStart).indexOf(')') + eachStart, preEach = statement.substring(0, eachStart), postEach = statement.substring(eachEnd + 1), eachStatement = statement.substring(eachStart + 6, eachEnd), eachArguments = eachStatement.split(','), lenArg = Number(eachArguments[1]), len;
                result = '';
                arr = ctx[eachArguments[0]];
                if (arr) {
                    lenArg = isNaN(lenArg) ? arr.length : lenArg;
                    len = lenArg < 0 ?
                        arr.length + lenArg :
                        Math.min(lenArg, arr.length); // Overshoot
                    // Run through the array for the specified length
                    for (var i = 0; i < len; ++i) {
                        result += preEach + arr[i] + postEach;
                    }
                }
                return result.length ? result : '';
            }
            // Dealing with a plural-function?
            if (pluralStart > -1) {
                var pluralEnd = statement.slice(pluralStart).indexOf(')') + pluralStart, pluralStatement = statement.substring(pluralStart + 8, pluralEnd), pluralArguments = pluralStatement.split(','), num = Number(ctx[pluralArguments[0]]);
                switch (num) {
                    case 0:
                        result = pick(pluralArguments[4], pluralArguments[1]);
                        break;
                    case 1:
                        result = pick(pluralArguments[2], pluralArguments[1]);
                        break;
                    case 2:
                        result = pick(pluralArguments[3], pluralArguments[1]);
                        break;
                    default:
                        result = pluralArguments[1];
                }
                return result ? stringTrim(result) : '';
            }
            // Array index
            if (indexStart > -1) {
                var arrayName = statement.substring(0, indexStart), ix = Number(statement.substring(indexStart + 1, indexEnd)), val;
                arr = ctx[arrayName];
                if (!isNaN(ix) && arr) {
                    if (ix < 0) {
                        val = arr[arr.length + ix];
                        // Handle negative overshoot
                        if (typeof val === 'undefined') {
                            val = arr[0];
                        }
                    }
                    else {
                        val = arr[ix];
                        // Handle positive overshoot
                        if (typeof val === 'undefined') {
                            val = arr[arr.length - 1];
                        }
                    }
                }
                return typeof val !== 'undefined' ? val : '';
            }
            // Standard substitution, delegate to H.format or similar
            return '{' + statement + '}';
        }
        /**
         * i18n formatting function. Extends Highcharts.format() functionality by also
         * handling arrays and plural conditionals. Arrays can be indexed as follows:
         *
         * - Format: 'This is the first index: {myArray[0]}. The last: {myArray[-1]}.'
         *
         * - Context: { myArray: [0, 1, 2, 3, 4, 5] }
         *
         * - Result: 'This is the first index: 0. The last: 5.'
         *
         *
         * They can also be iterated using the #each() function. This will repeat the
         * contents of the bracket expression for each element. Example:
         *
         * - Format: 'List contains: {#each(myArray)cm }'
         *
         * - Context: { myArray: [0, 1, 2] }
         *
         * - Result: 'List contains: 0cm 1cm 2cm '
         *
         *
         * The #each() function optionally takes a length parameter. If positive, this
         * parameter specifies the max number of elements to iterate through. If
         * negative, the function will subtract the number from the length of the array.
         * Use this to stop iterating before the array ends. Example:
         *
         * - Format: 'List contains: {#each(myArray, -1) }and {myArray[-1]}.'
         *
         * - Context: { myArray: [0, 1, 2, 3] }
         *
         * - Result: 'List contains: 0, 1, 2, and 3.'
         *
         *
         * Use the #plural() function to pick a string depending on whether or not a
         * context object is 1. Arguments are #plural(obj, plural, singular). Example:
         *
         * - Format: 'Has {numPoints} {#plural(numPoints, points, point}.'
         *
         * - Context: { numPoints: 5 }
         *
         * - Result: 'Has 5 points.'
         *
         *
         * Optionally there are additional parameters for dual and none: #plural(obj,
         * plural, singular, dual, none). Example:
         *
         * - Format: 'Has {#plural(numPoints, many points, one point, two points,
         *   none}.'
         *
         * - Context: { numPoints: 2 }
         *
         * - Result: 'Has two points.'
         *
         *
         * The dual or none parameters will take precedence if they are supplied.
         *
         * @requires modules/accessibility
         *
         * @function Highcharts.i18nFormat
         *
         * @param {string} formatString
         *        The string to format.
         *
         * @param {Highcharts.Dictionary<*>} context
         *        Context to apply to the format string.
         *
         * @param {Highcharts.Chart} chart
         *        A `Chart` instance with a time object and numberFormatter, passed on
         *        to H.format().
         *
         * @return {string}
         *         The formatted string.
         */
        H.i18nFormat = function (formatString, context, chart) {
            var getFirstBracketStatement = function (sourceStr, offset) {
                var str = sourceStr.slice(offset || 0), startBracket = str.indexOf('{'), endBracket = str.indexOf('}');
                if (startBracket > -1 && endBracket > startBracket) {
                    return {
                        statement: str.substring(startBracket + 1, endBracket),
                        begin: offset + startBracket + 1,
                        end: offset + endBracket
                    };
                }
            }, tokens = [], bracketRes, constRes, cursor = 0;
            // Tokenize format string into bracket statements and constants
            do {
                bracketRes = getFirstBracketStatement(formatString, cursor);
                constRes = formatString.substring(cursor, bracketRes && bracketRes.begin - 1);
                // If we have constant content before this bracket statement, add it
                if (constRes.length) {
                    tokens.push({
                        value: constRes,
                        type: 'constant'
                    });
                }
                // Add the bracket statement
                if (bracketRes) {
                    tokens.push({
                        value: bracketRes.statement,
                        type: 'statement'
                    });
                }
                cursor = bracketRes ? bracketRes.end + 1 : cursor + 1;
            } while (bracketRes);
            // Perform the formatting. The formatArrayStatement function returns the
            // statement in brackets if it is not an array statement, which means it
            // gets picked up by H.format below.
            tokens.forEach(function (token) {
                if (token.type === 'statement') {
                    token.value = formatExtendedStatement(token.value, context);
                }
            });
            // Join string back together and pass to H.format to pick up non-array
            // statements.
            return H.format(tokens.reduce(function (acc, cur) {
                return acc + cur.value;
            }, ''), context, chart);
        };
        /**
         * Apply context to a format string from lang options of the chart.
         *
         * @requires modules/accessibility
         *
         * @function Highcharts.Chart#langFormat
         *
         * @param {string} langKey
         *        Key (using dot notation) into lang option structure.
         *
         * @param {Highcharts.Dictionary<*>} context
         *        Context to apply to the format string.
         *
         * @return {string}
         *         The formatted string.
         */
        H.Chart.prototype.langFormat = function (langKey, context) {
            var keys = langKey.split('.'), formatString = this.options.lang, i = 0;
            for (; i < keys.length; ++i) {
                formatString = formatString && formatString[keys[i]];
            }
            return typeof formatString === 'string' ?
                H.i18nFormat(formatString, context, this) : '';
        };

    });
    _registerModule(_modules, 'modules/accessibility/focusBorder.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Extend SVG and Chart classes with focus border capabilities.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var addEvent = H.addEvent;
        var extend = U.extend, pick = U.pick;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /*
         * Add focus border functionality to SVGElements. Draws a new rect on top of
         * element around its bounding box. This is used by multiple components.
         */
        extend(H.SVGElement.prototype, {
            /**
             * @private
             * @function Highcharts.SVGElement#addFocusBorder
             *
             * @param {number} margin
             *
             * @param {Highcharts.CSSObject} style
             */
            addFocusBorder: function (margin, style) {
                // Allow updating by just adding new border
                if (this.focusBorder) {
                    this.removeFocusBorder();
                }
                // Add the border rect
                var bb = this.getBBox(), pad = pick(margin, 3);
                bb.x += this.translateX ? this.translateX : 0;
                bb.y += this.translateY ? this.translateY : 0;
                this.focusBorder = this.renderer.rect(bb.x - pad, bb.y - pad, bb.width + 2 * pad, bb.height + 2 * pad, parseInt((style && style.borderRadius || 0).toString(), 10))
                    .addClass('highcharts-focus-border')
                    .attr({
                    zIndex: 99
                })
                    .add(this.parentGroup);
                if (!this.renderer.styledMode) {
                    this.focusBorder.attr({
                        stroke: style && style.stroke,
                        'stroke-width': style && style.strokeWidth
                    });
                }
            },
            /**
             * @private
             * @function Highcharts.SVGElement#removeFocusBorder
             */
            removeFocusBorder: function () {
                if (this.focusBorder) {
                    this.focusBorder.destroy();
                    delete this.focusBorder;
                }
            }
        });
        /**
         * Set chart's focus to an SVGElement. Calls focus() on it, and draws the focus
         * border. This is used by multiple components.
         *
         * @private
         * @function Highcharts.Chart#setFocusToElement
         *
         * @param {Highcharts.SVGElement} svgElement
         *        Element to draw the border around.
         *
         * @param {SVGDOMElement|HTMLDOMElement} [focusElement]
         *        If supplied, it draws the border around svgElement and sets the focus
         *        to focusElement.
         */
        H.Chart.prototype.setFocusToElement = function (svgElement, focusElement) {
            var focusBorderOptions = this.options.accessibility.keyboardNavigation.focusBorder, browserFocusElement = focusElement || svgElement.element;
            // Set browser focus if possible
            if (browserFocusElement &&
                browserFocusElement.focus) {
                // If there is no focusin-listener, add one to work around Edge issue
                // where Narrator is not reading out points despite calling focus().
                if (!(browserFocusElement.hcEvents &&
                    browserFocusElement.hcEvents.focusin)) {
                    addEvent(browserFocusElement, 'focusin', function () { });
                }
                browserFocusElement.focus();
                // Hide default focus ring
                if (focusBorderOptions.hideBrowserFocusOutline) {
                    browserFocusElement.style.outline = 'none';
                }
            }
            if (focusBorderOptions.enabled) {
                // Remove old focus border
                if (this.focusElement) {
                    this.focusElement.removeFocusBorder();
                }
                // Draw focus border (since some browsers don't do it automatically)
                svgElement.addFocusBorder(focusBorderOptions.margin, {
                    stroke: focusBorderOptions.style.color,
                    strokeWidth: focusBorderOptions.style.lineWidth,
                    borderRadius: focusBorderOptions.style.borderRadius
                });
                this.focusElement = svgElement;
            }
        };

    });
    _registerModule(_modules, 'modules/accessibility/accessibility.js', [_modules['modules/accessibility/utils/chartUtilities.js'], _modules['parts/Globals.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigation.js'], _modules['modules/accessibility/components/LegendComponent.js'], _modules['modules/accessibility/components/MenuComponent.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesComponent.js'], _modules['modules/accessibility/components/ZoomComponent.js'], _modules['modules/accessibility/components/RangeSelectorComponent.js'], _modules['modules/accessibility/components/InfoRegionsComponent.js'], _modules['modules/accessibility/components/ContainerComponent.js'], _modules['modules/accessibility/high-contrast-mode.js'], _modules['modules/accessibility/high-contrast-theme.js'], _modules['modules/accessibility/options/options.js'], _modules['modules/accessibility/options/langOptions.js'], _modules['modules/accessibility/options/deprecatedOptions.js']], function (ChartUtilities, H, KeyboardNavigationHandler, U, AccessibilityComponent, KeyboardNavigation, LegendComponent, MenuComponent, SeriesComponent, ZoomComponent, RangeSelectorComponent, InfoRegionsComponent, ContainerComponent, whcm, highContrastTheme, defaultOptions, defaultLangOptions, copyDeprecatedOptions) {
        /* *
         *
         *  (c) 2009-2019 Øystein Moseng
         *
         *  Accessibility module for Highcharts
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        var extend = U.extend;
        var addEvent = H.addEvent, doc = H.win.document, merge = H.merge, fireEvent = H.fireEvent;
        // Add default options
        merge(true, H.defaultOptions, defaultOptions, {
            accessibility: {
                highContrastTheme: highContrastTheme
            },
            lang: defaultLangOptions
        });
        // Expose functionality on Highcharts namespace
        H.A11yChartUtilities = ChartUtilities;
        H.KeyboardNavigationHandler = KeyboardNavigationHandler;
        H.AccessibilityComponent = AccessibilityComponent;
        /* eslint-disable no-invalid-this, valid-jsdoc */
        /**
         * The Accessibility class
         *
         * @private
         * @requires module:modules/accessibility
         *
         * @class
         * @name Highcharts.Accessibility
         *
         * @param {Highcharts.Chart} chart
         *        Chart object
         */
        function Accessibility(chart) {
            this.init(chart);
        }
        Accessibility.prototype = {
            /**
             * Initialize the accessibility class
             * @private
             * @param {Highcharts.Chart} chart
             *        Chart object
             */
            init: function (chart) {
                this.chart = chart;
                // Abort on old browsers
                if (!doc.addEventListener || !chart.renderer.isSVG) {
                    chart.renderTo.setAttribute('aria-hidden', true);
                    return;
                }
                // Copy over any deprecated options that are used. We could do this on
                // every update, but it is probably not needed.
                copyDeprecatedOptions(chart);
                this.initComponents();
                this.keyboardNavigation = new KeyboardNavigation(chart, this.components);
                this.update();
            },
            /**
             * @private
             */
            initComponents: function () {
                var chart = this.chart, a11yOptions = chart.options.accessibility;
                this.components = {
                    container: new ContainerComponent(),
                    infoRegions: new InfoRegionsComponent(),
                    legend: new LegendComponent(),
                    chartMenu: new MenuComponent(),
                    rangeSelector: new RangeSelectorComponent(),
                    series: new SeriesComponent(),
                    zoom: new ZoomComponent()
                };
                if (a11yOptions.customComponents) {
                    extend(this.components, a11yOptions.customComponents);
                }
                var components = this.components;
                // Refactor to use Object.values if we polyfill
                Object.keys(components).forEach(function (componentName) {
                    components[componentName].initBase(chart);
                    components[componentName].init();
                });
            },
            /**
             * Update all components.
             */
            update: function () {
                var components = this.components, chart = this.chart, a11yOptions = chart.options.accessibility;
                fireEvent(chart, 'beforeA11yUpdate');
                // Update the chart type list as this is used by multiple modules
                chart.types = this.getChartTypes();
                // Update markup
                Object.keys(components).forEach(function (componentName) {
                    components[componentName].onChartUpdate();
                    fireEvent(chart, 'afterA11yComponentUpdate', {
                        name: componentName,
                        component: components[componentName]
                    });
                });
                // Update keyboard navigation
                this.keyboardNavigation.update(a11yOptions.keyboardNavigation.order);
                // Handle high contrast mode
                if (!chart.highContrastModeActive && // Only do this once
                    whcm.isHighContrastModeActive()) {
                    whcm.setHighContrastTheme(chart);
                }
                fireEvent(chart, 'afterA11yUpdate');
            },
            /**
             * Destroy all elements.
             */
            destroy: function () {
                var chart = this.chart || {};
                // Destroy components
                var components = this.components;
                Object.keys(components).forEach(function (componentName) {
                    components[componentName].destroy();
                    components[componentName].destroyBase();
                });
                // Kill keyboard nav
                if (this.keyboardNavigation) {
                    this.keyboardNavigation.destroy();
                }
                // Hide container from screen readers if it exists
                if (chart.renderTo) {
                    chart.renderTo.setAttribute('aria-hidden', true);
                }
                // Remove focus border if it exists
                if (chart.focusElement) {
                    chart.focusElement.removeFocusBorder();
                }
            },
            /**
             * Return a list of the types of series we have in the chart.
             * @private
             */
            getChartTypes: function () {
                var types = {};
                this.chart.series.forEach(function (series) {
                    types[series.type] = 1;
                });
                return Object.keys(types);
            }
        };
        /**
         * @private
         */
        H.Chart.prototype.updateA11yEnabled = function () {
            var a11y = this.accessibility, accessibilityOptions = this.options.accessibility;
            if (accessibilityOptions && accessibilityOptions.enabled) {
                if (a11y) {
                    a11y.update();
                }
                else {
                    this.accessibility = a11y = new Accessibility(this);
                }
            }
            else if (a11y) {
                // Destroy if after update we have a11y and it is disabled
                if (a11y.destroy) {
                    a11y.destroy();
                }
                delete this.accessibility;
            }
            else {
                // Just hide container
                this.renderTo.setAttribute('aria-hidden', true);
            }
        };
        // Handle updates to the module and send render updates to components
        addEvent(H.Chart, 'render', function (e) {
            // Update/destroy
            if (this.a11yDirty && this.renderTo) {
                delete this.a11yDirty;
                this.updateA11yEnabled();
            }
            var a11y = this.accessibility;
            if (a11y) {
                Object.keys(a11y.components).forEach(function (componentName) {
                    a11y.components[componentName].onChartRender();
                });
            }
        });
        // Update with chart/series/point updates
        addEvent(H.Chart, 'update', function (e) {
            // Merge new options
            var newOptions = e.options.accessibility;
            if (newOptions) {
                // Handle custom component updating specifically
                if (newOptions.customComponents) {
                    this.options.accessibility.customComponents =
                        newOptions.customComponents;
                    delete newOptions.customComponents;
                }
                merge(true, this.options.accessibility, newOptions);
                // Recreate from scratch
                if (this.accessibility && this.accessibility.destroy) {
                    this.accessibility.destroy();
                    delete this.accessibility;
                }
            }
            // Mark dirty for update
            this.a11yDirty = true;
        });
        // Mark dirty for update
        addEvent(H.Point, 'update', function () {
            if (this.series.chart.accessibility) {
                this.series.chart.a11yDirty = true;
            }
        });
        ['addSeries', 'init'].forEach(function (event) {
            addEvent(H.Chart, event, function () {
                this.a11yDirty = true;
            });
        });
        ['update', 'updatedData', 'remove'].forEach(function (event) {
            addEvent(H.Series, event, function () {
                if (this.chart.accessibility) {
                    this.chart.a11yDirty = true;
                }
            });
        });
        // Direct updates (events happen after render)
        [
            'afterDrilldown', 'drillupall'
        ].forEach(function (event) {
            addEvent(H.Chart, event, function () {
                if (this.accessibility) {
                    this.accessibility.update();
                }
            });
        });
        // Destroy with chart
        addEvent(H.Chart, 'destroy', function () {
            if (this.accessibility) {
                this.accessibility.destroy();
            }
        });

    });
    _registerModule(_modules, 'masters/modules/accessibility.src.js', [], function () {



    });
}));