@syncfusion/ej2-charts
Version:
Feature-rich chart control with built-in support for over 25 chart types, technical indictors, trendline, zooming, tooltip, selection, crosshair and trackball.
892 lines • 106 kB
JavaScript
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 (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
/**
* Selection src file
*/
import { Animation, Browser } from '@syncfusion/ej2-base';
import { remove } from '@syncfusion/ej2-base';
import { extend, isNullOrUndefined } from '@syncfusion/ej2-base';
import { ChartLocation, RectOption, CircleOption, withInBounds, getDraggedRectLocation, removeElement, getElement } from '../../common/utils/helper';
import { Rect, PathOption } from '@syncfusion/ej2-svg-base';
import { Index } from '../../common/model/base';
import { dragComplete, selectionComplete } from '../../common/model/constants';
import { BaseSelection } from '../../common/user-interaction/selection';
/**
* The `Selection` module handles the selection of chart elements.
*
* @private
*/
var Selection = /** @class */ (function (_super) {
__extends(Selection, _super);
/**
* Constructor for selection module.
*
* @private
*/
function Selection(chart) {
var _this = _super.call(this, chart) || this;
_this.isdrawRect = true;
_this.multiDataIndexes = [];
_this.pathIndex = 0;
_this.seriesIndex = 0;
_this.count = -1;
_this.dragRectArray = [];
_this.filterArray = [];
_this.totalSelectedPoints = [];
_this.chart = chart;
_this.renderer = chart.renderer;
var mode = chart.selectionMode;
_this.isMultiDrag = chart.isMultiSelect && (mode.indexOf('Drag') > -1);
_this.addEventListener();
return _this;
}
/**
* Adds event listeners for the chart.
*
* @returns {void}
*/
Selection.prototype.addEventListener = function () {
if (this.chart.isDestroyed || (this.chart.stockChart && this.chart.stockChart.onPanning)) {
return;
}
var cancelEvent = Browser.isPointer ? 'pointerleave' : 'mouseleave';
this.chart.on(Browser.touchMoveEvent, this.mouseMove, this);
this.chart.on(cancelEvent, this.mouseLeave, this);
this.chart.on('click', this.mouseClick, this);
this.chart.on(Browser.touchStartEvent, this.mousedown, this);
this.chart.on(Browser.touchEndEvent, this.mouseLeave, this);
};
/**
* Handles the mousedown event.
*
* @private
* @param {Event} e - The event object.
* @returns {void}
*/
Selection.prototype.mousedown = function (e) {
var chart = this.chart;
if (chart.isPointMouseDown || chart.selectionMode === 'None' || chart.isChartDrag) {
return;
}
if (chart.isDoubleTap || !chart.isTouch || this.rectPoints) {
this.dragStart(chart, chart.chartAxisLayoutPanel.seriesClipRect, chart.mouseDownX, chart.mouseDownY, e);
}
};
/**
* UnBinding events for selection module.
*
* @returns {void}
*/
Selection.prototype.removeEventListener = function () {
if (this.chart.isDestroyed) {
return;
}
this.chart.off(Browser.touchMoveEvent, this.mouseMove);
this.chart.off('pointerleave' || 'mouseleave', this.mouseLeave);
this.chart.off('click', this.mouseClick);
this.chart.off(Browser.touchStartEvent, this.mousedown);
this.chart.off(Browser.touchEndEvent, this.mouseLeave);
};
/**
* Initializes private variables for the chart.
*
* @private
* @param {Chart} chart - The chart instance.
* @returns {void}
*/
Selection.prototype.initPrivateVariables = function (chart) {
this.styleId = chart.element.id + '_ej2_chart_selection';
this.unselected = chart.element.id + '_ej2_deselected';
this.closeIconId = chart.element.id + '_ej2_drag_close';
this.draggedRectGroup = chart.element.id + '_ej2_drag_group';
this.multiRectGroup = chart.element.id + '_ej2_drag_multi_group';
this.draggedRect = chart.element.id + '_ej2_drag_rect';
this.lassoPath = chart.element.id + '_ej2_drag_path';
this.selectedDataIndexes = [];
this.rectPoints = null;
this.isSeriesMode = chart.selectionMode === 'Series';
};
/**
* Method to select the point and series.
*
* @param {Chart} chart - The chart instance.
* @returns {void}
*/
Selection.prototype.invokeSelection = function (chart) {
this.initPrivateVariables(chart);
this.series = extend({}, chart.visibleSeries, null, true);
this.seriesStyles();
this.currentMode = chart.selectionMode;
if (!(chart.selectionMode.indexOf('Drag') > -1)) {
this.selectDataIndex(chart, this.concatIndexes(chart.selectedDataIndexes, this.selectedDataIndexes));
}
};
Selection.prototype.generateStyle = function (series) {
if (series) {
if (this.styleId.indexOf('selection') > 1 && this.chart.selectionMode !== 'None') {
this.unselected = series.unSelectedStyle || this.unselected;
}
if (this.styleId.indexOf('highlight') > 0 && (this.chart.highlightMode !== 'None' || this.chart.legendSettings.enableHighlight)) {
this.unselected = series.nonHighlightStyle || this.unselected;
}
return (series.selectionStyle || this.styleId + '_series_' + series.index);
}
return 'undefined';
};
/**
* Selects data points in the chart based on the provided indexes.
*
* @param {Chart} chart - The chart instance.
* @param {Index[]} indexes - An array of Index objects specifying the series and point indexes to be selected.
* @returns {void}
*/
Selection.prototype.selectDataIndex = function (chart, indexes) {
for (var _i = 0, indexes_1 = indexes; _i < indexes_1.length; _i++) {
var index = indexes_1[_i];
this.performSelection(index, chart, this.getElementByIndex(chart, index, '', this.series[index.series].marker.visible)[0]);
}
};
/**
* Retrieves the DOM elements corresponding to the specified data point index.
*
* @param {Chart} chart - The chart instance.
* @param {Index} index - The index object specifying the series and point indexes.
* @param {string} [suffix=''] - Optional suffix to be appended to the element IDs.
* @param {boolean} [marker] - Optional parameter to specify whether to retrieve marker elements. Default is false.
* @param {boolean} [dataLabel] - Optional parameter to specify whether to retrieve datalabel elements. Default is false.
* @returns {Element[]} - An array of DOM elements corresponding to the specified data point index.
*/
Selection.prototype.getElementByIndex = function (chart, index, suffix, marker, dataLabel) {
if (suffix === void 0) { suffix = ''; }
var elementId = chart.element.id + '_Series_' + index.series + '_Point' + '_' + index.point;
var series = chart.series[index.series];
elementId = (series.type !== 'Scatter' && series.type !== 'Bubble' && marker) ? (elementId + '_Symbol' + suffix) : elementId;
if (!marker && dataLabel) {
return [getElement(elementId + '_Text_0' + suffix), getElement(elementId + '_TextShape_0' + suffix)];
}
return [getElement(elementId), ((series.type === 'RangeArea' || series.type === 'SplineRangeArea' || series.type === 'RangeStepArea') && series.marker.visible) ?
getElement(elementId + '1') : null];
};
/**
* Retrieves the DOM elements corresponding to the cluster of data points at the specified index.
*
* @param {Chart} chart - The chart instance.
* @param {Index} index - The index object specifying the series and point indexes.
* @returns {Element[]} - An array of DOM elements corresponding to the cluster of data points at the specified index.
*/
Selection.prototype.getClusterElements = function (chart, index) {
var clusters = [];
var seriesStyle;
var selectedElements;
for (var _i = 0, _a = chart.visibleSeries; _i < _a.length; _i++) {
var series = _a[_i];
if (series.visible) {
index = new Index(series.index, index.point);
if (series.isRectSeries) {
clusters.push(this.getElementByIndex(chart, index)[0]);
}
clusters.push(this.getElementByIndex(chart, index, '', series.marker.visible)[0]);
var dataLabelTextElement = document.getElementById(chart.element.id + '_Series_' + series.index + '_Point_' + index.point + '_Text_0');
var dataLabelShapeElement = document.getElementById(chart.element.id + '_Series_' + series.index + '_Point_' + index.point + '_TextShape_0');
if (dataLabelTextElement) {
clusters.push(dataLabelTextElement);
}
if (dataLabelShapeElement) {
clusters.push(dataLabelShapeElement);
}
seriesStyle = this.generateStyle(chart.visibleSeries[index.series]);
selectedElements = document.querySelectorAll('.' + seriesStyle);
this.findTrackballElements(selectedElements, seriesStyle);
var clusterIndex = series.marker.visible && series.isRectSeries ? 2 : 1;
clusterIndex += (dataLabelTextElement && dataLabelShapeElement) ? 2 :
(dataLabelTextElement || dataLabelShapeElement) ? 1 : 0;
if (!chart.isMultiSelect && selectedElements.length > 0 &&
selectedElements[0].id !== (clusters[clusters.length - clusterIndex] ? clusters[clusters.length - clusterIndex].id : '')) {
this.removeSelection(chart, index.series, selectedElements, seriesStyle, true);
}
}
}
return clusters;
};
/**
* Finds the elements within the selected elements that match the specified class name.
*
* @param {Element[] | NodeListOf<HTMLElement>} selectedElements - The elements to search within.
* @param {string} className - The class name to search for.
* @returns {void}
*/
Selection.prototype.findTrackballElements = function (selectedElements, className) {
var trackballElements;
var elements;
for (var i = 0; i < selectedElements.length; i++) {
if (!isNullOrUndefined(selectedElements[i])) {
trackballElements = !isNullOrUndefined(selectedElements[i].parentNode) ?
[].slice.call(selectedElements[0].parentNode.querySelectorAll('.' + className)) : [];
if (trackballElements.length > 0) {
elements = [];
for (var i_1 = 0; i_1 < trackballElements.length; i_1++) {
if (trackballElements[i_1].id.indexOf('Trackball') > -1) {
elements.push(trackballElements[i_1]);
}
}
this.removeStyles(elements);
}
}
}
};
/**
* Finds the elements in the chart corresponding to the specified series and data point index.
*
* @param {Chart} chart - The chart instance.
* @param {SeriesModel} series - The series for which to find the elements.
* @param {Index} index - The index of the data point.
* @param {string} [suffix=''] - A suffix to append to the element IDs.
* @param {boolean} [marker] - Specifies whether to include marker elements.
* @param {boolean} [dataLabel] - Specifies whether to include datalabel elements.
* @returns {Element[]} - An array of elements corresponding to the specified series and data point index.
*/
Selection.prototype.findElements = function (chart, series, index, suffix, marker, dataLabel) {
if (suffix === void 0) { suffix = ''; }
if (this.isSeriesMode) {
return this.getSeriesElements(series);
}
else if (this.currentMode === 'Cluster') {
return this.getClusterElements(chart, index);
}
else {
return this.getElementByIndex(chart, index, suffix, marker, dataLabel);
}
};
/**
* Checks if the target element is already selected for the specified event type.
*
* @param {Element} targetElem - The target element to check.
* @param {string} eventType - The type of event (e.g., 'mouse move', 'touch move').
* @returns {boolean} - A boolean value indicating whether the target element is already selected for the specified event type.
*/
Selection.prototype.isAlreadySelected = function (targetElem, eventType) {
if (eventType === 'click') {
this.currentMode = this.chart.selectionMode;
this.styleId = this.chart.element.id + (this.chart.selectionModule && this.chart.selectionMode !== 'None' ? '_ej2_chart_selection' : '_ej2_chart_highlight');
}
else if (eventType === 'mousemove' || eventType === 'pointermove') {
this.currentMode = this.chart.highlightMode;
this.highlightDataIndexes = [];
this.styleId = this.chart.element.id + '_ej2_chart_highlight';
}
if (this.chart.highlightMode !== 'None' && this.chart.selectionMode === 'None') {
if (eventType === 'click') {
return false;
}
}
if (((this.chart.highlightMode !== 'None' || this.chart.legendSettings.enableHighlight) && this.previousSelectedEle && this.previousSelectedEle[0])) {
var parentNodeId = targetElem.parentNode ? targetElem.parentNode.id : '';
var isElement = void 0;
if (targetElem.parentNode) {
isElement = (parentNodeId.indexOf('SeriesGroup') > 0 || parentNodeId.indexOf('SymbolGroup') > 0) ? true : false;
}
for (var i = 0; i < this.previousSelectedEle.length; i++) {
if (this.previousSelectedEle[i] && this.previousSelectedEle[i].hasAttribute('class')) {
if (this.previousSelectedEle[i].getAttribute('class').indexOf('highlight') > -1 &&
(isElement || eventType === 'click')) {
this.previousSelectedEle[i].removeAttribute('class');
if (this.previousSelectedEle[i].id.indexOf('Group') > 0) {
for (var j = 0; j < this.previousSelectedEle[i].children.length; j++) {
if (this.chart.highlightColor !== '' && !isNullOrUndefined(this.chart.highlightColor) && this.chart.highlightPattern === 'None') {
this.previousSelectedEle[i].children[j].setAttribute('fill', (this.previousSelectedEle[i].children[j].id.indexOf('Text') > -1 || this.previousSelectedEle[i].children[j].id.indexOf('TextShape') > -1) ? this.previousSelectedEle[i].children[j].getAttribute('fill') : this.control.visibleSeries[this.indexFinder(this.previousSelectedEle[i].id).series].interior);
}
this.previousSelectedEle[i].children[j].removeAttribute('style');
}
}
else {
if (this.chart.highlightColor !== '' && !isNullOrUndefined(this.chart.highlightColor) && this.chart.highlightPattern === 'None') {
this.previousSelectedEle[i].setAttribute('fill', (this.previousSelectedEle[i].id.indexOf('Text') > -1 || this.previousSelectedEle[i].id.indexOf('TextShape') > -1) ? this.previousSelectedEle[i].getAttribute('fill') : this.control.visibleSeries[this.indexFinder(this.previousSelectedEle[i].id).series].interior);
}
this.previousSelectedEle[i].removeAttribute('style');
}
this.addOrRemoveIndex(this.highlightDataIndexes, this.indexFinder(this.previousSelectedEle[i].id));
}
else if (!isElement && this.previousSelectedEle[i].getAttribute('class').indexOf('highlight') > -1) {
this.performSelection(this.indexFinder(this.previousSelectedEle[i].id), this.chart, this.previousSelectedEle[i]);
}
}
}
}
return true;
};
Selection.prototype.mouseClick = function (event) {
this.calculateSelectedElements(event.target, event.type, true);
if (this.chart.highlightModule && this.chart.highlightModule.highlightDataIndexes
&& this.chart.highlightModule.highlightDataIndexes.length > 0 && event.target.id.indexOf('_chart_legend_') === -1
&& this.chart.isTouch && Browser.isDevice) {
this.removeLegendHighlightStyles();
}
};
/**
* Calculates the selected elements based on the target element and event type.
*
* @param {HTMLElement} targetElement - The target element for which to calculate selected elements.
* @param {string} eventType - The type of event (e.g., 'mouse move', 'touch move').
* @param {boolean} pointClick - Selection of series points.
* @returns {void}
*/
Selection.prototype.calculateSelectedElements = function (targetElement, eventType, pointClick) {
if (isNullOrUndefined(targetElement)) {
return;
}
if ((this.chart.selectionMode === 'None' && this.chart.highlightMode === 'None') ||
targetElement.id && targetElement.id.indexOf(this.chart.element.id + '_') === -1) {
return;
}
if (eventType === 'mousemove' || eventType === 'pointermove') {
if (targetElement.hasAttribute('class') && (targetElement.getAttribute('class').indexOf('highlight') > -1 ||
targetElement.getAttribute('class').indexOf('selection') > -1)) {
return;
}
if (!isNullOrUndefined(targetElement.parentNode) && targetElement.parentNode.hasAttribute('class') &&
(targetElement.parentNode.getAttribute('class').indexOf('highlight') > 0 ||
targetElement.parentNode.getAttribute('class').indexOf('selection') > 0)) {
return;
}
}
this.isAlreadySelected(targetElement, eventType);
if (targetElement.id && targetElement.id.indexOf('_Series_') > -1 && targetElement.id.indexOf('_Text_') === -1) {
var element = void 0;
if (targetElement.id.indexOf('_Trackball_1') > -1) {
element = getElement(targetElement.id.split('_Trackball_')[0] + '_Symbol');
element = isNullOrUndefined(element) ? getElement(targetElement.id.split('_Trackball_')[0]) : element;
}
else if (targetElement.id.indexOf('_Trackball_0') > -1) {
return null;
}
this.performSelection(this.indexFinder(targetElement.id), this.chart, element || targetElement, pointClick);
}
};
/**
* Performs selection based on the provided index and chart.
*
* @param {Index} index - The index for which to perform the selection.
* @param {Chart} chart - The chart instance.
* @param {Element} [element] - Optional. The element associated with the selection.
* @param {boolean} pointClick - Selection of series points.
* @returns {void}
*/
Selection.prototype.performSelection = function (index, chart, element, pointClick) {
this.isSeriesMode = this.currentMode === 'Series';
if (chart.visibleSeries[index.series].type === 'BoxAndWhisker' && element &&
element.id === chart.element.id + '_Series_' + index.series + '_Point_' + index.point + '_BoxPath') {
element = element.parentNode;
}
if (chart.visibleSeries[index.series].type === 'Area' && (this.currentMode === 'Point' || this.currentMode === 'Cluster') && element &&
(element.id === this.chart.element.id + '_Series_' + index.series)) {
var className = this.generateStyle(chart.series[index.series]);
var selectionEle = document.querySelectorAll('.' + className);
this.findTrackballElements(selectionEle, className);
this.blurEffect(chart.element.id, chart.visibleSeries, false, index.point);
}
switch (this.currentMode) {
case 'Series':
this.selection(chart, index, this.getSeriesElements(chart.series[index.series]));
this.selectionComplete(chart, index, this.currentMode);
this.blurEffect(chart.element.id, chart.visibleSeries, false, index.point);
break;
case 'Point':
if ((!isNaN(index.point) && element) || (!pointClick && isNaN(index.point))) {
var pointElements = [];
pointElements.push(element);
var series = this.chart.visibleSeries[index.series];
var baseId = chart.element.id + "_Series_" + index.series + "_Point_" + index.point;
var textElement = document.getElementById(baseId + "_Text_0");
if (series.marker.dataLabel.visible && textElement !== null) {
pointElements.push(textElement);
pointElements.push(document.getElementById(baseId + "_TextShape_0"));
}
if (pointElements[0] !== null && chart.series[index.series].marker.visible &&
(chart.series[index.series].type.indexOf('Column') !== -1 || chart.series[index.series].type.indexOf('Bar') !== -1)) {
if (!(element.id.indexOf('_Symbol') !== -1) && getElement(element.id + '_Symbol')) {
pointElements.push(getElement(element.id + '_Symbol'));
}
else if (element.id.indexOf('_Symbol') !== -1 && getElement(element.id.replace('_Symbol', ''))) {
pointElements.push(getElement(element.id.replace('_Symbol', '')));
}
}
this.selection(chart, index, (!pointClick && isNaN(index.point)) ?
this.getSeriesElements(chart.series[index.series]) : pointElements);
this.selectionComplete(chart, index, this.currentMode);
this.blurEffect(chart.element.id, chart.visibleSeries, false, index.point);
}
break;
case 'Cluster':
if (!isNaN(index.point) || (!pointClick && isNaN(index.point))) {
if (!pointClick && isNaN(index.point)) {
this.selection(chart, index, this.getSeriesElements(chart.series[index.series]));
}
else {
this.clusterSelection(chart, index);
}
this.selectionComplete(chart, index, this.currentMode);
this.blurEffect(chart.element.id, chart.visibleSeries, false, index.point);
}
break;
}
};
/**
* Completes the selection process based on the provided index and selection mode.
*
* @param {Chart} chart - The chart instance.
* @param {Index} index - The index for which the selection is completed.
* @param {SelectionMode | HighlightMode} selectionMode - The selection mode.
* @returns {void}
*/
Selection.prototype.selectionComplete = function (chart, index, selectionMode) {
var points;
var pointIndex;
var seriesIndex;
var selectedPointValues = [];
var yValue;
var selectedPointX;
if (selectionMode === 'Cluster') {
for (var _i = 0, _a = chart.visibleSeries; _i < _a.length; _i++) {
var series = _a[_i];
if (series.visible) {
for (var i = 0; i < this.selectedDataIndexes.length; i++) {
pointIndex = chart.isMultiSelect ? this.selectedDataIndexes[i].point : index.point;
seriesIndex = series.index;
points = series.points;
if (!isNaN(pointIndex) && (pointIndex < points.length)) {
yValue = (series.type !== 'RangeArea' || series.type.indexOf('SplineRangeArea') > -1 || series.type.indexOf('RangeStepArea') > -1) ? points[pointIndex].yValue :
points[pointIndex].regions[0].y;
selectedPointX = points[pointIndex].xValue;
if (chart.primaryXAxis.valueType === 'Category') {
selectedPointX = points[pointIndex].x.toLocaleString();
}
else if (chart.primaryXAxis.valueType === 'DateTime') {
selectedPointX = new Date(points[pointIndex].xValue);
}
if (series.category !== 'Indicator') {
selectedPointValues.push({
x: selectedPointX, y: yValue, seriesIndex: seriesIndex,
pointIndex: pointIndex
});
}
if (series.type === 'RangeArea' || series.type === 'SplineRangeArea' || series.type === 'RangeStepArea') {
selectedPointValues.push({
x: selectedPointX, y: points[pointIndex].regions[0].y,
seriesIndex: seriesIndex, pointIndex: pointIndex
});
}
}
}
}
}
}
else if (selectionMode === 'Series') {
if (chart.isMultiSelect) {
for (var i = 0; i < this.selectedDataIndexes.length; i++) {
seriesIndex = this.selectedDataIndexes[i].series;
if (this.selectedDataIndexes.length > 0) {
selectedPointValues.push({
seriesIndex: seriesIndex
});
}
}
}
else {
seriesIndex = (this.selectedDataIndexes.length > 0) ? this.selectedDataIndexes[0].series :
(this.highlightDataIndexes && this.highlightDataIndexes.length > 0) ? this.highlightDataIndexes[0].series : 0;
if (this.selectedDataIndexes.length > 0 || (this.highlightDataIndexes && this.highlightDataIndexes.length > 0)) {
selectedPointValues.push({
seriesIndex: seriesIndex
});
}
}
}
else if (selectionMode === 'Point') {
var selectedData = [];
if (this.styleId.indexOf('highlight') > -1) {
selectedData = this.highlightDataIndexes;
}
else {
selectedData = this.selectedDataIndexes;
}
for (var i = 0; i < selectedData.length; i++) {
pointIndex = selectedData[i].point;
seriesIndex = selectedData[i].series;
var series = chart.series[seriesIndex];
points = series.points;
if (!isNaN(pointIndex)) {
selectedPointX = points[pointIndex].xValue;
yValue = (series.type !== 'RangeArea' || series.type.indexOf('SplineRangeArea') > -1 || series.type.indexOf('RangeStepArea') > -1) ? points[pointIndex].yValue :
points[pointIndex].regions[0].y;
if (chart.primaryXAxis.valueType === 'Category') {
selectedPointX = points[pointIndex].x.toLocaleString();
}
else if (chart.primaryXAxis.valueType === 'DateTime') {
selectedPointX = new Date(points[pointIndex].xValue);
}
selectedPointValues.push({
x: selectedPointX, y: yValue, seriesIndex: seriesIndex,
pointIndex: pointIndex
});
}
}
}
var args = {
name: selectionComplete,
selectedDataValues: selectedPointValues,
cancel: false,
chart: chart
};
chart.trigger(selectionComplete, args);
};
/**
* Handles the selection logic for the chart.
*
* @param {Chart} chart - The chart instance.
* @param {Index} index - The index of the selected data point.
* @param {Element[]} selectedElements - The elements representing the selected data point.
* @returns {void}
*/
Selection.prototype.selection = function (chart, index, selectedElements) {
if (!(this.currentMode === 'Lasso')) {
if (!chart.isMultiSelect && (this.currentMode.indexOf('Drag') === -1 && this.styleId.indexOf('highlight') === -1 &&
chart.selectionMode !== 'None')) {
this.removeMultiSelectElements(chart, this.selectedDataIndexes, index, chart.series);
}
}
var indexValue = (this.rangeColorMappingEnabled()) ? 0 : index.series;
if (!isNullOrUndefined(selectedElements[0])) {
if (chart.visibleSeries[indexValue].isRectSeries) {
if (selectedElements[0].id) {
if (document.getElementById(selectedElements[0].id + '_Symbol')) {
selectedElements.push(getElement(selectedElements[0].id + '_Symbol'));
}
else if (selectedElements[0].id.indexOf('SeriesGroup') !== -1) {
if (document.getElementById(selectedElements[0].id.replace('SeriesGroup', 'SymbolGroup'))) {
selectedElements.push(getElement(selectedElements[0].id.replace('SeriesGroup', 'SymbolGroup')));
}
}
}
}
var isAdd = void 0;
var className = selectedElements[0] && (selectedElements[0].getAttribute('class') || '');
className = className.replace('e-chart-focused', '').trim();
var pClassName = selectedElements[0].parentNode &&
(selectedElements[0].parentNode.getAttribute('class') || '');
if (className !== '' && this.currentMode !== 'Cluster') {
this.findTrackballElements(selectedElements, className);
}
if (selectedElements[0] && className.indexOf(this.getSelectionClass(selectedElements[0].id)) > -1) {
this.removeStyles(selectedElements);
}
else if (selectedElements[0].parentNode && pClassName.indexOf(this.getSelectionClass(selectedElements[0].id)) > -1) {
this.removeStyles([selectedElements[0].parentNode]);
}
else {
this.previousSelectedEle = (chart.highlightMode !== 'None' || chart.legendSettings.enableHighlight) ? selectedElements : [];
this.applyStyles(selectedElements);
isAdd = true;
}
if (this.styleId.indexOf('highlight') > 0 && (chart.highlightMode !== 'None' || chart.legendSettings.enableHighlight)) {
this.addOrRemoveIndex(this.highlightDataIndexes, index, isAdd);
}
else {
this.addOrRemoveIndex(this.selectedDataIndexes, index, isAdd);
}
}
};
/**
* Handles the selection logic for clustered data points in the chart.
*
* @param {Chart} chart - The chart instance.
* @param {Index} index - The index of the selected clustered data point.
* @returns {void}
*/
Selection.prototype.clusterSelection = function (chart, index) {
this.selection(chart, index, this.getClusterElements(chart, new Index(index.series, index.point)));
};
/**
* Removes the multi-selected elements from the chart.
*
* @param {Chart} chart - The chart instance.
* @param {Index[]} index - The indices of the multi-selected elements to be removed.
* @param {Index} currentIndex - The index of the current selected element.
* @param {SeriesModel[]} seriesCollection - The collection of series in the chart.
* @returns {void}
*/
Selection.prototype.removeMultiSelectElements = function (chart, index, currentIndex, seriesCollection) {
var series;
for (var i = 0; i < index.length; i++) {
series = seriesCollection[index[i].series];
if ((this.isSeriesMode && !this.toEquals(index[i], currentIndex, this.isSeriesMode)) ||
(this.currentMode === 'Cluster' && !this.toEquals(index[i], currentIndex, false)) ||
(!this.isSeriesMode && this.toEquals(index[i], currentIndex, true) &&
!this.toEquals(index[i], currentIndex, false))) {
this.removeStyles(this.findElements(chart, series, index[i], '', false));
if (series.marker.visible) {
this.removeStyles(this.findElements(chart, series, index[i], '', true));
}
if (series.marker.dataLabel.visible) {
this.removeStyles(this.findElements(chart, series, index[i], '', false, true));
}
index.splice(i, 1);
i--;
}
}
};
/**
* Applies a blur effect to a specific chart or legend.
*
* @param {string} chartId - The ID of the chart or legend.
* @param {Series[]} visibleSeries - The collection of visible series in the chart.
* @param {boolean} isLegend - Indicates whether the blur effect should be applied to a legend. Defaults to false.
* @param {number} index - The index of the series or legend item to which the blur effect should be applied. Defaults to 0.
* @returns {void}
*/
Selection.prototype.blurEffect = function (chartId, visibleSeries, isLegend, index) {
if (isLegend === void 0) { isLegend = false; }
if (index === void 0) { index = 0; }
var visibility = (this.checkVisibility(this.highlightDataIndexes, this.chart) ||
this.checkVisibility(this.selectedDataIndexes, this.chart)); // legend click scenario
for (var _i = 0, visibleSeries_1 = visibleSeries; _i < visibleSeries_1.length; _i++) {
var series = visibleSeries_1[_i];
var legendIndex = void 0;
var legendStrokeColor = void 0;
if (this.rangeColorMappingEnabled()) {
if (isLegend === false) {
legendIndex = Object.keys(series.rangeColorPoints).indexOf(series.points[index].interior);
legendStrokeColor = series.points[index].interior;
}
else {
legendIndex = index;
legendStrokeColor = document.getElementById(chartId + '_chart_legend_shape_' + index).getAttribute('fill');
}
}
else {
legendIndex = series.index;
legendStrokeColor = this.chart.visibleSeries[series.index].interior;
}
if (series.visible) {
this.checkSelectionElements(getElement(chartId + 'SeriesGroup' + series.index), this.generateStyle(series), visibility, isLegend, legendIndex, legendStrokeColor);
if (series.marker.dataLabel.visible && !isNullOrUndefined(series.shapeElement)) {
this.checkSelectionElements(series.shapeElement, this.generateStyle(series), visibility, isLegend, legendIndex, legendStrokeColor);
this.checkSelectionElements(series.textElement, this.generateStyle(series), visibility, isLegend, legendIndex, legendStrokeColor);
}
if (!isNullOrUndefined(getElement(chartId + 'SymbolGroup' + series.index))) {
this.checkSelectionElements(getElement(chartId + 'SymbolGroup' + series.index), this.generateStyle(series), visibility, isLegend, legendIndex, legendStrokeColor);
}
}
}
};
/**
* Checks and updates the selection state of elements based on the provided criteria.
*
* @param {Element} element - The element to check for selection.
* @param {string} className - The class name used for selecting elements.
* @param {boolean} visibility - The visibility state of the element.
* @param {boolean} isLegend - Indicates whether the element is a legend. Defaults to true.
* @param {number} series - The index of the series associated with the element. Defaults to 0.
* @param {string} legendStrokeColor - The stroke color of the legend. Defaults to '#D3D3D3'.
* @returns {void}
*/
Selection.prototype.checkSelectionElements = function (element, className, visibility, isLegend, series, legendStrokeColor) {
if (isLegend === void 0) { isLegend = true; }
if (series === void 0) { series = 0; }
if (legendStrokeColor === void 0) { legendStrokeColor = '#D3D3D3'; }
var children = (this.isSeriesMode ?
element.childNodes || [element] : element.childNodes || element);
if (this.chart.selectionMode !== 'None' && (this.chart.highlightMode !== 'None' || this.chart.legendSettings.enableHighlight)) {
children = (element.childNodes || element);
}
if (this.chart.selectionMode === 'Cluster' && element.tagName.toLowerCase() === 'text' && element.id.indexOf('_Text_') >= 0) {
children = [element];
}
var elementClassName;
var parentClassName;
var legendShape;
var selectElement = element;
var isDataLabelTextElement = (this.chart.visibleSeries[this.rangeColorMappingEnabled() ? 0 : series].marker.dataLabel.visible && (element.id.indexOf('Text') > -1 || element.id.indexOf('TextShape') > -1) && element.tagName !== 'g');
for (var i = 0; i < children.length && !isDataLabelTextElement; i++) {
elementClassName = children[i].getAttribute('class') || '';
parentClassName = children[i].parentNode.getAttribute('class') || '';
if (this.chart.selectionMode !== 'None' && (this.chart.highlightMode !== 'None' || this.chart.legendSettings.enableHighlight)) {
className = elementClassName.indexOf('selection') > 0 ||
elementClassName.indexOf('highlight') > 0 ? elementClassName : className;
className = (parentClassName.indexOf('selection') > 0 ||
parentClassName.indexOf('highlight') > 0) ? parentClassName : className;
}
if (elementClassName.indexOf(className) === -1 &&
parentClassName.indexOf(className) === -1 && visibility) {
this.addSvgClass(children[i], this.unselected);
}
else {
selectElement = children[i];
this.removeSvgClass(children[i], this.unselected);
this.removeSvgClass(children[i].parentNode, this.unselected);
if (children[i].id !== '' && elementClassName.indexOf(this.unselected) !== -1 && parentClassName.indexOf(className) === -1) {
this.highlightAnimation(children[i], this.chart.series.length === 1 ? 0 :
this.indexFinder(children[i].id).series, 700, 0.3);
}
}
if (children[i].id.indexOf('Trackball') > 0 && selectElement.classList[0] === className) {
this.removeSvgClass(children[i], this.unselected);
this.removeSvgClass(children[i].parentNode, this.unselected);
this.addSvgClass(children[i], className);
}
}
if (element.id.indexOf('Symbol') > -1) {
if ((element.querySelectorAll('.' + className)[0]) && element.querySelectorAll('.' + className)[0].getAttribute('class')
=== className) {
var symbolEle = getElement(this.control.element.id + '_Series_' + element.id[element.id.length - 1]);
var seriesClassName = symbolEle && symbolEle.hasAttribute('class') ? symbolEle.getAttribute('class') : '';
if (seriesClassName.indexOf(this.unselected) > -1) {
this.removeSvgClass(symbolEle, this.unselected);
}
}
}
if (this.control.legendModule && this.control.legendSettings.visible && this.control.legendSettings.visible
&& !(isLegend && this.rangeColorMappingEnabled && (element === this.control.visibleSeries[0].textElement
|| element === this.control.visibleSeries[0].shapeElement))) {
legendShape = getElement(this.control.element.id + '_chart_legend_shape_' + series);
if (legendShape) {
if (legendShape.hasAttribute('class')) {
this.removeSvgClass(legendShape, legendShape.getAttribute('class'));
if (!isNullOrUndefined(this.chart.highlightColor && this.chart.highlightColor !== '') && !this.chart.legendSettings.enableHighlight) {
legendShape.setAttribute('stroke', legendStrokeColor);
if (this.chart.highlightPattern === 'None') {
legendShape.setAttribute('fill', legendStrokeColor);
}
}
}
elementClassName = selectElement.getAttribute('class') || '';
parentClassName = selectElement.parentNode.getAttribute('class') || '';
if (elementClassName.indexOf(className) === -1 && parentClassName.indexOf(className) === -1 && visibility) {
this.addSvgClass(legendShape, (this.chart.highlightMode === 'None' && this.chart.legendSettings.enableHighlight && (!this.chart.selectionModule || this.chart.selectionModule.selectedDataIndexes.length === 0)) ? className : this.unselected);
this.removeSvgClass(legendShape, className);
if (this.chart.highlightColor !== '' && !isNullOrUndefined(this.chart.highlightColor)) {
legendShape.setAttribute('stroke', this.control.visibleSeries[series].interior);
if (this.chart.highlightPattern === 'None') {
legendShape.setAttribute('fill', this.control.visibleSeries[series].interior);
}
}
}
else {
this.removeSvgClass(legendShape, this.unselected);
if (!isNullOrUndefined(this.chart.highlightColor) && this.chart.highlightColor !== '') {
legendShape.setAttribute('stroke', this.control.visibleSeries[series].interior);
if (this.chart.highlightPattern === 'None') {
legendShape.setAttribute('fill', this.control.visibleSeries[series].interior);
}
}
if ((elementClassName === '' && parentClassName === '') || elementClassName.trim() === 'EJ2-Trackball') {
this.removeSvgClass(legendShape, className);
}
else {
this.addSvgClass(legendShape, className);
if (className.indexOf('highlight') > 0 && this.chart.highlightColor !== '' && this.chart.highlightColor !== 'transparent' && !isNullOrUndefined(this.chart.highlightColor)) {
legendShape.setAttribute('stroke', this.chart.highlightColor);
if (this.styleId.indexOf('highlight') > 0 && this.chart.highlightPattern === 'None') {
legendShape.setAttribute('fill', this.chart.highlightColor);
}
}
}
}
var legendItemsId = void 0;
if (this.rangeColorMappingEnabled()) {
for (var i = 0; i < this.chart.rangeColorSettings.length; i++) {
legendItemsId = document.getElementById(this.chart.element.id + '_chart_legend_shape_' + i);
if (legendShape !== legendItemsId) {
this.addSvgClass(legendItemsId, this.unselected);
this.removeSvgClass(legendItemsId, className);
}
else if (isLegend === true) {
this.addSvgClass(legendItemsId, className);
}
if (elementClassName.indexOf(className) === -1 && isLegend === false) {
this.removeSvgClass(legendItemsId, this.unselected);
}
}
}
if (isLegend && parentClassName.indexOf(className) > -1) {
this.addSvgClass(legendShape, className);
}
}
}
};
/**
* Applies styles to the specified elements.
*
* @param {Element[]} elements - The elements to which styles will be applied.
* @returns {void}
*/
Selection.prototype.applyStyles = function (elements) {
for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) {
var element = elements_1[_i];
if (element) {
this.removeSvgClass(element.parentNode, this.unselected);
this.removeSvgClass(element, this.unselected);
if (this.chart.series[0].pointColorMapping === 'fill' || this.rangeColorMappingEnabled()) {
var className = this.getSelectionClass(element.id);
var index = className.indexOf('highlight') > -1 ? parseInt(className.split(this.chart.element.id + '_ej2_chart_highlight_series_')[1], 10) : parseInt(className.split(this.chart.element.id + '_ej2_chart_selection_series_')[1], 10);
var patternName = this.styleId.indexOf('highlight') > 0 ? this.chart.highlightPattern : this.chart.selectionPattern;
var pattern = void 0;
if (className.indexOf('highlight') > -1 || className.indexOf('selection') > -1) {
pattern = document.getElementById(this.chart.element.id + '_' + patternName + '_' + 'Selection' + '_' + index);
}
if (element.id.indexOf('legend') === -1 && element.id.indexOf('Text') === -1 && element.id.indexOf('TextShape') === -1 && element.id.indexOf('Group') === -1 && pattern != null) {
for (var i = 1; i < pattern.children.length; i++) {
pattern.children[i].setAttribute('fill', element.getAttribute('fill'));
pattern.children[i].setAttribute('stroke', element.getAttribute('fill'));
}
}
}
this.addSvgClass(element, this.getSelectionClass(element.id));
if (element.id.indexOf('Group') > 0) {
var seriesIndex = this.indexFinder(element.id);
for (var i = 0; i < element.children.length; i++) {
if (element.children[i].nodeName !== 'defs') {
this.stopElementAnimation(element.children[i], seriesIndex.series);
}
}
}
if (this.styleId.indexOf('highlight') > 0 && this.chart.highlightColor !== '' && !isNullOrUndefined(this.chart.highlightColor) && this.chart.highlightPattern === 'None' && this.chart.highlightColor !== 'transparent') {
if (element.id.indexOf('Group') > 0) {
for (var i = 0; i < element.children.length; i++) {
element.children[i].setAttribute('fill', (element.id.indexOf('Text') > -1
|| element.id.indexOf('TextShape') > -1) ? element.children[i].getAttribute('fill')
: this.chart.highlightColor);
}
}
else {
element.setAttribute('fill', (element.id.indexOf('Text') > -1
|| element.id.indexOf('TextShape') > -1) ? element.getAttribute('fill')
: this.chart.highlightColor);
}
}
}
}
};
/**
* Gets the CSS class for selection based on the provided identifier.
*
* @param {string} id - The identifier used to determine the selection class.
* @returns {string} - The CSS class for selection.
*/
Selection.prototype.getSelectionClass = function (id) {
return this.generateStyle(this.control.visibleSeries[this.indexFinder(id).series]);
};
/**
* Removes styles from the provided elements.
*
*