devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,164 lines (1,138 loc) • 59 kB
JavaScript
/**
* DevExtreme (esm/viz/chart.js)
* Version: 21.1.4
* Build date: Mon Jun 21 2021
*
* Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import {
noop
} from "../core/utils/common";
import {
extend as _extend
} from "../core/utils/extend";
import {
inArray
} from "../core/utils/array";
import {
hasWindow
} from "../core/utils/window";
import {
each as _each
} from "../core/utils/iterator";
import registerComponent from "../core/component_registrator";
import {
prepareSegmentRectPoints
} from "./utils";
import {
map as _map,
getLog,
getCategoriesInfo,
updatePanesCanvases,
convertVisualRangeObject,
PANE_PADDING,
normalizePanesHeight,
rangesAreEqual,
isRelativeHeightPane
} from "./core/utils";
import {
type,
isDefined as _isDefined
} from "../core/utils/type";
import {
getPrecision
} from "../core/utils/math";
import {
overlapping
} from "./chart_components/base_chart";
import multiAxesSynchronizer from "./chart_components/multi_axes_synchronizer";
import {
AdvancedChart
} from "./chart_components/advanced_chart";
import {
ScrollBar
} from "./chart_components/scroll_bar";
import {
Crosshair
} from "./chart_components/crosshair";
import rangeDataCalculator from "./series/helpers/range_data_calculator";
import {
LayoutManager
} from "./chart_components/layout_manager";
import {
Range
} from "./translators/range";
var DEFAULT_PANE_NAME = "default";
var VISUAL_RANGE = "VISUAL_RANGE";
var DEFAULT_PANES = [{
name: DEFAULT_PANE_NAME,
border: {}
}];
var DISCRETE = "discrete";
var _isArray = Array.isArray;
function getFirstAxisNameForPane(axes, paneName, defaultPane) {
var result;
for (var i = 0; i < axes.length; i++) {
if (axes[i].pane === paneName || void 0 === axes[i].pane && paneName === defaultPane) {
result = axes[i].name;
break
}
}
if (!result) {
result = axes[0].name
}
return result
}
function changeVisibilityAxisGrids(axis, gridVisibility, minorGridVisibility) {
var gridOpt = axis.getOptions().grid;
var minorGridOpt = axis.getOptions().minorGrid;
gridOpt.visible = gridVisibility;
minorGridOpt && (minorGridOpt.visible = minorGridVisibility)
}
function hideGridsOnNonFirstValueAxisForPane(axesForPane) {
var axisShown = false;
var hiddenStubAxis = [];
var minorGridVisibility = axesForPane.some((function(axis) {
var minorGridOptions = axis.getOptions().minorGrid;
return minorGridOptions && minorGridOptions.visible
}));
var gridVisibility = axesForPane.some((function(axis) {
var gridOptions = axis.getOptions().grid;
return gridOptions && gridOptions.visible
}));
if (axesForPane.length > 1) {
axesForPane.forEach((function(axis) {
var gridOpt = axis.getOptions().grid;
if (axisShown) {
changeVisibilityAxisGrids(axis, false, false)
} else if (gridOpt && gridOpt.visible) {
if (axis.getTranslator().getBusinessRange().isEmpty()) {
changeVisibilityAxisGrids(axis, false, false);
hiddenStubAxis.push(axis)
} else {
axisShown = true;
changeVisibilityAxisGrids(axis, gridVisibility, minorGridVisibility)
}
}
}));
!axisShown && hiddenStubAxis.length && changeVisibilityAxisGrids(hiddenStubAxis[0], gridVisibility, minorGridVisibility)
}
}
function findAxisOptions(valueAxes, valueAxesOptions, axisName) {
var result;
var axInd;
for (axInd = 0; axInd < valueAxesOptions.length; axInd++) {
if (valueAxesOptions[axInd].name === axisName) {
result = valueAxesOptions[axInd];
result.priority = axInd;
break
}
}
if (!result) {
for (axInd = 0; axInd < valueAxes.length; axInd++) {
if (valueAxes[axInd].name === axisName) {
result = valueAxes[axInd].getOptions();
result.priority = valueAxes[axInd].priority;
break
}
}
}
return result
}
function findAxis(paneName, axisName, axes) {
var axis;
var i;
for (i = 0; i < axes.length; i++) {
axis = axes[i];
if (axis.name === axisName && axis.pane === paneName) {
return axis
}
}
if (paneName) {
return findAxis(void 0, axisName, axes)
}
}
function compareAxes(a, b) {
return a.priority - b.priority
}
function doesPaneExist(panes, paneName) {
var found = false;
_each(panes, (function(_, pane) {
if (pane.name === paneName) {
found = true;
return false
}
}));
return found
}
function accumulate(field, src1, src2, auxSpacing) {
var val1 = src1[field] || 0;
var val2 = src2[field] || 0;
return val1 + val2 + (val1 && val2 ? auxSpacing : 0)
}
function pickMax(field, src1, src2) {
return pickMaxValue(src1[field], src2[field])
}
function pickMaxValue(val1, val2) {
return Math.max(val1 || 0, val2 || 0)
}
function getAxisMargins(axis) {
return axis.getMargins()
}
function getHorizontalAxesMargins(axes, getMarginsFunc) {
return axes.reduce((function(margins, axis) {
var _axis$getOrthogonalAx;
var axisMargins = getMarginsFunc(axis);
var paneMargins = margins.panes[axis.pane] = margins.panes[axis.pane] || {};
var spacing = axis.getMultipleAxesSpacing();
paneMargins.top = accumulate("top", paneMargins, axisMargins, spacing);
paneMargins.bottom = accumulate("bottom", paneMargins, axisMargins, spacing);
paneMargins.left = pickMax("left", paneMargins, axisMargins);
paneMargins.right = pickMax("right", paneMargins, axisMargins);
margins.top = pickMax("top", paneMargins, margins);
margins.bottom = pickMax("bottom", paneMargins, margins);
margins.left = pickMax("left", paneMargins, margins);
margins.right = pickMax("right", paneMargins, margins);
var orthogonalAxis = null === (_axis$getOrthogonalAx = axis.getOrthogonalAxis) || void 0 === _axis$getOrthogonalAx ? void 0 : _axis$getOrthogonalAx.call(axis);
if (orthogonalAxis && orthogonalAxis.customPositionIsAvailable() && (!axis.customPositionIsBoundaryOrthogonalAxis() || !orthogonalAxis.customPositionEqualsToPredefined())) {
margins[orthogonalAxis.getResolvedBoundaryPosition()] = 0
}
return margins
}), {
panes: {}
})
}
function getVerticalAxesMargins(axes) {
return axes.reduce((function(margins, axis) {
var axisMargins = axis.getMargins();
var paneMargins = margins.panes[axis.pane] = margins.panes[axis.pane] || {};
var spacing = axis.getMultipleAxesSpacing();
paneMargins.top = pickMax("top", paneMargins, axisMargins);
paneMargins.bottom = pickMax("bottom", paneMargins, axisMargins);
paneMargins.left = accumulate("left", paneMargins, axisMargins, spacing);
paneMargins.right = accumulate("right", paneMargins, axisMargins, spacing);
margins.top = pickMax("top", paneMargins, margins);
margins.bottom = pickMax("bottom", paneMargins, margins);
margins.left = pickMax("left", paneMargins, margins);
margins.right = pickMax("right", paneMargins, margins);
return margins
}), {
panes: {}
})
}
function performActionOnAxes(axes, action, actionArgument1, actionArgument2, actionArgument3) {
axes.forEach((function(axis) {
axis[action](actionArgument1 && actionArgument1[axis.pane], actionArgument2 && actionArgument2[axis.pane] || actionArgument2, actionArgument3)
}))
}
function shrinkCanvases(isRotated, canvases, sizes, verticalMargins, horizontalMargins) {
function getMargin(side, margins, pane) {
var m = -1 === (isRotated ? ["left", "right"] : ["top", "bottom"]).indexOf(side) ? margins : margins.panes[pane] || {};
return m[side]
}
function getMaxMargin(side, margins1, margins2, pane) {
return pickMaxValue(getMargin(side, margins1, pane), getMargin(side, margins2, pane))
}
var getOriginalField = field => "original".concat(field[0].toUpperCase()).concat(field.slice(1));
function shrink(canvases, paneNames, sizeField, startMargin, endMargin, oppositeMargins) {
paneNames = paneNames.sort((p1, p2) => canvases[p2][startMargin] - canvases[p1][startMargin]);
paneNames.forEach(pane => {
var canvas = canvases[pane];
oppositeMargins.forEach(margin => {
canvas[margin] = canvas[getOriginalField(margin)] + getMaxMargin(margin, verticalMargins, horizontalMargins, pane)
})
});
var firstPane = canvases[paneNames[0]];
var emptySpace = paneNames.reduce((space, paneName) => {
space -= getMaxMargin(startMargin, verticalMargins, horizontalMargins, paneName) + getMaxMargin(endMargin, verticalMargins, horizontalMargins, paneName);
return space
}, firstPane[sizeField] - firstPane[getOriginalField(endMargin)] - canvases[paneNames[paneNames.length - 1]][getOriginalField(startMargin)]) - PANE_PADDING * (paneNames.length - 1);
emptySpace -= Object.keys(sizes).reduce((prev, key) => prev + (!isRelativeHeightPane(sizes[key]) ? sizes[key].height : 0), 0);
paneNames.reduce((offset, pane) => {
var canvas = canvases[pane];
var paneSize = sizes[pane];
offset -= getMaxMargin(endMargin, verticalMargins, horizontalMargins, pane);
canvas[endMargin] = firstPane[sizeField] - offset;
offset -= !isRelativeHeightPane(paneSize) ? paneSize.height : Math.floor(emptySpace * paneSize.height);
canvas[startMargin] = offset;
offset -= getMaxMargin(startMargin, verticalMargins, horizontalMargins, pane) + PANE_PADDING;
return offset
}, firstPane[sizeField] - firstPane[getOriginalField(endMargin)] - (emptySpace < 0 ? emptySpace : 0))
}
var paneNames = Object.keys(canvases);
if (!isRotated) {
shrink(canvases, paneNames, "height", "top", "bottom", ["left", "right"])
} else {
shrink(canvases, paneNames, "width", "left", "right", ["top", "bottom"])
}
return canvases
}
function drawAxesWithTicks(axes, condition, canvases, panesBorderOptions) {
if (condition) {
performActionOnAxes(axes, "createTicks", canvases);
multiAxesSynchronizer.synchronize(axes)
}
performActionOnAxes(axes, "draw", !condition && canvases, panesBorderOptions)
}
function shiftAxis(side1, side2) {
var shifts = {};
return function(axis) {
if (!axis.customPositionIsAvailable() || axis.customPositionEqualsToPredefined()) {
var shift = shifts[axis.pane] = shifts[axis.pane] || {
top: 0,
left: 0,
bottom: 0,
right: 0
};
var spacing = axis.getMultipleAxesSpacing();
var margins = axis.getMargins();
axis.shift(shift);
shift[side1] = accumulate(side1, shift, margins, spacing);
shift[side2] = accumulate(side2, shift, margins, spacing)
} else {
axis.shift({
top: 0,
left: 0,
bottom: 0,
right: 0
})
}
}
}
function getCommonSize(side, margins) {
var size = 0;
var pane;
var paneMargins;
for (pane in margins.panes) {
paneMargins = margins.panes[pane];
size += "height" === side ? paneMargins.top + paneMargins.bottom : paneMargins.left + paneMargins.right
}
return size
}
function checkUsedSpace(sizeShortage, side, axes, getMarginFunc) {
var size = 0;
if (sizeShortage[side] > 0) {
size = getCommonSize(side, getMarginFunc(axes, getAxisMargins));
performActionOnAxes(axes, "hideTitle");
sizeShortage[side] -= size - getCommonSize(side, getMarginFunc(axes, getAxisMargins))
}
if (sizeShortage[side] > 0) {
performActionOnAxes(axes, "hideOuterElements")
}
}
function axisAnimationEnabled(drawOptions, pointsToAnimation) {
var pointsCount = pointsToAnimation.reduce((sum, count) => sum + count, 0) / pointsToAnimation.length;
return drawOptions.animate && pointsCount <= drawOptions.animationPointsLimit
}
function collectMarkersInfoBySeries(allSeries, filteredSeries, argAxis) {
var series = [];
var overloadedSeries = {};
var argVisualRange = argAxis.visualRange();
var argTranslator = argAxis.getTranslator();
var argViewPortFilter = rangeDataCalculator.getViewPortFilter(argVisualRange || {});
filteredSeries.forEach(s => {
var valAxis = s.getValueAxis();
var valVisualRange = valAxis.getCanvasRange();
var valTranslator = valAxis.getTranslator();
var seriesIndex = allSeries.indexOf(s);
var valViewPortFilter = rangeDataCalculator.getViewPortFilter(valVisualRange || {});
overloadedSeries[seriesIndex] = {};
filteredSeries.forEach(sr => overloadedSeries[seriesIndex][allSeries.indexOf(sr)] = 0);
var seriesPoints = [];
s.getPoints().filter(p => p.getOptions().visible && argViewPortFilter(p.argument) && (valViewPortFilter(p.getMinValue(true)) || valViewPortFilter(p.getMaxValue(true)))).forEach(p => {
var tp = {
seriesIndex: seriesIndex,
argument: p.argument,
value: p.getMaxValue(true),
size: p.bubbleSize || p.getOptions().size
};
if (p.getMinValue(true) !== p.getMaxValue(true)) {
var mp = _extend({}, tp);
mp.value = p.getMinValue(true);
mp.x = argTranslator.to(mp.argument, 1);
mp.y = valTranslator.to(mp.value, 1);
seriesPoints.push(mp)
}
tp.x = argTranslator.to(tp.argument, 1);
tp.y = valTranslator.to(tp.value, 1);
seriesPoints.push(tp)
});
overloadedSeries[seriesIndex].pointsCount = seriesPoints.length;
overloadedSeries[seriesIndex].total = 0;
overloadedSeries[seriesIndex].continuousSeries = 0;
series.push({
name: s.name,
index: seriesIndex,
points: seriesPoints
})
});
return {
series: series,
overloadedSeries: overloadedSeries
}
}
function applyAutoHidePointMarkers(allSeries, filteredSeries, overloadedSeries, argAxis) {
var argAxisType = argAxis.getOptions().type;
filteredSeries.forEach(s => {
var seriesIndex = allSeries.indexOf(s);
s.autoHidePointMarkers = false;
var tickCount = argAxis.getTicksValues().majorTicksValues.length;
if (s.autoHidePointMarkersEnabled() && (argAxisType === DISCRETE || overloadedSeries[seriesIndex].pointsCount > tickCount)) {
for (var index in overloadedSeries[seriesIndex]) {
var i = parseInt(index);
if (isNaN(i) || overloadedSeries[seriesIndex].total / overloadedSeries[seriesIndex].continuousSeries < 3) {
continue
}
if (i === seriesIndex) {
if (2 * overloadedSeries[i][i] >= overloadedSeries[i].pointsCount) {
s.autoHidePointMarkers = true;
break
}
} else if (overloadedSeries[seriesIndex].total >= overloadedSeries[seriesIndex].pointsCount) {
s.autoHidePointMarkers = true;
break
}
}
}
})
}
function fastHidingPointMarkersByArea(canvas, markersInfo, series) {
var area = canvas.width * canvas.height;
var seriesPoints = markersInfo.series;
var _loop = function(i) {
var currentSeries = series.filter(s => s.name === seriesPoints[i].name)[0];
var points = seriesPoints[i].points;
var pointSize = points.length ? points[0].size : 0;
var pointsArea = pointSize * pointSize * points.length;
if (currentSeries.autoHidePointMarkersEnabled() && pointsArea >= area / seriesPoints.length) {
var index = seriesPoints[i].index;
currentSeries.autoHidePointMarkers = true;
seriesPoints.splice(i, 1);
series.splice(series.indexOf(currentSeries), 1);
delete markersInfo.overloadedSeries[index]
}
};
for (var i = seriesPoints.length - 1; i >= 0; i--) {
_loop(i)
}
}
function updateMarkersInfo(points, overloadedSeries) {
var isContinuousSeries = false;
for (var i = 0; i < points.length - 1; i++) {
var curPoint = points[i];
var size = curPoint.size;
if (_isDefined(curPoint.x) && _isDefined(curPoint.y)) {
for (var j = i + 1; j < points.length; j++) {
var nextPoint = points[j];
var next_x = null === nextPoint || void 0 === nextPoint ? void 0 : nextPoint.x;
var next_y = null === nextPoint || void 0 === nextPoint ? void 0 : nextPoint.y;
if (!_isDefined(next_x) || Math.abs(curPoint.x - next_x) >= size) {
isContinuousSeries &= j !== i + 1;
break
} else {
var distance = _isDefined(next_x) && _isDefined(next_y) && Math.sqrt(Math.pow(curPoint.x - next_x, 2) + Math.pow(curPoint.y - next_y, 2));
if (distance && distance < size) {
overloadedSeries[curPoint.seriesIndex][nextPoint.seriesIndex]++;
overloadedSeries[curPoint.seriesIndex].total++;
if (!isContinuousSeries) {
overloadedSeries[curPoint.seriesIndex].continuousSeries++;
isContinuousSeries = true
}
}
}
}
}
}
}
var dxChart = AdvancedChart.inherit({
_themeSection: "chart",
_fontFields: ["crosshair.label.font"],
_initCore: function() {
this.paneAxis = {};
this.callBase()
},
_init() {
this._containerInitialHeight = hasWindow() ? this._$element.height() : 0;
this.callBase()
},
_correctAxes: function() {
this._correctValueAxes(true)
},
_getExtraOptions: noop,
_createPanes: function() {
var panes = this.option("panes");
var panesNameCounter = 0;
var defaultPane;
if (!panes || _isArray(panes) && !panes.length) {
panes = DEFAULT_PANES
}
this.callBase();
defaultPane = this.option("defaultPane");
panes = _extend(true, [], _isArray(panes) ? panes : [panes]);
_each(panes, (function(_, pane) {
pane.name = !_isDefined(pane.name) ? DEFAULT_PANE_NAME + panesNameCounter++ : pane.name
}));
if (_isDefined(defaultPane)) {
if (!doesPaneExist(panes, defaultPane)) {
this._incidentOccurred("W2101", [defaultPane]);
defaultPane = panes[panes.length - 1].name
}
} else {
defaultPane = panes[panes.length - 1].name
}
this.defaultPane = defaultPane;
panes = this._isRotated() ? panes.reverse() : panes;
return panes
},
_getAxisRenderingOptions: function() {
return {
axisType: "xyAxes",
drawingType: "linear"
}
},
_prepareAxisOptions: function(typeSelector, userOptions, rotated) {
return {
isHorizontal: "argumentAxis" === typeSelector !== rotated,
containerColor: this._themeManager.getOptions("containerBackgroundColor")
}
},
_checkPaneName: function(seriesTheme) {
var paneList = _map(this.panes, (function(pane) {
return pane.name
}));
seriesTheme.pane = seriesTheme.pane || this.defaultPane;
return -1 !== inArray(seriesTheme.pane, paneList)
},
_initCustomPositioningAxes() {
var that = this;
var argumentAxis = that.getArgumentAxis();
var valueAxisName = argumentAxis.getOptions().customPositionAxis;
var valueAxis = that._valueAxes.filter(v => v.pane === argumentAxis.pane && (!valueAxisName || valueAxisName === v.name))[0];
that._valueAxes.forEach(v => {
if (argumentAxis !== v.getOrthogonalAxis()) {
v.getOrthogonalAxis = () => argumentAxis;
v.customPositionIsBoundaryOrthogonalAxis = () => argumentAxis.customPositionIsBoundary()
}
});
if (_isDefined(valueAxis) && valueAxis !== argumentAxis.getOrthogonalAxis()) {
argumentAxis.getOrthogonalAxis = () => valueAxis;
argumentAxis.customPositionIsBoundaryOrthogonalAxis = () => that._valueAxes.some(v => v.customPositionIsBoundary())
} else if (_isDefined(argumentAxis.getOrthogonalAxis()) && !_isDefined(valueAxis)) {
argumentAxis.getOrthogonalAxis = noop
}
},
_getAllAxes() {
return this._argumentAxes.concat(this._valueAxes)
},
_resetAxesAnimation(isFirstDrawing, isHorizontal) {
var axes = _isDefined(isHorizontal) ? isHorizontal ^ this._isRotated() ? this._argumentAxes : this._valueAxes : this._getAllAxes();
axes.forEach(a => {
a.resetApplyingAnimation(isFirstDrawing)
})
},
_axesBoundaryPositioning() {
var allAxes = this._getAllAxes();
var boundaryStateChanged = false;
allAxes.forEach(a => {
if (!a.customPositionIsAvailable()) {
return false
}
var prevBoundaryState = a.customPositionIsBoundary();
a._customBoundaryPosition = a.getCustomBoundaryPosition();
boundaryStateChanged |= prevBoundaryState !== a.customPositionIsBoundary()
});
return boundaryStateChanged
},
_getValueAxis: function(paneName, axisName) {
var valueAxes = this._valueAxes;
var valueAxisOptions = this.option("valueAxis") || {};
var valueAxesOptions = _isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions];
var rotated = this._isRotated();
var crosshairMargins = this._getCrosshairMargins();
var axisOptions;
var axis;
axisName = axisName || getFirstAxisNameForPane(valueAxes, paneName, this.defaultPane);
axis = findAxis(paneName, axisName, valueAxes);
if (!axis) {
axisOptions = findAxisOptions(valueAxes, valueAxesOptions, axisName);
if (!axisOptions) {
this._incidentOccurred("W2102", [axisName]);
axisOptions = {
name: axisName,
priority: valueAxes.length
}
}
axis = this._createAxis(false, this._populateAxesOptions("valueAxis", axisOptions, {
pane: paneName,
name: axisName,
optionPath: _isArray(valueAxisOptions) ? "valueAxis[".concat(axisOptions.priority, "]") : "valueAxis",
crosshairMargin: rotated ? crosshairMargins.y : crosshairMargins.x
}, rotated));
axis.applyVisualRangeSetter(this._getVisualRangeSetter());
valueAxes.push(axis)
}
axis.setPane(paneName);
return axis
},
_correctValueAxes: function(needHideGrids) {
var that = this;
var synchronizeMultiAxes = that._themeManager.getOptions("synchronizeMultiAxes");
var valueAxes = that._valueAxes;
var paneWithAxis = {};
that.series.forEach((function(series) {
var axis = series.getValueAxis();
paneWithAxis[axis.pane] = true
}));
that.panes.forEach((function(pane) {
var paneName = pane.name;
if (!paneWithAxis[paneName]) {
that._getValueAxis(paneName)
}
if (needHideGrids && synchronizeMultiAxes) {
hideGridsOnNonFirstValueAxisForPane(valueAxes.filter((function(axis) {
return axis.pane === paneName
})))
}
}));
that._valueAxes = valueAxes.filter((function(axis) {
if (!axis.pane) {
axis.setPane(that.defaultPane)
}
return doesPaneExist(that.panes, axis.pane)
})).sort(compareAxes);
var defaultAxis = this.getValueAxis();
that._valueAxes.forEach(axis => {
var optionPath = axis.getOptions().optionPath;
if (optionPath) {
var axesWithSamePath = that._valueAxes.filter(a => a.getOptions().optionPath === optionPath);
if (axesWithSamePath.length > 1) {
if (axesWithSamePath.some(a => a === defaultAxis)) {
axesWithSamePath.forEach(a => {
if (a !== defaultAxis) {
a.getOptions().optionPath = null
}
})
} else {
axesWithSamePath.forEach((a, i) => {
if (0 !== i) {
a.getOptions().optionPath = null
}
})
}
}
}
})
},
_getSeriesForPane: function(paneName) {
var paneSeries = [];
_each(this.series, (function(_, oneSeries) {
if (oneSeries.pane === paneName) {
paneSeries.push(oneSeries)
}
}));
return paneSeries
},
_createPanesBorderOptions: function() {
var commonBorderOptions = this._themeManager.getOptions("commonPaneSettings").border;
var panesBorderOptions = {};
this.panes.forEach(pane => panesBorderOptions[pane.name] = _extend(true, {}, commonBorderOptions, pane.border));
return panesBorderOptions
},
_createScrollBar: function() {
var scrollBarOptions = this._themeManager.getOptions("scrollBar") || {};
var scrollBarGroup = this._scrollBarGroup;
if (scrollBarOptions.visible) {
scrollBarOptions.rotated = this._isRotated();
this._scrollBar = (this._scrollBar || new ScrollBar(this._renderer, scrollBarGroup)).update(scrollBarOptions)
} else {
scrollBarGroup.linkRemove();
this._scrollBar && this._scrollBar.dispose();
this._scrollBar = null
}
},
_executeAppendAfterSeries(append) {
append()
},
_prepareToRender(drawOptions) {
var panesBorderOptions = this._createPanesBorderOptions();
this._createPanesBackground();
this._appendAxesGroups();
this._adjustViewport();
return panesBorderOptions
},
_adjustViewport() {
var adjustOnZoom = this._themeManager.getOptions("adjustOnZoom");
if (!adjustOnZoom) {
return
}
this._valueAxes.forEach(axis => axis.adjust())
},
_recreateSizeDependentObjects(isCanvasChanged) {
var that = this;
var series = that._getVisibleSeries();
var useAggregation = series.some(s => s.useAggregation());
var zoomChanged = that._isZooming();
if (!useAggregation) {
return
}
that._argumentAxes.forEach((function(axis) {
axis.updateCanvas(that._canvas, true)
}));
series.forEach((function(series) {
if (series.useAggregation() && (isCanvasChanged || zoomChanged || !series._useAllAggregatedPoints)) {
series.createPoints()
}
}));
that._processSeriesFamilies()
},
_isZooming() {
var argumentAxis = this.getArgumentAxis();
if (!argumentAxis || !argumentAxis.getTranslator()) {
return false
}
var businessRange = argumentAxis.getTranslator().getBusinessRange();
var zoomRange = argumentAxis.getViewport();
var min = zoomRange ? zoomRange.min : 0;
var max = zoomRange ? zoomRange.max : 0;
if ("logarithmic" === businessRange.axisType) {
min = getLog(min, businessRange.base);
max = getLog(max, businessRange.base)
}
var viewportDistance = businessRange.axisType === DISCRETE ? getCategoriesInfo(businessRange.categories, min, max).categories.length : Math.abs(max - min);
var precision = getPrecision(viewportDistance);
precision = precision > 1 ? Math.pow(10, precision - 2) : 1;
var zoomChanged = Math.round((this._zoomLength - viewportDistance) * precision) / precision !== 0;
this._zoomLength = viewportDistance;
return zoomChanged
},
_handleSeriesDataUpdated: function() {
var that = this;
var viewport = new Range;
that.series.forEach((function(s) {
viewport.addRange(s.getArgumentRange())
}));
that._argumentAxes.forEach((function(axis) {
axis.updateCanvas(that._canvas, true);
axis.setBusinessRange(viewport, that._axesReinitialized)
}));
that.callBase()
},
_isLegendInside: function() {
return this._legend && "inside" === this._legend.getPosition()
},
_isRotated: function() {
return this._themeManager.getOptions("rotated")
},
_getLayoutTargets: function() {
return this.panes
},
_applyClipRects: function(panesBorderOptions) {
this._drawPanesBorders(panesBorderOptions);
this._createClipRectsForPanes();
this._applyClipRectsForAxes();
this._fillPanesBackground()
},
_updateLegendPosition: function(drawOptions, legendHasInsidePosition) {
if (drawOptions.drawLegend && this._legend && legendHasInsidePosition) {
var panes = this.panes;
var newCanvas = _extend({}, panes[0].canvas);
var layoutManager = new LayoutManager;
newCanvas.right = panes[panes.length - 1].canvas.right;
newCanvas.bottom = panes[panes.length - 1].canvas.bottom;
layoutManager.layoutInsideLegend(this._legend, newCanvas)
}
},
_allowLegendInsidePosition: () => true,
_applyExtraSettings: function(series) {
var paneIndex = this._getPaneIndex(series.pane);
var panesClipRects = this._panesClipRects;
var wideClipRect = panesClipRects.wide[paneIndex];
series.setClippingParams(panesClipRects.base[paneIndex].id, wideClipRect && wideClipRect.id, this._getPaneBorderVisibility(paneIndex))
},
_updatePanesCanvases: function(drawOptions) {
if (!drawOptions.recreateCanvas) {
return
}
updatePanesCanvases(this.panes, this._canvas, this._isRotated())
},
_normalizePanesHeight: function() {
normalizePanesHeight(this.panes)
},
_renderScaleBreaks: function() {
this._valueAxes.concat(this._argumentAxes).forEach((function(axis) {
axis.drawScaleBreaks()
}))
},
_getArgFilter() {
return rangeDataCalculator.getViewPortFilter(this.getArgumentAxis().visualRange() || {})
},
_applyPointMarkersAutoHiding() {
var that = this;
var allSeries = that.series;
if (!that._themeManager.getOptions("autoHidePointMarkers")) {
allSeries.forEach(s => s.autoHidePointMarkers = false);
return
}
that.panes.forEach(_ref => {
var {
borderCoords: borderCoords,
name: name
} = _ref;
var series = allSeries.filter(s => s.pane === name && s.usePointsToDefineAutoHiding());
var argAxis = that.getArgumentAxis();
var markersInfo = collectMarkersInfoBySeries(allSeries, series, argAxis);
fastHidingPointMarkersByArea(borderCoords, markersInfo, series);
if (markersInfo.series.length) {
var argVisualRange = argAxis.visualRange();
var argAxisIsDiscrete = argAxis.getOptions().type === DISCRETE;
var sortingCallback = argAxisIsDiscrete ? (p1, p2) => argVisualRange.categories.indexOf(p1.argument) - argVisualRange.categories.indexOf(p2.argument) : (p1, p2) => p1.argument - p2.argument;
var points = [];
markersInfo.series.forEach(s => points = points.concat(s.points));
points.sort(sortingCallback);
updateMarkersInfo(points, markersInfo.overloadedSeries);
applyAutoHidePointMarkers(allSeries, series, markersInfo.overloadedSeries, argAxis)
}
})
},
_renderAxes: function(drawOptions, panesBorderOptions) {
function calculateTitlesWidth(axes) {
return axes.map(axis => {
if (!axis.getTitle) {
return 0
}
var title = axis.getTitle();
return title ? title.bBox.width : 0
})
}
var that = this;
var rotated = that._isRotated();
var synchronizeMultiAxes = that._themeManager.getOptions("synchronizeMultiAxes");
var scrollBar = that._scrollBar ? [that._scrollBar] : [];
var extendedArgAxes = that._isArgumentAxisBeforeScrollBar() ? that._argumentAxes.concat(scrollBar) : scrollBar.concat(that._argumentAxes);
var verticalAxes = rotated ? that._argumentAxes : that._valueAxes;
var verticalElements = rotated ? extendedArgAxes : that._valueAxes;
var horizontalAxes = rotated ? that._valueAxes : that._argumentAxes;
var horizontalElements = rotated ? that._valueAxes : extendedArgAxes;
var allAxes = verticalAxes.concat(horizontalAxes);
var allElements = allAxes.concat(scrollBar);
var verticalAxesFirstDrawing = verticalAxes.some(v => v.isFirstDrawing());
that._normalizePanesHeight();
that._updatePanesCanvases(drawOptions);
var panesCanvases = that.panes.reduce((function(canvases, pane) {
canvases[pane.name] = _extend({}, pane.canvas);
return canvases
}), {});
var paneSizes = that.panes.reduce((sizes, pane) => {
sizes[pane.name] = {
height: pane.height,
unit: pane.unit
};
return sizes
}, {});
var cleanPanesCanvases = _extend(true, {}, panesCanvases);
that._initCustomPositioningAxes();
var needCustomAdjustAxes = that._axesBoundaryPositioning();
if (!drawOptions.adjustAxes && !needCustomAdjustAxes) {
drawAxesWithTicks(verticalAxes, !rotated && synchronizeMultiAxes, panesCanvases, panesBorderOptions);
drawAxesWithTicks(horizontalAxes, rotated && synchronizeMultiAxes, panesCanvases, panesBorderOptions);
performActionOnAxes(allAxes, "prepareAnimation");
that._renderScaleBreaks();
horizontalAxes.forEach(a => a.resolveOverlappingForCustomPositioning(verticalAxes));
verticalAxes.forEach(a => a.resolveOverlappingForCustomPositioning(horizontalAxes));
return false
}
if (needCustomAdjustAxes) {
allAxes.forEach(a => a.customPositionIsAvailable() && a.shift({
top: 0,
left: 0,
bottom: 0,
right: 0
}))
}
if (that._scrollBar) {
that._scrollBar.setPane(that.panes)
}
var vAxesMargins = {
panes: {}
};
var hAxesMargins = getHorizontalAxesMargins(horizontalElements, axis => axis.estimateMargins(panesCanvases[axis.pane]));
panesCanvases = shrinkCanvases(rotated, panesCanvases, paneSizes, vAxesMargins, hAxesMargins);
var drawAxesAndSetCanvases = isHorizontal => {
var axes = isHorizontal ? horizontalAxes : verticalAxes;
var condition = (isHorizontal ? rotated : !rotated) && synchronizeMultiAxes;
drawAxesWithTicks(axes, condition, panesCanvases, panesBorderOptions);
if (isHorizontal) {
hAxesMargins = getHorizontalAxesMargins(horizontalElements, getAxisMargins)
} else {
vAxesMargins = getVerticalAxesMargins(verticalElements)
}
panesCanvases = shrinkCanvases(rotated, panesCanvases, paneSizes, vAxesMargins, hAxesMargins)
};
drawAxesAndSetCanvases(false);
drawAxesAndSetCanvases(true);
if (!that._changesApplying && that._estimateTickIntervals(verticalAxes, panesCanvases)) {
drawAxesAndSetCanvases(false)
}
var oldTitlesWidth = calculateTitlesWidth(verticalAxes);
var visibleSeries = that._getVisibleSeries();
var pointsToAnimation = that._getPointsToAnimation(visibleSeries);
var axesIsAnimated = axisAnimationEnabled(drawOptions, pointsToAnimation);
performActionOnAxes(allElements, "updateSize", panesCanvases, axesIsAnimated);
horizontalElements.forEach(shiftAxis("top", "bottom"));
verticalElements.forEach(shiftAxis("left", "right"));
that._renderScaleBreaks();
that.panes.forEach((function(pane) {
_extend(pane.canvas, panesCanvases[pane.name])
}));
that._valueAxes.forEach(axis => {
axis.setInitRange()
});
verticalAxes.forEach((axis, i) => {
var _axis$hasWrap;
if (null !== (_axis$hasWrap = axis.hasWrap) && void 0 !== _axis$hasWrap && _axis$hasWrap.call(axis)) {
var title = axis.getTitle();
var newTitleWidth = title ? title.bBox.width : 0;
var offset = newTitleWidth - oldTitlesWidth[i];
if ("right" === axis.getOptions().position) {
vAxesMargins.right += offset
} else {
vAxesMargins.left += offset;
that.panes.forEach(_ref2 => {
var {
name: name
} = _ref2;
return vAxesMargins.panes[name].left += offset
})
}
panesCanvases = shrinkCanvases(rotated, panesCanvases, paneSizes, vAxesMargins, hAxesMargins);
performActionOnAxes(allElements, "updateSize", panesCanvases, false, false);
oldTitlesWidth = calculateTitlesWidth(verticalAxes)
}
});
if (verticalAxes.some(v => v.customPositionIsAvailable() && v.getCustomPosition() !== v._axisPosition)) {
axesIsAnimated && that._resetAxesAnimation(verticalAxesFirstDrawing, false);
performActionOnAxes(verticalAxes, "updateSize", panesCanvases, axesIsAnimated)
}
horizontalAxes.forEach(a => a.resolveOverlappingForCustomPositioning(verticalAxes));
verticalAxes.forEach(a => a.resolveOverlappingForCustomPositioning(horizontalAxes));
return cleanPanesCanvases
},
_getExtraTemplatesItems() {
var allAxes = (this._argumentAxes || []).concat(this._valueAxes || []);
var elements = this._collectTemplatesFromItems(allAxes);
return {
items: elements.items,
groups: elements.groups,
launchRequest() {
allAxes.forEach((function(a) {
a.setRenderedState(true)
}))
},
doneRequest() {
allAxes.forEach((function(a) {
a.setRenderedState(false)
}))
}
}
},
_estimateTickIntervals: (axes, canvases) => axes.some(axis => axis.estimateTickInterval(canvases[axis.pane])),
checkForMoreSpaceForPanesCanvas() {
var rotated = this._isRotated();
var panesAreCustomSized = this.panes.filter(p => p.unit).length === this.panes.length;
var needSpace = false;
if (panesAreCustomSized) {
var needHorizontalSpace = 0;
var needVerticalSpace = 0;
if (rotated) {
var argAxisRightMargin = this.getArgumentAxis().getMargins().right;
var rightPanesIndent = Math.min.apply(Math, this.panes.map(p => p.canvas.right));
needHorizontalSpace = this._canvas.right + argAxisRightMargin - rightPanesIndent
} else {
var argAxisBottomMargin = this.getArgumentAxis().getMargins().bottom;
var bottomPanesIndent = Math.min.apply(Math, this.panes.map(p => p.canvas.bottom));
needVerticalSpace = this._canvas.bottom + argAxisBottomMargin - bottomPanesIndent
}
needSpace = needHorizontalSpace > 0 || needVerticalSpace > 0 ? {
width: needHorizontalSpace,
height: needVerticalSpace
} : false;
if (0 !== needVerticalSpace) {
var realSize = this.getSize();
var customSize = this.option("size");
var container = this._$element[0];
var containerHasStyledHeight = !!parseInt(container.style.height) || 0 !== this._containerInitialHeight;
if (!rotated && !(customSize && customSize.height) && !containerHasStyledHeight) {
this._forceResize(realSize.width, realSize.height + needVerticalSpace);
needSpace = false
}
}
} else {
needSpace = this.layoutManager.needMoreSpaceForPanesCanvas(this._getLayoutTargets(), rotated, pane => ({
width: rotated && !!pane.unit,
height: !rotated && !!pane.unit
}))
}
return needSpace
},
_forceResize(width, height) {
this._renderer.resize(width, height);
this._updateSize();
this._setContentSize();
this._preserveOriginalCanvas();
this._updateCanvasClipRect(this._canvas)
},
_shrinkAxes(sizeShortage, panesCanvases) {
if (!sizeShortage || !panesCanvases) {
return
}
this._renderer.stopAllAnimations(true);
var rotated = this._isRotated();
var scrollBar = this._scrollBar ? [this._scrollBar] : [];
var extendedArgAxes = this._isArgumentAxisBeforeScrollBar() ? this._argumentAxes.concat(scrollBar) : scrollBar.concat(this._argumentAxes);
var verticalAxes = rotated ? extendedArgAxes : this._valueAxes;
var horizontalAxes = rotated ? this._valueAxes : extendedArgAxes;
var allAxes = verticalAxes.concat(horizontalAxes);
if (sizeShortage.width || sizeShortage.height) {
checkUsedSpace(sizeShortage, "height", horizontalAxes, getHorizontalAxesMargins);
checkUsedSpace(sizeShortage, "width", verticalAxes, getVerticalAxesMargins);
performActionOnAxes(allAxes, "updateSize", panesCanvases);
var paneSizes = this.panes.reduce((sizes, pane) => {
sizes[pane.name] = {
height: pane.height,
unit: pane.unit
};
return sizes
}, {});
panesCanvases = shrinkCanvases(rotated, panesCanvases, paneSizes, getVerticalAxesMargins(verticalAxes), getHorizontalAxesMargins(horizontalAxes, getAxisMargins));
performActionOnAxes(allAxes, "updateSize", panesCanvases);
horizontalAxes.forEach(shiftAxis("top", "bottom"));
verticalAxes.forEach(shiftAxis("left", "right"));
this.panes.forEach(pane => _extend(pane.canvas, panesCanvases[pane.name]))
}
},
_isArgumentAxisBeforeScrollBar() {
var argumentAxis = this.getArgumentAxis();
if (this._scrollBar) {
var _argumentAxis$getOpti;
var argAxisPosition = argumentAxis.getResolvedBoundaryPosition();
var argAxisLabelPosition = null === (_argumentAxis$getOpti = argumentAxis.getOptions().label) || void 0 === _argumentAxis$getOpti ? void 0 : _argumentAxis$getOpti.position;
var scrollBarPosition = this._scrollBar.getOptions().position;
return argumentAxis.hasNonBoundaryPosition() || scrollBarPosition === argAxisPosition && argAxisLabelPosition !== scrollBarPosition
}
return false
},
_getPanesParameters: function() {
var panes = this.panes;
var i;
var params = [];
for (i = 0; i < panes.length; i++) {
if (this._getPaneBorderVisibility(i)) {
params.push({
coords: panes[i].borderCoords,
clipRect: this._panesClipRects.fixed[i]
})
}
}
return params
},
_createCrosshairCursor: function() {
var options = this._themeManager.getOptions("crosshair") || {};
var argumentAxis = this.getArgumentAxis();
var axes = !this._isRotated() ? [
[argumentAxis], this._valueAxes
] : [this._valueAxes, [argumentAxis]];
var parameters = {
canvas: this._getCommonCanvas(),
panes: this._getPanesParameters(),
axes: axes
};
if (!options || !options.enabled) {
return
}
if (!this._crosshair) {
this._crosshair = new Crosshair(this._renderer, options, parameters, this._crosshairCursorGroup)
} else {
this._crosshair.update(options, parameters)
}
this._crosshair.render()
},
_getCommonCanvas: function() {
var i;
var canvas;
var commonCanvas;
var panes = this.panes;
for (i = 0; i < panes.length; i++) {
canvas = panes[i].canvas;
if (!commonCanvas) {
commonCanvas = _extend({}, canvas)
} else {
commonCanvas.right = canvas.right;
commonCanvas.bottom = canvas.bottom
}
}
return commonCanvas
},
_createPanesBackground: function() {
var defaultBackgroundColor = this._themeManager.getOptions("commonPaneSettings").backgroundColor;
var backgroundColor;
var renderer = this._renderer;
var rect;
var i;
var rects = [];
this._panesBackgroundGroup.clear();
for (i = 0; i < this.panes.length; i++) {
backgroundColor = this.panes[i].backgroundColor || defaultBackgroundColor;
if (!backgroundColor || "none" === backgroundColor) {
rects.push(null);
continue
}
rect = renderer.rect(0, 0, 0, 0).attr({
fill: backgroundColor,
"stroke-width": 0
}).append(this._panesBackgroundGroup);
rects.push(rect)
}
this.panesBackground = rects
},
_fillPanesBackground: function() {
var that = this;
var bc;
_each(that.panes, (function(i, pane) {
bc = pane.borderCoords;
if (null !== that.panesBackground[i]) {
that.panesBackground[i].attr({
x: bc.left,
y: bc.top,
width: bc.width,
height: bc.height
})
}
}))
},
_calcPaneBorderCoords: function(pane) {
var canvas = pane.canvas;
var bc = pane.borderCoords = pane.borderCoords || {};
bc.left = canvas.left;
bc.top = canvas.top;
bc.right = canvas.width - canvas.right;
bc.bottom = canvas.height - canvas.bottom;
bc.width = Math.max(bc.right - bc.left, 0);
bc.height = Math.max(bc.bottom - bc.top, 0)
},
_drawPanesBorders: function(panesBorderOptions) {
var that = this;
var rotated = that._isRotated();
that._panesBorderGroup.linkRemove().clear();
_each(that.panes, (function(i, pane) {
var borderOptions = panesBorderOptions[pane.name];
var attr = {
fill: "none",
stroke: borderOptions.color,
"stroke-opacity": borderOptions.opacity,
"stroke-width": borderOptions.width,
dashStyle: borderOptions.dashStyle,
"stroke-linecap": "square"
};
that._calcPaneBorderCoords(pane, rotated);
if (