Carga
This commit is contained in:
2025-04-17 00:35:33 -06:00
parent 4977462629
commit 67fc72aed5
1333 changed files with 1077639 additions and 0 deletions

View File

@@ -0,0 +1,486 @@
/* *
*
* (c) 2009-2021 Øystein Moseng
*
* Accessibility component for chart legend.
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import A from '../../Core/Animation/AnimationUtilities.js';
var animObject = A.animObject;
import H from '../../Core/Globals.js';
var doc = H.doc;
import Legend from '../../Core/Legend/Legend.js';
import U from '../../Core/Utilities.js';
var addEvent = U.addEvent, fireEvent = U.fireEvent, isNumber = U.isNumber, pick = U.pick, syncTimeout = U.syncTimeout;
import AccessibilityComponent from '../AccessibilityComponent.js';
import KeyboardNavigationHandler from '../KeyboardNavigationHandler.js';
import CU from '../Utils/ChartUtilities.js';
var getChartTitle = CU.getChartTitle;
import HU from '../Utils/HTMLUtilities.js';
var stripHTMLTags = HU.stripHTMLTagsFromString, addClass = HU.addClass, removeClass = HU.removeClass;
/* *
*
* Functions
*
* */
/**
* @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 || {}), unsupportedColorAxis = chart.colorAxis && chart.colorAxis.some(function (c) { return !c.dataClasses || !c.dataClasses.length; });
return !!(items && items.length &&
!unsupportedColorAxis &&
legendA11yOptions.enabled !== false);
}
/**
* @private
*/
function setLegendItemHoverState(hoverActive, legendItem) {
legendItem.setState(hoverActive ? 'hover' : '', true);
['legendGroup', 'legendItem', 'legendSymbol'].forEach(function (i) {
var obj = legendItem[i];
var el = obj && obj.element || obj;
if (el) {
fireEvent(el, hoverActive ? 'mouseover' : 'mouseout');
}
});
}
/* *
*
* Class
*
* */
/**
* The LegendComponent class
*
* @private
* @class
* @name Highcharts.LegendComponent
*/
var LegendComponent = /** @class */ (function (_super) {
__extends(LegendComponent, _super);
function LegendComponent() {
/* *
*
* Properties
*
* */
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.highlightedLegendItemIx = NaN;
_this.proxyGroup = null;
return _this;
}
/* *
*
* Functions
*
* */
/**
* Init the component
* @private
*/
LegendComponent.prototype.init = function () {
var component = this;
this.recreateProxies();
// Note: Chart could create legend dynamically, so events cannot be
// tied to the component's chart's current legend.
// @todo 1. attach component to created legends
// @todo 2. move listeners to composition and access `this.component`
this.addEvent(Legend, 'afterScroll', function () {
if (this.chart === component.chart) {
component.proxyProvider.updateGroupProxyElementPositions('legend');
component.updateLegendItemProxyVisibility();
if (component.highlightedLegendItemIx > -1) {
this.chart.highlightLegendItem(component.highlightedLegendItemIx);
}
}
});
this.addEvent(Legend, 'afterPositionItem', function (e) {
if (this.chart === component.chart && this.chart.renderer) {
component.updateProxyPositionForItem(e.item);
}
});
this.addEvent(Legend, 'afterRender', function () {
if (this.chart === component.chart &&
this.chart.renderer &&
component.recreateProxies()) {
syncTimeout(function () { return component.proxyProvider
.updateGroupProxyElementPositions('legend'); }, animObject(pick(this.chart.renderer.globalAnimation, true)).duration);
}
});
};
/**
* Update visibility of legend items when using paged legend
* @private
*/
LegendComponent.prototype.updateLegendItemProxyVisibility = function () {
var chart = this.chart;
var legend = chart.legend;
var items = legend.allItems || [];
var curPage = legend.currentPage || 1;
var clipHeight = legend.clipHeight || 0;
items.forEach(function (item) {
if (item.a11yProxyElement) {
var hasPages = legend.pages && legend.pages.length;
var proxyEl = item.a11yProxyElement.element;
var hide = false;
if (hasPages) {
var itemPage = item.pageIx || 0;
var y = item._legendItemPos ? item._legendItemPos[1] : 0;
var h = item.legendItem ?
Math.round(item.legendItem.getBBox().height) :
0;
hide = y + h - legend.pages[itemPage] > clipHeight ||
itemPage !== curPage - 1;
}
if (hide) {
if (chart.styledMode) {
addClass(proxyEl, 'highcharts-a11y-invisible');
}
else {
proxyEl.style.visibility = 'hidden';
}
}
else {
removeClass(proxyEl, 'highcharts-a11y-invisible');
proxyEl.style.visibility = '';
}
}
});
};
/**
* @private
*/
LegendComponent.prototype.onChartRender = function () {
if (!shouldDoLegendA11y(this.chart)) {
this.removeProxies();
}
};
/**
* @private
*/
LegendComponent.prototype.highlightAdjacentLegendPage = function (direction) {
var chart = this.chart;
var legend = chart.legend;
var curPageIx = legend.currentPage || 1;
var newPageIx = curPageIx + direction;
var pages = legend.pages || [];
if (newPageIx > 0 && newPageIx <= pages.length) {
var len = legend.allItems.length;
for (var i = 0; i < len; ++i) {
if (legend.allItems[i].pageIx + 1 === newPageIx) {
var res = chart.highlightLegendItem(i);
if (res) {
this.highlightedLegendItemIx = i;
}
return;
}
}
}
};
/**
* @private
*/
LegendComponent.prototype.updateProxyPositionForItem = function (item) {
if (item.a11yProxyElement) {
item.a11yProxyElement.refreshPosition();
}
};
/**
* Returns false if legend a11y is disabled and proxies were not created,
* true otherwise.
* @private
*/
LegendComponent.prototype.recreateProxies = function () {
var focusedElement = doc.activeElement;
var proxyGroup = this.proxyGroup;
var shouldRestoreFocus = focusedElement && proxyGroup &&
proxyGroup.contains(focusedElement);
this.removeProxies();
if (shouldDoLegendA11y(this.chart)) {
this.addLegendProxyGroup();
this.proxyLegendItems();
this.updateLegendItemProxyVisibility();
this.updateLegendTitle();
if (shouldRestoreFocus) {
this.chart.highlightLegendItem(this.highlightedLegendItemIx);
}
return true;
}
return false;
};
/**
* @private
*/
LegendComponent.prototype.removeProxies = function () {
this.proxyProvider.removeGroup('legend');
};
/**
* @private
*/
LegendComponent.prototype.updateLegendTitle = function () {
var chart = this.chart;
var legendTitle = stripHTMLTags((chart.legend &&
chart.legend.options.title &&
chart.legend.options.title.text ||
'').replace(/<br ?\/?>/g, ' '));
var legendLabel = chart.langFormat('accessibility.legend.legendLabel' + (legendTitle ? '' : 'NoTitle'), {
chart: chart,
legendTitle: legendTitle,
chartTitle: getChartTitle(chart)
});
this.proxyProvider.updateGroupAttrs('legend', {
'aria-label': legendLabel
});
};
/**
* @private
*/
LegendComponent.prototype.addLegendProxyGroup = function () {
var a11yOptions = this.chart.options.accessibility;
var groupRole = a11yOptions.landmarkVerbosity === 'all' ?
'region' : null;
this.proxyGroup = this.proxyProvider.addGroup('legend', 'ul', {
// Filled by updateLegendTitle, to keep up to date without
// recreating group
'aria-label': '_placeholder_',
role: groupRole
});
};
/**
* @private
*/
LegendComponent.prototype.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.BubbleLegendItem|Point|Highcharts.Series} item
*/
LegendComponent.prototype.proxyLegendItem = function (item) {
if (!item.legendItem || !item.legendGroup) {
return;
}
var itemLabel = this.chart.langFormat('accessibility.legend.legendItem', {
chart: this.chart,
itemName: stripHTMLTags(item.name),
item: item
});
var attribs = {
tabindex: -1,
'aria-pressed': item.visible,
'aria-label': itemLabel
};
// Considers useHTML
var proxyPositioningElement = item.legendGroup.div ?
item.legendItem :
item.legendGroup;
item.a11yProxyElement = this.proxyProvider.addProxyElement('legend', {
click: item.legendItem,
visual: proxyPositioningElement.element
}, attribs);
};
/**
* Get keyboard navigation handler for this component.
* @private
*/
LegendComponent.prototype.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 (keyCode) {
if (H.isFirefox && keyCode === keys.space) { // #15520
return this.response.success;
}
return component.onKbdClick(this);
}
],
[
[keys.pageDown, keys.pageUp],
function (keyCode) {
var direction = keyCode === keys.pageDown ? 1 : -1;
component.highlightAdjacentLegendPage(direction);
return this.response.success;
}
]
],
validate: function () {
return component.shouldHaveLegendNavigation();
},
init: function () {
chart.highlightLegendItem(0);
component.highlightedLegendItemIx = 0;
},
terminate: function () {
component.highlightedLegendItemIx = -1;
chart.legend.allItems.forEach(function (item) { return setLegendItemHoverState(false, item); });
}
});
};
/**
* Arrow key navigation
* @private
*/
LegendComponent.prototype.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;
}
return response.success;
};
/**
* @private
* @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler
* @return {number} Response code
*/
LegendComponent.prototype.onKbdClick = function (keyboardNavigationHandler) {
var legendItem = this.chart.legend.allItems[this.highlightedLegendItemIx];
if (legendItem && legendItem.a11yProxyElement) {
legendItem.a11yProxyElement.click();
}
return keyboardNavigationHandler.response.success;
};
/**
* @private
*/
LegendComponent.prototype.shouldHaveLegendNavigation = function () {
if (!shouldDoLegendA11y(this.chart)) {
return false;
}
var chart = this.chart, legendOptions = chart.options.legend || {}, legendA11yOptions = (legendOptions.accessibility || {});
return !!(chart.legend.display &&
legendA11yOptions.keyboardNavigation &&
legendA11yOptions.keyboardNavigation.enabled);
};
return LegendComponent;
}(AccessibilityComponent));
/* *
*
* Class Namespace
*
* */
(function (LegendComponent) {
/* *
*
* Declarations
*
* */
/* *
*
* Constants
*
* */
var composedClasses = [];
/* *
*
* Functions
*
* */
/* eslint-disable valid-jsdoc */
/**
* Highlight legend item by index.
* @private
*/
function chartHighlightLegendItem(ix) {
var items = this.legend.allItems;
var oldIx = this.accessibility &&
this.accessibility.components.legend.highlightedLegendItemIx;
var itemToHighlight = items[ix];
if (itemToHighlight) {
if (isNumber(oldIx) && items[oldIx]) {
setLegendItemHoverState(false, items[oldIx]);
}
scrollLegendToItem(this.legend, ix);
var legendItemProp = itemToHighlight.legendItem;
var proxyBtn = itemToHighlight.a11yProxyElement &&
itemToHighlight.a11yProxyElement.buttonElement;
if (legendItemProp && legendItemProp.element && proxyBtn) {
this.setFocusToElement(legendItemProp, proxyBtn);
}
setLegendItemHoverState(true, itemToHighlight);
return true;
}
return false;
}
/**
* @private
*/
function compose(ChartClass, LegendClass) {
if (composedClasses.indexOf(ChartClass) === -1) {
composedClasses.push(ChartClass);
var chartProto = ChartClass.prototype;
chartProto.highlightLegendItem = chartHighlightLegendItem;
}
if (composedClasses.indexOf(LegendClass) === -1) {
composedClasses.push(LegendClass);
addEvent(LegendClass, 'afterColorizeItem', legendOnAfterColorizeItem);
}
}
LegendComponent.compose = compose;
/**
* Keep track of pressed state for legend items.
* @private
*/
function legendOnAfterColorizeItem(e) {
var chart = this.chart, a11yOptions = chart.options.accessibility, legendItem = e.item;
if (a11yOptions.enabled && legendItem && legendItem.a11yProxyElement) {
legendItem.a11yProxyElement.buttonElement.setAttribute('aria-pressed', e.visible ? 'true' : 'false');
}
}
})(LegendComponent || (LegendComponent = {}));
/* *
*
* Default Export
*
* */
export default LegendComponent;