Icard/angular-clarity-master(work.../node_modules/highcharts/es-modules/Accessibility/ProxyElement.js

221 lines
7.4 KiB
JavaScript
Raw Normal View History

2024-07-16 14:55:36 +00:00
/* *
*
* (c) 2009-2024 Øystein Moseng
*
* Proxy elements are used to shadow SVG elements in HTML for assistive
* technology, such as screen readers or voice input software.
*
* The ProxyElement class represents such an element, and deals with
* overlay positioning and mirroring events for the target.
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
import H from '../Core/Globals.js';
const { doc } = H;
import U from '../Core/Utilities.js';
const { attr, css, merge } = U;
import EventProvider from './Utils/EventProvider.js';
import ChartUtilities from './Utils/ChartUtilities.js';
const { fireEventOnWrappedOrUnwrappedElement } = ChartUtilities;
import HTMLUtilities from './Utils/HTMLUtilities.js';
const { cloneMouseEvent, cloneTouchEvent, getFakeMouseEvent, removeElement } = HTMLUtilities;
/* *
*
* Class
*
* */
/**
* Represents a proxy element that overlays a target and relays events
* to its target.
*
* @private
* @class
*/
class ProxyElement {
/* *
*
* Constructor
*
* */
constructor(chart, target, proxyElementType = 'button', wrapperElementType, attributes) {
this.chart = chart;
this.target = target;
this.eventProvider = new EventProvider();
const innerEl = this.innerElement =
doc.createElement(proxyElementType), wrapperEl = this.element = wrapperElementType ?
doc.createElement(wrapperElementType) : innerEl;
if (!chart.styledMode) {
this.hideElementVisually(innerEl);
}
if (wrapperElementType) {
if (wrapperElementType === 'li' && !chart.styledMode) {
wrapperEl.style.listStyle = 'none';
}
wrapperEl.appendChild(innerEl);
this.element = wrapperEl;
}
this.updateTarget(target, attributes);
}
/* *
*
* Functions
*
* */
/**
* Fake a click event on the target.
*/
click() {
const pos = this.getTargetPosition();
pos.x += pos.width / 2;
pos.y += pos.height / 2;
const fakeEventObject = getFakeMouseEvent('click', pos);
fireEventOnWrappedOrUnwrappedElement(this.target.click, fakeEventObject);
}
/**
* Update the target to be proxied. The position and events are updated to
* match the new target.
* @param target The new target definition
* @param attributes New HTML attributes to apply to the proxy. Set an
* attribute to null to remove.
*/
updateTarget(target, attributes) {
this.target = target;
this.updateCSSClassName();
const attrs = attributes || {};
Object.keys(attrs).forEach((a) => {
if (attrs[a] === null) {
delete attrs[a];
}
});
const targetAriaLabel = this.getTargetAttr(target.click, 'aria-label');
attr(this.innerElement, merge(targetAriaLabel ? {
'aria-label': targetAriaLabel
} : {}, attrs));
this.eventProvider.removeAddedEvents();
this.addProxyEventsToElement(this.innerElement, target.click);
this.refreshPosition();
}
/**
* Refresh the position of the proxy element to match the current target
*/
refreshPosition() {
const bBox = this.getTargetPosition();
css(this.innerElement, {
width: (bBox.width || 1) + 'px',
height: (bBox.height || 1) + 'px',
left: (Math.round(bBox.x) || 0) + 'px',
top: (Math.round(bBox.y) || 0) + 'px'
});
}
/**
* Remove button from DOM, and clear events.
*/
remove() {
this.eventProvider.removeAddedEvents();
removeElement(this.element);
}
// -------------------------- private ------------------------------------
/**
* Update the CSS class name to match target
*/
updateCSSClassName() {
const stringHasNoTooltip = (s) => (s.indexOf('highcharts-no-tooltip') > -1);
const legend = this.chart.legend;
const groupDiv = legend.group && legend.group.div;
const noTooltipOnGroup = stringHasNoTooltip(groupDiv && groupDiv.className || '');
const targetClassName = this.getTargetAttr(this.target.click, 'class') || '';
const noTooltipOnTarget = stringHasNoTooltip(targetClassName);
this.innerElement.className = noTooltipOnGroup || noTooltipOnTarget ?
'highcharts-a11y-proxy-element highcharts-no-tooltip' :
'highcharts-a11y-proxy-element';
}
/**
* Mirror events for a proxy element to a target
*/
addProxyEventsToElement(element, target) {
[
'click', 'touchstart', 'touchend', 'touchcancel', 'touchmove',
'mouseover', 'mouseenter', 'mouseleave', 'mouseout'
].forEach((evtType) => {
const isTouchEvent = evtType.indexOf('touch') === 0;
this.eventProvider.addEvent(element, evtType, (e) => {
const clonedEvent = isTouchEvent ?
cloneTouchEvent(e) :
cloneMouseEvent(e);
if (target) {
fireEventOnWrappedOrUnwrappedElement(target, clonedEvent);
}
e.stopPropagation();
// #9682, #15318: Touch scrolling didn't work when touching
// proxy
if (!isTouchEvent) {
e.preventDefault();
}
}, { passive: false });
});
}
/**
* Set visually hidden style on a proxy element
*/
hideElementVisually(el) {
css(el, {
borderWidth: 0,
backgroundColor: 'transparent',
cursor: 'pointer',
outline: 'none',
opacity: 0.001,
filter: 'alpha(opacity=1)',
zIndex: 999,
overflow: 'hidden',
padding: 0,
margin: 0,
display: 'block',
position: 'absolute',
'-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)'
});
}
/**
* Get the position relative to chart container for the target
*/
getTargetPosition() {
const clickTarget = this.target.click;
// We accept both DOM elements and wrapped elements as click targets.
const clickTargetElement = clickTarget.element ?
clickTarget.element :
clickTarget;
const posElement = this.target.visual || clickTargetElement;
const chartDiv = this.chart.renderTo, pointer = this.chart.pointer;
if (chartDiv && posElement?.getBoundingClientRect && pointer) {
const rectEl = posElement.getBoundingClientRect(), chartPos = pointer.getChartPosition();
return {
x: (rectEl.left - chartPos.left) / chartPos.scaleX,
y: (rectEl.top - chartPos.top) / chartPos.scaleY,
width: rectEl.right / chartPos.scaleX -
rectEl.left / chartPos.scaleX,
height: rectEl.bottom / chartPos.scaleY -
rectEl.top / chartPos.scaleY
};
}
return { x: 0, y: 0, width: 1, height: 1 };
}
/**
* Get an attribute value of a target
*/
getTargetAttr(target, key) {
if (target.element) {
return target.element.getAttribute(key);
}
return target.getAttribute(key);
}
}
/* *
*
* Default Export
*
* */
export default ProxyElement;