UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,260 lines (1,244 loc) • 49.6 kB
/** * DevExtreme (cjs/__internal/viz/chart_components/m_base_chart.js) * Version: 24.2.6 * Build date: Mon Mar 17 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.overlapping = exports.BaseChart = void 0; var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine")); var _index = require("../../../common/core/events/utils/index"); var _common = require("../../../core/utils/common"); var _extend = require("../../../core/utils/extend"); var _iterator = require("../../../core/utils/iterator"); var _type = require("../../../core/utils/type"); var _layout_manager = require("../../../viz/chart_components/layout_manager"); var trackerModule = _interopRequireWildcard(require("../../../viz/chart_components/tracker")); var _chart_theme_manager = require("../../../viz/components/chart_theme_manager"); var _data_validator = require("../../../viz/components/data_validator"); var _legend = require("../../../viz/components/legend"); var _data_source = require("../../../viz/core/data_source"); var _export = require("../../../viz/core/export"); var _loading_indicator = require("../../../viz/core/loading_indicator"); var _title = require("../../../viz/core/title"); var _tooltip = require("../../../viz/core/tooltip"); var _utils = require("../../../viz/core/utils"); var _base_series = require("../../../viz/series/base_series"); var _m_base_widget = _interopRequireDefault(require("../core/m_base_widget")); var _rolling_stock = require("./rolling_stock"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) { return null } var r = new WeakMap, t = new WeakMap; return (_getRequireWildcardCache = function(e) { return e ? t : r })(e) } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) { return e } if (null === e || "object" != typeof e && "function" != typeof e) { return { default: e } } var t = _getRequireWildcardCache(r); if (t && t.has(e)) { return t.get(e) } var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) { if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u] } } return n.default = e, t && t.set(e, n), n } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const { isArray: isArray } = Array; const REINIT_REFRESH_ACTION = "_reinit"; const REINIT_DATA_SOURCE_REFRESH_ACTION = "_updateDataSource"; const DATA_INIT_REFRESH_ACTION = "_dataInit"; const FORCE_RENDER_REFRESH_ACTION = "_forceRender"; const RESIZE_REFRESH_ACTION = "_resize"; const ACTIONS_BY_PRIORITY = ["_reinit", "_updateDataSource", "_dataInit", "_forceRender", "_resize"]; const DEFAULT_OPACITY = .3; const REFRESH_SERIES_DATA_INIT_ACTION_OPTIONS = ["series", "commonSeriesSettings", "dataPrepareSettings", "seriesSelectionMode", "pointSelectionMode", "synchronizeMultiAxes", "resolveLabelsOverlapping"]; const REFRESH_SERIES_FAMILIES_ACTION_OPTIONS = ["minBubbleSize", "maxBubbleSize", "barGroupPadding", "barGroupWidth", "negativesAsZeroes", "negativesAsZeros"]; const FORCE_RENDER_REFRESH_ACTION_OPTIONS = ["adaptiveLayout", "crosshair", "resolveLabelOverlapping", "adjustOnZoom", "stickyHovering"]; const FONT = "font"; function checkHeightRollingStock(rollingStocks, stubCanvas) { const canvasSize = stubCanvas.end - stubCanvas.start; let size = 0; rollingStocks.forEach((rollingStock => { size += rollingStock.getBoundingRect().width })); while (canvasSize < size) { size -= findAndKillSmallValue(rollingStocks) } } function findAndKillSmallValue(rollingStocks) { const smallestObject = rollingStocks.reduce(((prev, rollingStock, index) => { if (!rollingStock) { return prev } const value = rollingStock.value(); return value < prev.value ? { value: value, rollingStock: rollingStock, index: index } : prev }), { rollingStock: void 0, value: 1 / 0, index: void 0 }); smallestObject.rollingStock.getLabels()[0].draw(false); const { width: width } = smallestObject.rollingStock.getBoundingRect(); rollingStocks[smallestObject.index] = null; return width } function checkStackOverlap(rollingStocks) { let i; let j; let iLength; let jLength; let overlap = false; for (i = 0, iLength = rollingStocks.length - 1; i < iLength; i++) { for (j = i + 1, jLength = rollingStocks.length; j < jLength; j++) { if (i !== j && checkStacksOverlapping(rollingStocks[i], rollingStocks[j], true)) { overlap = true; break } } if (overlap) { break } } return overlap } function resolveLabelOverlappingInOneDirection(points, canvas, isRotated, isInverted, shiftFunction) { let customSorting = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : () => 0; const rollingStocks = []; const stubCanvas = { start: isRotated ? canvas.left : canvas.top, end: isRotated ? canvas.width - canvas.right : canvas.height - canvas.bottom }; let hasStackedSeries = false; let sortRollingStocks; points.forEach((p => { if (!p) { return } hasStackedSeries = hasStackedSeries || p.series.isStackedSeries() || p.series.isFullStackedSeries(); p.getLabels().forEach((l => { if (l.isVisible()) { rollingStocks.push(new _rolling_stock.RollingStock(l, isRotated, shiftFunction)) } })) })); if (hasStackedSeries) { if (Number(!isRotated) ^ Number(isInverted)) { rollingStocks.reverse() } sortRollingStocks = isInverted ? rollingStocks : sortRollingStocksByValue(rollingStocks) } else { const rollingStocksTmp = rollingStocks.slice(); sortRollingStocks = rollingStocks.sort(((a, b) => customSorting(a, b) || a.getInitialPosition() - b.getInitialPosition() || rollingStocksTmp.indexOf(a) - rollingStocksTmp.indexOf(b))) } if (!checkStackOverlap(sortRollingStocks)) { return false } checkHeightRollingStock(sortRollingStocks, stubCanvas); prepareOverlapStacks(sortRollingStocks); sortRollingStocks.reverse(); moveRollingStock(sortRollingStocks, stubCanvas); return true } function checkStacksOverlapping(firstRolling, secondRolling, inTwoSides) { if (!firstRolling || !secondRolling) { return } const firstRect = firstRolling.getBoundingRect(); const secondRect = secondRolling.getBoundingRect(); const oppositeOverlapping = inTwoSides ? firstRect.oppositeStart <= secondRect.oppositeStart && firstRect.oppositeEnd > secondRect.oppositeStart || secondRect.oppositeStart <= firstRect.oppositeStart && secondRect.oppositeEnd > firstRect.oppositeStart : true; return firstRect.end > secondRect.start && oppositeOverlapping } function sortRollingStocksByValue(rollingStocks) { const positiveRollingStocks = []; const negativeRollingStocks = []; rollingStocks.forEach((stock => { if (stock.value() > 0) { positiveRollingStocks.push(stock) } else { negativeRollingStocks.unshift(stock) } })); return positiveRollingStocks.concat(negativeRollingStocks) } function prepareOverlapStacks(rollingStocks) { let root; for (let i = 0; i < rollingStocks.length - 1; i += 1) { const currentRollingStock = root || rollingStocks[i]; if (checkStacksOverlapping(currentRollingStock, rollingStocks[i + 1])) { currentRollingStock.toChain(rollingStocks[i + 1]); rollingStocks[i + 1] = null; root = currentRollingStock } else { root = rollingStocks[i + 1] || currentRollingStock } } } function rollingStocksIsOut(rollingStock, canvas) { return rollingStock.getBoundingRect().end > canvas.end } function moveRollingStock(rollingStocks, canvas) { for (let i = 0; i < rollingStocks.length; i += 1) { const currentRollingStock = rollingStocks[i]; let shouldSetCanvas = true; if (null !== currentRollingStock && rollingStocksIsOut(currentRollingStock, canvas)) { const currentBBox = currentRollingStock.getBoundingRect(); for (let j = i + 1; j < rollingStocks.length; j += 1) { const nextRollingStock = rollingStocks[j]; if (nextRollingStock) { const nextBBox = nextRollingStock.getBoundingRect(); if (nextBBox.end > currentBBox.start - (currentBBox.end - canvas.end)) { nextRollingStock.toChain(currentRollingStock); shouldSetCanvas = false; break } } } } if (shouldSetCanvas) { null === currentRollingStock || void 0 === currentRollingStock || currentRollingStock.setRollingStockInCanvas(canvas) } } } function getLegendFields(name) { return { nameField: `${name}Name`, colorField: `${name}Color`, indexField: `${name}Index` } } function getLegendSettings(legendDataField) { const formatObjectFields = getLegendFields(legendDataField); return { getFormatObject(data) { const res = {}; res[formatObjectFields.indexField] = data.id; res[formatObjectFields.colorField] = data.states.normal.fill; res[formatObjectFields.nameField] = data.text; return res }, textField: formatObjectFields.nameField } } function checkOverlapping(firstRect, secondRect) { return (firstRect.x <= secondRect.x && secondRect.x <= firstRect.x + firstRect.width || firstRect.x >= secondRect.x && firstRect.x <= secondRect.x + secondRect.width) && (firstRect.y <= secondRect.y && secondRect.y <= firstRect.y + firstRect.height || firstRect.y >= secondRect.y && firstRect.y <= secondRect.y + secondRect.height) } const overlapping = exports.overlapping = { resolveLabelOverlappingInOneDirection: resolveLabelOverlappingInOneDirection }; const BaseChart = exports.BaseChart = _m_base_widget.default.inherit({ _eventsMap: { onSeriesClick: { name: "seriesClick" }, onPointClick: { name: "pointClick" }, onArgumentAxisClick: { name: "argumentAxisClick" }, onLegendClick: { name: "legendClick" }, onSeriesSelectionChanged: { name: "seriesSelectionChanged" }, onPointSelectionChanged: { name: "pointSelectionChanged" }, onSeriesHoverChanged: { name: "seriesHoverChanged" }, onPointHoverChanged: { name: "pointHoverChanged" }, onDone: { name: "done", actionSettings: { excludeValidators: ["disabled"] } }, onZoomStart: { name: "zoomStart" }, onZoomEnd: { name: "zoomEnd" } }, _fontFields: [`legend.${FONT}`, `legend.title.${FONT}`, `legend.title.subtitle.${FONT}`, `commonSeriesSettings.label.${FONT}`], _rootClassPrefix: "dxc", _rootClass: "dxc-chart", _initialChanges: ["INIT"], _themeDependentChanges: ["REFRESH_SERIES_REINIT"], _getThemeManagerOptions() { const themeOptions = this.callBase.apply(this, arguments); themeOptions.options = this.option(); return themeOptions }, _createThemeManager() { const chartOption = this.option(); const themeManager = new _chart_theme_manager.ThemeManager(this._getThemeManagerOptions()); themeManager.setTheme(chartOption.theme, chartOption.rtlEnabled); return themeManager }, _initCore() { this._canvasClipRect = this._renderer.clipRect(); this._createHtmlStructure(); this._createLegend(); this._createTracker(); this._needHandleRenderComplete = true; this.layoutManager = new _layout_manager.LayoutManager; this._createScrollBar(); _events_engine.default.on(this._$element, "contextmenu", (event => { if ((0, _index.isTouchEvent)(event) || (0, _index.isPointerEvent)(event)) { event.preventDefault() } })); _events_engine.default.on(this._$element, "MSHoldVisual", (event => { event.preventDefault() })) }, _getLayoutItems: _common.noop, _layoutManagerOptions() { return this._themeManager.getOptions("adaptiveLayout") }, _reinit() { (0, _utils.setCanvasValues)(this._canvas); this._reinitAxes(); this._requestChange(["DATA_SOURCE", "DATA_INIT", "CORRECT_AXIS", "FULL_RENDER"]) }, _correctAxes: _common.noop, _createHtmlStructure() { const renderer = this._renderer; const { root: root } = renderer; const createConstantLinesGroup = function() { return renderer.g().attr({ class: "dxc-constant-lines-group" }).linkOn(root, "constant-lines") }; this._constantLinesGroup = { dispose() { this.under.dispose(); this.above.dispose() }, linkOff() { this.under.linkOff(); this.above.linkOff() }, clear() { this.under.linkRemove().clear(); this.above.linkRemove().clear() }, linkAppend() { this.under.linkAppend(); this.above.linkAppend() } }; this._labelsAxesGroup = renderer.g().attr({ class: "dxc-elements-axes-group" }); const appendLabelsAxesGroup = () => { this._labelsAxesGroup.linkOn(root, "elements") }; this._backgroundRect = renderer.rect().attr({ fill: "gray", opacity: 1e-4 }).append(root); this._panesBackgroundGroup = renderer.g().attr({ class: "dxc-background" }).append(root); this._stripsGroup = renderer.g().attr({ class: "dxc-strips-group" }).linkOn(root, "strips"); this._gridGroup = renderer.g().attr({ class: "dxc-grids-group" }).linkOn(root, "grids"); this._panesBorderGroup = renderer.g().attr({ class: "dxc-border" }).linkOn(root, "border"); this._axesGroup = renderer.g().attr({ class: "dxc-axes-group" }).linkOn(root, "axes"); this._executeAppendBeforeSeries(appendLabelsAxesGroup); this._stripLabelAxesGroup = renderer.g().attr({ class: "dxc-strips-labels-group" }).linkOn(root, "strips-labels"); this._constantLinesGroup.under = createConstantLinesGroup(); this._seriesGroup = renderer.g().attr({ class: "dxc-series-group" }).linkOn(root, "series"); this._executeAppendAfterSeries(appendLabelsAxesGroup); this._constantLinesGroup.above = createConstantLinesGroup(); this._scaleBreaksGroup = renderer.g().attr({ class: "dxc-scale-breaks" }).linkOn(root, "scale-breaks"); this._labelsGroup = renderer.g().attr({ class: "dxc-labels-group" }).linkOn(root, "labels"); this._crosshairCursorGroup = renderer.g().attr({ class: "dxc-crosshair-cursor" }).linkOn(root, "crosshair"); this._legendGroup = renderer.g().attr({ class: "dxc-legend", "clip-path": this._getCanvasClipRectID() }).linkOn(root, "legend").linkAppend(root).enableLinks(); this._scrollBarGroup = renderer.g().attr({ class: "dxc-scroll-bar" }).linkOn(root, "scroll-bar") }, _executeAppendBeforeSeries() {}, _executeAppendAfterSeries() {}, _disposeObjectsInArray(propName, fieldNames) { (this[propName] || []).forEach((item => { if (fieldNames && item) { fieldNames.forEach((field => { var _item$field; null === (_item$field = item[field]) || void 0 === _item$field || _item$field.dispose() })) } else { null === item || void 0 === item || item.dispose() } })); this[propName] = null }, _disposeCore() { const disposeObject = propName => { if (this[propName]) { this[propName].dispose(); this[propName] = null } }; const unlinkGroup = name => { this[name].linkOff() }; const disposeObjectsInArray = this._disposeObjectsInArray; this._renderer.stopAllAnimations(); disposeObjectsInArray.call(this, "series"); disposeObject("_tracker"); disposeObject("_crosshair"); this.layoutManager = this._userOptions = this._canvas = this._groupsData = null; unlinkGroup("_stripsGroup"); unlinkGroup("_gridGroup"); unlinkGroup("_axesGroup"); unlinkGroup("_constantLinesGroup"); unlinkGroup("_stripLabelAxesGroup"); unlinkGroup("_panesBorderGroup"); unlinkGroup("_seriesGroup"); unlinkGroup("_labelsGroup"); unlinkGroup("_crosshairCursorGroup"); unlinkGroup("_legendGroup"); unlinkGroup("_scrollBarGroup"); unlinkGroup("_scaleBreaksGroup"); disposeObject("_canvasClipRect"); disposeObject("_panesBackgroundGroup"); disposeObject("_backgroundRect"); disposeObject("_stripsGroup"); disposeObject("_gridGroup"); disposeObject("_axesGroup"); disposeObject("_constantLinesGroup"); disposeObject("_stripLabelAxesGroup"); disposeObject("_panesBorderGroup"); disposeObject("_seriesGroup"); disposeObject("_labelsGroup"); disposeObject("_crosshairCursorGroup"); disposeObject("_legendGroup"); disposeObject("_scrollBarGroup"); disposeObject("_scaleBreaksGroup") }, _getAnimationOptions() { return this._themeManager.getOptions("animation") }, _getDefaultSize: () => ({ width: 400, height: 400 }), _getOption(name) { return this._themeManager.getOptions(name) }, _applySize(rect) { this._rect = rect.slice(); if (!this._changes.has("FULL_RENDER")) { this._processRefreshData("_resize") } }, _resize() { this._doRender(this.__renderOptions || { animate: false, isResize: true }) }, _trackerType: "ChartTracker", _createTracker() { this._tracker = new trackerModule[this._trackerType]({ seriesGroup: this._seriesGroup, renderer: this._renderer, tooltip: this._tooltip, legend: this._legend, eventTrigger: this._eventTrigger }) }, _getTrackerSettings() { return (0, _extend.extend)({ chart: this }, this._getSelectionModes()) }, _getSelectionModes() { const themeManager = this._themeManager; return { seriesSelectionMode: themeManager.getOptions("seriesSelectionMode"), pointSelectionMode: themeManager.getOptions("pointSelectionMode") } }, _updateTracker(trackerCanvases) { this._tracker.update(this._getTrackerSettings()); this._tracker.setCanvases({ left: 0, right: this._canvas.width, top: 0, bottom: this._canvas.height }, trackerCanvases) }, _createCanvasFromRect(rect) { const currentCanvas = this._canvas; return (0, _utils.setCanvasValues)({ left: rect[0], top: rect[1], right: currentCanvas.width - rect[2], bottom: currentCanvas.height - rect[3], width: currentCanvas.width, height: currentCanvas.height }) }, _doRender(_options) { if (0 === this._canvas.width && 0 === this._canvas.height) { return } this._resetIsReady(); const drawOptions = this._prepareDrawOptions(_options); const { recreateCanvas: recreateCanvas } = drawOptions; this._preserveOriginalCanvas(); if (recreateCanvas) { this.__currentCanvas = this._canvas } else { this._canvas = this.__currentCanvas } recreateCanvas && this._updateCanvasClipRect(this._canvas); this._canvas = this._createCanvasFromRect(this._rect); this._renderer.stopAllAnimations(true); this._cleanGroups(); const startTime = new Date; this._renderElements(drawOptions); this._lastRenderingTime = Number(new Date) - Number(startTime) }, _preserveOriginalCanvas() { this.__originalCanvas = this._canvas; this._canvas = (0, _extend.extend)({}, this._canvas) }, _layoutAxes: _common.noop, _renderElements(drawOptions) { const preparedOptions = this._prepareToRender(drawOptions); const isRotated = this._isRotated(); const isLegendInside = this._isLegendInside(); const trackerCanvases = []; (0, _extend.extend)({}, this._canvas); let argBusinessRange; let zoomMinArg; let zoomMaxArg; this._renderer.lock(); if (drawOptions.drawLegend && this._legend) { this._legendGroup.linkAppend() } this.layoutManager.setOptions(this._layoutManagerOptions()); const layoutTargets = this._getLayoutTargets(); this._layoutAxes((needSpace => { const axisDrawOptions = needSpace ? (0, _extend.extend)({}, drawOptions, { animate: false, recreateCanvas: true }) : drawOptions; const canvas = this._renderAxes(axisDrawOptions, preparedOptions); this._shrinkAxes(needSpace, canvas) })); this._applyClipRects(preparedOptions); this._appendSeriesGroups(); this._createCrosshairCursor(); layoutTargets.forEach((_ref => { let { canvas: canvas } = _ref; trackerCanvases.push({ left: canvas.left, right: canvas.width - canvas.right, top: canvas.top, bottom: canvas.height - canvas.bottom }) })); if (this._scrollBar) { argBusinessRange = this._argumentAxes[0].getTranslator().getBusinessRange(); if ("discrete" === argBusinessRange.axisType && argBusinessRange.categories && argBusinessRange.categories.length <= 1 || "discrete" !== argBusinessRange.axisType && argBusinessRange.min === argBusinessRange.max) { zoomMinArg = zoomMaxArg = void 0 } else { zoomMinArg = argBusinessRange.minVisible; zoomMaxArg = argBusinessRange.maxVisible } this._scrollBar.init(argBusinessRange, !this._argumentAxes[0].getOptions().valueMarginsEnabled).setPosition(zoomMinArg, zoomMaxArg) } this._updateTracker(trackerCanvases); this._updateLegendPosition(drawOptions, isLegendInside); this._applyPointMarkersAutoHiding(); this._renderSeries(drawOptions, isRotated, isLegendInside); this._renderGraphicObjects(); this._renderer.unlock() }, _updateLegendPosition: _common.noop, _createCrosshairCursor: _common.noop, _appendSeriesGroups() { this._seriesGroup.linkAppend(); this._labelsGroup.linkAppend(); this._appendAdditionalSeriesGroups() }, _renderSeries(drawOptions, isRotated, isLegendInside) { this._calculateSeriesLayout(drawOptions, isRotated); this._renderSeriesElements(drawOptions, isLegendInside) }, _calculateSeriesLayout(drawOptions, isRotated) { drawOptions.hideLayoutLabels = this.layoutManager.needMoreSpaceForPanesCanvas(this._getLayoutTargets(), isRotated) && !this._themeManager.getOptions("adaptiveLayout").keepLabels; this._updateSeriesDimensions(drawOptions) }, _getArgFilter: () => () => true, _getValFilter: () => () => true, _getPointsToAnimation(series) { const argViewPortFilter = this._getArgFilter(); return series.map((s => { const valViewPortFilter = this._getValFilter(s); return s.getPoints().filter((p => p.getOptions().visible && argViewPortFilter(p.argument) && (valViewPortFilter(p.getMinValue(true)) || valViewPortFilter(p.getMaxValue(true))))).length })) }, _renderSeriesElements(drawOptions, isLegendInside) { const { series: series } = this; const resolveLabelOverlapping = this._themeManager.getOptions("resolveLabelOverlapping"); const pointsToAnimation = this._getPointsToAnimation(series); series.forEach(((singleSeries, index) => { this._applyExtraSettings(singleSeries, drawOptions); const animationEnabled = drawOptions.animate && pointsToAnimation[index] <= drawOptions.animationPointsLimit && this._renderer.animationEnabled(); singleSeries.draw(animationEnabled, drawOptions.hideLayoutLabels, this._getLegendCallBack(singleSeries)) })); if ("none" === resolveLabelOverlapping) { this._adjustSeriesLabels(false) } else { this._locateLabels(resolveLabelOverlapping) } this._renderTrackers(isLegendInside); this._tracker.repairTooltip(); this._renderExtraElements(); this._clearCanvas(); this._seriesElementsDrawn = true }, _changesApplied() { if (this._seriesElementsDrawn) { this._seriesElementsDrawn = false; this._drawn(); this._renderCompleteHandler() } }, _locateLabels(resolveLabelOverlapping) { this._resolveLabelOverlapping(resolveLabelOverlapping) }, _renderExtraElements() {}, _clearCanvas() { this._canvas = this.__originalCanvas }, _resolveLabelOverlapping(resolveLabelOverlapping) { let func; switch (resolveLabelOverlapping) { case "stack": func = this._resolveLabelOverlappingStack; break; case "hide": func = this._resolveLabelOverlappingHide; break; case "shift": func = this._resolveLabelOverlappingShift } return (0, _type.isFunction)(func) && func.call(this) }, _getVisibleSeries() { return (0, _common.grep)(this.getAllSeries(), (series => series.isVisible())) }, _resolveLabelOverlappingHide() { const labels = []; let currentLabel; let nextLabel; let currentLabelRect; let nextLabelRect; let i; let j; let points; const series = this._getVisibleSeries(); for (i = 0; i < series.length; i++) { points = series[i].getVisiblePoints(); for (j = 0; j < points.length; j++) { labels.push.apply(labels, points[j].getLabels()) } } for (i = 0; i < labels.length; i++) { currentLabel = labels[i]; if (!currentLabel.isVisible()) { continue } currentLabelRect = currentLabel.getBoundingRect(); for (j = i + 1; j < labels.length; j++) { nextLabel = labels[j]; nextLabelRect = nextLabel.getBoundingRect(); if (checkOverlapping(currentLabelRect, nextLabelRect)) { nextLabel.draw(false) } } } }, _cleanGroups() { this._stripsGroup.linkRemove().clear(); this._gridGroup.linkRemove().clear(); this._axesGroup.linkRemove().clear(); this._constantLinesGroup.clear(); this._stripLabelAxesGroup.linkRemove().clear(); this._labelsGroup.linkRemove().clear(); this._crosshairCursorGroup.linkRemove().clear(); this._scaleBreaksGroup.linkRemove().clear() }, _allowLegendInsidePosition: () => false, _createLegend() { const legendSettings = getLegendSettings(this._legendDataField); this._legend = new _legend.Legend({ renderer: this._renderer, widget: this, group: this._legendGroup, backgroundClass: "dxc-border", itemGroupClass: "dxc-item", titleGroupClass: "dxc-title", textField: legendSettings.textField, getFormatObject: legendSettings.getFormatObject, allowInsidePosition: this._allowLegendInsidePosition() }); this._updateLegend(); this._layout.add(this._legend) }, _updateLegend() { const themeManager = this._themeManager; const legendOptions = themeManager.getOptions("legend"); const legendData = this._getLegendData(); legendOptions.containerBackgroundColor = themeManager.getOptions("containerBackgroundColor"); legendOptions._incidentOccurred = this._incidentOccurred; this._legend.update(legendData, legendOptions, themeManager.theme("legend").title); this._change(["LAYOUT"]) }, _prepareDrawOptions(drawOptions) { const animationOptions = this._getAnimationOptions(); const options = (0, _extend.extend)({}, { force: false, adjustAxes: true, drawLegend: true, drawTitle: true, animate: animationOptions.enabled, animationPointsLimit: animationOptions.maxPointCountSupported }, drawOptions, this.__renderOptions); if (!(0, _type.isDefined)(options.recreateCanvas)) { options.recreateCanvas = options.adjustAxes && options.drawLegend && options.drawTitle } return options }, _processRefreshData(newRefreshAction) { const currentRefreshActionPosition = ACTIONS_BY_PRIORITY.indexOf(this._currentRefreshData); const newRefreshActionPosition = ACTIONS_BY_PRIORITY.indexOf(newRefreshAction); if (!this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition) { this._currentRefreshData = newRefreshAction } this._requestChange(["REFRESH"]) }, _getLegendData() { return (0, _utils.map)(this._getLegendTargets(), (item => { const { legendData: legendData } = item; const style = item.getLegendStyles; let { opacity: opacity } = style.normal; if (!item.visible) { if (!(0, _type.isDefined)(opacity) || opacity > .3) { opacity = .3 } legendData.textOpacity = .3 } const opacityStyle = { opacity: opacity }; legendData.states = { hover: (0, _extend.extend)({}, style.hover, opacityStyle), selection: (0, _extend.extend)({}, style.selection, opacityStyle), normal: (0, _extend.extend)({}, style.normal, opacityStyle) }; return legendData })) }, _getLegendOptions(item) { return { legendData: { text: item[this._legendItemTextField], id: item.index, visible: true }, getLegendStyles: item.getLegendStyles(), visible: item.isVisible() } }, _disposeSeries(seriesIndex) { var _this$series; if (this.series) { if ((0, _type.isDefined)(seriesIndex)) { this.series[seriesIndex].dispose(); this.series.splice(seriesIndex, 1) } else { this.series.forEach((s => s.dispose())); this.series.length = 0 } } if (!(null !== (_this$series = this.series) && void 0 !== _this$series && _this$series.length)) { this.series = [] } }, _disposeSeriesFamilies() { (this.seriesFamilies || []).forEach((family => { family.dispose() })); this.seriesFamilies = null; this._needHandleRenderComplete = true }, _optionChanged(arg) { this._themeManager.resetOptions(arg.name); this.callBase.apply(this, arguments) }, _applyChanges() { this._themeManager.update(this._options.silent()); this.callBase(...arguments) }, _optionChangesMap: { animation: "ANIMATION", dataSource: "DATA_SOURCE", palette: "PALETTE", paletteExtensionMode: "PALETTE", legend: "FORCE_DATA_INIT", seriesTemplate: "FORCE_DATA_INIT", export: "FORCE_RENDER", valueAxis: "AXES_AND_PANES", argumentAxis: "AXES_AND_PANES", commonAxisSettings: "AXES_AND_PANES", panes: "AXES_AND_PANES", commonPaneSettings: "AXES_AND_PANES", defaultPane: "AXES_AND_PANES", containerBackgroundColor: "AXES_AND_PANES", rotated: "ROTATED", autoHidePointMarkers: "REFRESH_SERIES_REINIT", customizePoint: "REFRESH_SERIES_REINIT", customizeLabel: "REFRESH_SERIES_REINIT", scrollBar: "SCROLL_BAR" }, _optionChangesOrder: ["ROTATED", "PALETTE", "REFRESH_SERIES_REINIT", "USE_SPIDER_WEB", "AXES_AND_PANES", "INIT", "REINIT", "DATA_SOURCE", "REFRESH_SERIES_DATA_INIT", "DATA_INIT", "FORCE_DATA_INIT", "REFRESH_AXES", "CORRECT_AXIS"], _customChangesOrder: ["ANIMATION", "REFRESH_SERIES_FAMILIES", "FORCE_FIRST_DRAWING", "FORCE_DRAWING", "FORCE_RENDER", "VISUAL_RANGE", "SCROLL_BAR", "REINIT", "REFRESH", "FULL_RENDER"], _change_ANIMATION() { this._renderer.updateAnimationOptions(this._getAnimationOptions()) }, _change_DATA_SOURCE() { this._needHandleRenderComplete = true; this._updateDataSource() }, _change_PALETTE() { this._themeManager.updatePalette(); this._refreshSeries("DATA_INIT") }, _change_REFRESH_SERIES_DATA_INIT() { this._refreshSeries("DATA_INIT") }, _change_DATA_INIT() { if ((!this.series || this.needToPopulateSeries) && !this._changes.has("FORCE_DATA_INIT")) { this._dataInit() } }, _change_FORCE_DATA_INIT() { this._dataInit() }, _change_REFRESH_SERIES_FAMILIES() { this._processSeriesFamilies(); this._populateBusinessRange(); this._processRefreshData("_forceRender") }, _change_FORCE_RENDER() { this._processRefreshData("_forceRender") }, _change_AXES_AND_PANES() { this._refreshSeries("INIT") }, _change_ROTATED() { this._createScrollBar(); this._refreshSeries("INIT") }, _change_REFRESH_SERIES_REINIT() { this._refreshSeries("INIT") }, _change_REFRESH_AXES() { (0, _utils.setCanvasValues)(this._canvas); this._reinitAxes(); this._requestChange(["CORRECT_AXIS", "FULL_RENDER"]) }, _change_SCROLL_BAR() { this._createScrollBar(); this._processRefreshData("_forceRender") }, _change_REINIT() { this._processRefreshData("_reinit") }, _change_FORCE_DRAWING() { this._resetComponentsAnimation() }, _change_FORCE_FIRST_DRAWING() { this._resetComponentsAnimation(true) }, _resetComponentsAnimation(isFirstDrawing) { this.series.forEach((s => { s.resetApplyingAnimation(isFirstDrawing) })); this._resetAxesAnimation(isFirstDrawing) }, _resetAxesAnimation: _common.noop, _refreshSeries(actionName) { this.needToPopulateSeries = true; this._requestChange([actionName]) }, _change_CORRECT_AXIS() { this._correctAxes() }, _doRefresh() { const methodName = this._currentRefreshData; if (methodName) { this._currentRefreshData = null; this._renderer.stopAllAnimations(true); this[methodName]() } }, _updateCanvasClipRect(canvas) { const width = Math.max(canvas.width - canvas.left - canvas.right, 0); const height = Math.max(canvas.height - canvas.top - canvas.bottom, 0); this._canvasClipRect.attr({ x: canvas.left, y: canvas.top, width: width, height: height }); this._backgroundRect.attr({ x: canvas.left, y: canvas.top, width: width, height: height }) }, _getCanvasClipRectID() { return this._canvasClipRect.id }, _dataSourceChangedHandler() { if (this._changes.has("INIT")) { this._requestChange(["DATA_INIT"]) } else { this._requestChange(["FORCE_DATA_INIT"]) } }, _dataInit() { this._dataSpecificInit(true) }, _processSingleSeries(singleSeries) { singleSeries.createPoints(false) }, _handleSeriesDataUpdated() { if (this._getVisibleSeries().some((s => s.useAggregation()))) { this._populateMarginOptions() } this.series.forEach((s => this._processSingleSeries(s)), this) }, _dataSpecificInit(needRedraw) { if (!this.series || this.needToPopulateSeries) { this.series = this._populateSeries() } this._repopulateSeries(); this._seriesPopulatedHandlerCore(); this._populateBusinessRange(); this._tracker.updateSeries(this.series, this._changes.has("INIT")); this._updateLegend(); if (needRedraw) { this._requestChange(["FULL_RENDER"]) } }, _forceRender() { this._doRender({ force: true }) }, _repopulateSeries() { const themeManager = this._themeManager; const data = this._dataSourceItems(); const dataValidatorOptions = themeManager.getOptions("dataPrepareSettings"); const seriesTemplate = themeManager.getOptions("seriesTemplate"); if (seriesTemplate) { this._populateSeries(data) } this._groupSeries(); const parsedData = (0, _data_validator.validateData)(data, this._groupsData, this._incidentOccurred, dataValidatorOptions); themeManager.resetPalette(); this.series.forEach((singleSeries => { singleSeries.updateData(parsedData[singleSeries.getArgumentField()]) })); this._handleSeriesDataUpdated() }, _renderCompleteHandler() { let allSeriesInited = true; if (this._needHandleRenderComplete) { this.series.forEach((s => { allSeriesInited = allSeriesInited && s.canRenderCompleteHandle() })); if (allSeriesInited) { this._needHandleRenderComplete = false; this._eventTrigger("done", { target: this }) } } }, _dataIsReady() { return (0, _type.isDefined)(this.option("dataSource")) && this._dataIsLoaded() }, _populateSeriesOptions(data) { const themeManager = this._themeManager; const seriesTemplate = themeManager.getOptions("seriesTemplate"); const seriesOptions = seriesTemplate ? (0, _utils.processSeriesTemplate)(seriesTemplate, data || []) : this.option("series"); const allSeriesOptions = isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : []; const extraOptions = this._getExtraOptions(); let particularSeriesOptions; let seriesTheme; const seriesThemes = []; const seriesVisibilityChanged = target => { this._specialProcessSeries(); this._populateBusinessRange(target && target.getValueAxis(), true); this._renderer.stopAllAnimations(true); this._updateLegend(); this._requestChange(["FULL_RENDER"]) }; for (let i = 0; i < allSeriesOptions.length; i++) { particularSeriesOptions = (0, _extend.extend)(true, {}, allSeriesOptions[i], extraOptions); if (!(0, _type.isDefined)(particularSeriesOptions.name) || "" === particularSeriesOptions.name) { particularSeriesOptions.name = `Series ${(i+1).toString()}` } particularSeriesOptions.rotated = this._isRotated(); particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint"); particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel"); particularSeriesOptions.visibilityChanged = seriesVisibilityChanged; particularSeriesOptions.incidentOccurred = this._incidentOccurred; seriesTheme = themeManager.getOptions("series", particularSeriesOptions, allSeriesOptions.length); if (this._checkPaneName(seriesTheme)) { seriesThemes.push(seriesTheme) } } return seriesThemes }, _populateSeries(data) { var _this$series3; const seriesBasis = []; const incidentOccurred = this._incidentOccurred; const seriesThemes = this._populateSeriesOptions(data); let particularSeries; let disposeSeriesFamilies = false; this.needToPopulateSeries = false; seriesThemes.forEach((theme => { var _this$series2; const curSeries = null === (_this$series2 = this.series) || void 0 === _this$series2 ? void 0 : _this$series2.find((s => s.name === theme.name && !seriesBasis.map((sb => sb.series)).includes(s))); if (curSeries && curSeries.type === theme.type) { seriesBasis.push({ series: curSeries, options: theme }) } else { seriesBasis.push({ options: theme }); disposeSeriesFamilies = true } })); 0 !== (null === (_this$series3 = this.series) || void 0 === _this$series3 ? void 0 : _this$series3.length) && this._tracker.clearHover(); (0, _iterator.reverseEach)(this.series, ((index, series) => { if (!seriesBasis.some((s => series === s.series))) { this._disposeSeries(index); disposeSeriesFamilies = true } })); !disposeSeriesFamilies && (disposeSeriesFamilies = seriesBasis.some((sb => sb.series.name !== seriesThemes[sb.series.index].name))); this.series = []; disposeSeriesFamilies && this._disposeSeriesFamilies(); this._themeManager.resetPalette(); const eventPipe = data => { this.series.forEach((currentSeries => { currentSeries.notify(data) })) }; seriesBasis.forEach((basis => { var _this$_argumentAxes; const seriesTheme = basis.options; const argumentAxis = (null === (_this$_argumentAxes = this._argumentAxes) || void 0 === _this$_argumentAxes ? void 0 : _this$_argumentAxes.filter((a => a.pane === seriesTheme.pane))[0]) ?? this.getArgumentAxis(); const renderSettings = { commonSeriesModes: this._getSelectionModes(), argumentAxis: argumentAxis, valueAxis: this._getValueAxis(seriesTheme.pane, seriesTheme.axis) }; if (basis.series) { particularSeries = basis.series; particularSeries.updateOptions(seriesTheme, renderSettings) } else { particularSeries = new _base_series.Series((0, _extend.extend)({ renderer: this._renderer, seriesGroup: this._seriesGroup, labelsGroup: this._labelsGroup, eventTrigger: this._eventTrigger, eventPipe: eventPipe, incidentOccurred: incidentOccurred }, renderSettings), seriesTheme) } if (!particularSeries.isUpdated) { incidentOccurred("E2101", [seriesTheme.type]) } else { particularSeries.index = this.series.length; this.series.push(particularSeries) } })); return this.series }, getStackedPoints(point) { const stackName = point.series.getStackName(); return this._getVisibleSeries().reduce(((stackPoints, series) => { if (!(0, _type.isDefined)(series.getStackName()) || !(0, _type.isDefined)(stackName) || stackName === series.getStackName()) { stackPoints = stackPoints.concat(series.getPointsByArg(point.argument)) } return stackPoints }), []) }, getAllSeries: function() { return (this.series || []).slice() }, getSeriesByName: function(name) { const found = (this.series || []).find((singleSeries => singleSeries.name === name)); return found || null }, getSeriesByPos: function(pos) { return (this.series || [])[pos] }, clearSelection: function() { this._tracker.clearSelection() }, hideTooltip() { this._tracker._hideTooltip() }, clearHover() { this._tracker.clearHover() }, render(renderOptions) { this.__renderOptions = renderOptions; this.__forceRender = renderOptions && renderOptions.force; this.callBase.apply(this, arguments); this.__renderOptions = this.__forceRender = null; return this }, refresh() { this._disposeSeries(); this._disposeSeriesFamilies(); this._requestChange(["CONTAINER_SIZE", "REFRESH_SERIES_REINIT"]) }, _getMinSize() { const adaptiveLayout = this._layoutManagerOptions(); return [adaptiveLayout.width, adaptiveLayout.height] }, _change_REFRESH() { if (!this._changes.has("INIT")) { this._doRefresh() } else { this._currentRefreshData = null } }, _change_FULL_RENDER() { this._forceRender() }, _change_INIT() { this._reinit() }, _stopCurrentHandling() { if (this._disposed) { return } this._tracker.stopCurrentHandling() } }); REFRESH_SERIES_DATA_INIT_ACTION_OPTIONS.forEach((name => { BaseChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_DATA_INIT" })); FORCE_RENDER_REFRESH_ACTION_OPTIONS.forEach((name => { BaseChart.prototype._optionChangesMap[name] = "FORCE_RENDER" })); REFRESH_SERIES_FAMILIES_ACTION_OPTIONS.forEach((name => { BaseChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_FAMILIES" })); BaseChart.addPlugin(_export.plugin); BaseChart.addPlugin(_title.plugin); BaseChart.addPlugin(_data_source.plugin); BaseChart.addPlugin(_tooltip.plugin); BaseChart.addPlugin(_loading_indicator.plugin); const { _change_TITLE: _change_TITLE } = BaseChart.prototype; BaseChart.prototype._change_TITLE = function() { _change_TITLE.apply(this, arguments); this._change(["FORCE_RENDER"]) };