devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
258 lines (257 loc) • 11.7 kB
JavaScript
/**
* DevExtreme (cjs/viz/series/financial_series.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";
exports.stock = exports.candlestick = void 0;
var _scatter_series = require("./scatter_series");
var _bar_series = require("./bar_series");
var _extend2 = require("../../core/utils/extend");
var _type = require("../../core/utils/type");
var _utils = require("../core/utils");
var _common = require("../../core/utils/common");
const barSeries = _bar_series.chart.bar;
const DEFAULT_FINANCIAL_POINT_SIZE = 10;
const stock = exports.stock = (0, _extend2.extend)({}, _scatter_series.chart, {
_animate: _common.noop,
_applyMarkerClipRect: function(settings) {
settings["clip-path"] = this._forceClipping ? this._paneClipRectID : this._widePaneClipRectID
},
_updatePointsVisibility: barSeries._updatePointsVisibility,
_getOptionsForPoint: barSeries._getOptionsForPoint,
_createErrorBarGroup: _common.noop,
areErrorBarsVisible: _common.noop,
_createGroups: _scatter_series.chart._createGroups,
_setMarkerGroupSettings: function() {
const markersGroup = this._markersGroup;
const styles = this._createPointStyles(this._getMarkerGroupOptions());
const defaultStyle = (0, _extend2.extend)(styles.normal, {
class: "default-markers"
});
const defaultPositiveStyle = (0, _extend2.extend)(styles.positive.normal, {
class: "default-positive-markers"
});
const reductionStyle = (0, _extend2.extend)(styles.reduction.normal, {
class: "reduction-markers"
});
const reductionPositiveStyle = (0, _extend2.extend)(styles.reductionPositive.normal, {
class: "reduction-positive-markers"
});
const markerSettings = {
class: "dxc-markers"
};
this._applyMarkerClipRect(markerSettings);
markersGroup.attr(markerSettings);
this._createGroup("defaultMarkersGroup", markersGroup, markersGroup, defaultStyle);
this._createGroup("reductionMarkersGroup", markersGroup, markersGroup, reductionStyle);
this._createGroup("defaultPositiveMarkersGroup", markersGroup, markersGroup, defaultPositiveStyle);
this._createGroup("reductionPositiveMarkersGroup", markersGroup, markersGroup, reductionPositiveStyle)
},
_setGroupsSettings: function() {
_scatter_series.chart._setGroupsSettings.call(this, false)
},
_getCreatingPointOptions: function() {
const that = this;
let defaultPointOptions;
let creatingPointOptions = that._predefinedPointOptions;
if (!creatingPointOptions) {
defaultPointOptions = this._getPointOptions();
that._predefinedPointOptions = creatingPointOptions = (0, _extend2.extend)(true, {
styles: {}
}, defaultPointOptions);
creatingPointOptions.styles.normal = creatingPointOptions.styles.positive.normal = creatingPointOptions.styles.reduction.normal = creatingPointOptions.styles.reductionPositive.normal = {
"stroke-width": defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal["stroke-width"]
}
}
return creatingPointOptions
},
_checkData: function(data, skippedFields) {
const valueFields = this.getValueFields();
return _scatter_series.chart._checkData.call(this, data, skippedFields, {
openValue: valueFields[0],
highValue: valueFields[1],
lowValue: valueFields[2],
closeValue: valueFields[3]
}) && data.highValue === data.highValue && data.lowValue === data.lowValue
},
_getPointDataSelector: function(data, options) {
const that = this;
let level;
const valueFields = that.getValueFields();
const argumentField = that.getArgumentField();
const openValueField = valueFields[0];
const highValueField = valueFields[1];
const lowValueField = valueFields[2];
const closeValueField = valueFields[3];
that.level = that._options.reduction.level;
switch ((0, _utils.normalizeEnum)(that.level)) {
case "open":
level = openValueField;
break;
case "high":
level = highValueField;
break;
case "low":
level = lowValueField;
break;
default:
level = closeValueField;
that.level = "close"
}
let prevLevelValue;
return data => {
const reductionValue = data[level];
let isReduction = false;
if ((0, _type.isDefined)(reductionValue)) {
if ((0, _type.isDefined)(prevLevelValue)) {
isReduction = reductionValue < prevLevelValue
}
prevLevelValue = reductionValue
}
return {
argument: data[argumentField],
highValue: this._processEmptyValue(data[highValueField]),
lowValue: this._processEmptyValue(data[lowValueField]),
closeValue: this._processEmptyValue(data[closeValueField]),
openValue: this._processEmptyValue(data[openValueField]),
reductionValue: reductionValue,
tag: data[that.getTagField()],
isReduction: isReduction,
data: data
}
}
},
_parsePointStyle: function(style, defaultColor, innerColor) {
const color = (0, _utils.extractColor)(style.color, true);
return {
stroke: color || defaultColor,
"stroke-width": style.width,
fill: color || innerColor
}
},
_getDefaultStyle: function(options) {
const mainPointColor = (0, _utils.extractColor)(options.color, true) || this._options.mainSeriesColor;
return {
normal: this._parsePointStyle(options, mainPointColor, mainPointColor),
hover: this._parsePointStyle(options.hoverStyle, mainPointColor, mainPointColor),
selection: this._parsePointStyle(options.selectionStyle, mainPointColor, mainPointColor)
}
},
_getReductionStyle: function(options) {
const reductionColor = options.reduction.color;
return {
normal: this._parsePointStyle({
color: reductionColor,
width: options.width,
hatching: options.hatching
}, reductionColor, reductionColor),
hover: this._parsePointStyle(options.hoverStyle, reductionColor, reductionColor),
selection: this._parsePointStyle(options.selectionStyle, reductionColor, reductionColor)
}
},
_createPointStyles: function(pointOptions) {
const innerColor = this._options.innerColor;
const styles = this._getDefaultStyle(pointOptions);
const positiveStyle = (0, _extend2.extend)(true, {}, styles);
const reductionStyle = this._getReductionStyle(pointOptions);
const reductionPositiveStyle = (0, _extend2.extend)(true, {}, reductionStyle);
positiveStyle.normal.fill = positiveStyle.hover.fill = positiveStyle.selection.fill = innerColor;
reductionPositiveStyle.normal.fill = reductionPositiveStyle.hover.fill = reductionPositiveStyle.selection.fill = innerColor;
styles.positive = positiveStyle;
styles.reduction = reductionStyle;
styles.reductionPositive = reductionPositiveStyle;
styles.labelColor = this._options.mainSeriesColor;
return styles
},
_endUpdateData: function() {
delete this._predefinedPointOptions
},
_defaultAggregator: "ohlc",
_aggregators: {
ohlc: (_ref, series) => {
let {
intervalStart: intervalStart,
intervalEnd: intervalEnd,
data: data
} = _ref;
if (!data.length) {
return
}
let result = {};
const valueFields = series.getValueFields();
const highValueField = valueFields[1];
const lowValueField = valueFields[2];
result[highValueField] = -1 / 0;
result[lowValueField] = 1 / 0;
result = data.reduce((function(result, item) {
if (null !== item[highValueField]) {
result[highValueField] = Math.max(result[highValueField], item[highValueField])
}
if (null !== item[lowValueField]) {
result[lowValueField] = Math.min(result[lowValueField], item[lowValueField])
}
return result
}), result);
result[valueFields[0]] = data[0][valueFields[0]];
result[valueFields[3]] = data[data.length - 1][valueFields[3]];
if (!isFinite(result[highValueField])) {
result[highValueField] = null
}
if (!isFinite(result[lowValueField])) {
result[lowValueField] = null
}
result[series.getArgumentField()] = series._getIntervalCenter(intervalStart, intervalEnd);
return result
}
},
getValueFields: function() {
const options = this._options;
return [options.openValueField || "open", options.highValueField || "high", options.lowValueField || "low", options.closeValueField || "close"]
},
getArgumentField: function() {
return this._options.argumentField || "date"
},
_patchMarginOptions: function(options) {
const pointOptions = this._getCreatingPointOptions();
const styles = pointOptions.styles;
const border = [styles.normal, styles.hover, styles.selection].reduce((function(max, style) {
return Math.max(max, style["stroke-width"])
}), 0);
options.size = 10 + border;
options.sizePointNormalState = 10;
return options
},
getSeriesPairCoord(coord, isArgument) {
let oppositeCoord = null;
const points = this.getVisiblePoints();
for (let i = 0; i < points.length; i++) {
const p = points[i];
let tmpCoord;
if (isArgument) {
tmpCoord = p.vx === coord ? (p.openY + p.closeY) / 2 : void 0
} else {
const coords = [Math.min(p.lowY, p.highY), Math.max(p.lowY, p.highY)];
tmpCoord = coord >= coords[0] && coord <= coords[1] ? p.vx : void 0
}
if (this._checkAxisVisibleAreaCoord(!isArgument, tmpCoord)) {
oppositeCoord = tmpCoord;
break
}
}
return oppositeCoord
},
usePointsToDefineAutoHiding: () => false
});
const candlestick = exports.candlestick = (0, _extend2.extend)({}, stock, {
_parsePointStyle: function(style, defaultColor, innerColor) {
const color = (0, _utils.extractColor)(style.color, true) || innerColor;
const base = stock._parsePointStyle.call(this, style, defaultColor, color);
base.fill = color;
base.hatching = style.hatching;
return base
}
});