initial commit
This commit is contained in:
@@ -0,0 +1,778 @@
|
||||
/**
|
||||
* @license Highcharts JS v7.0.3 (2019-02-06)
|
||||
* Timeline series
|
||||
*
|
||||
* (c) 2010-2019 Highsoft AS
|
||||
* Author: Daniel Studencki
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
'use strict';
|
||||
(function (factory) {
|
||||
if (typeof module === 'object' && module.exports) {
|
||||
factory['default'] = factory;
|
||||
module.exports = factory;
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define(function () {
|
||||
return factory;
|
||||
});
|
||||
} else {
|
||||
factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
|
||||
}
|
||||
}(function (Highcharts) {
|
||||
(function (H) {
|
||||
/* *
|
||||
*
|
||||
* Experimental Timeline Series.
|
||||
* Note: This API is in alpha stage and will be changed before final release.
|
||||
*
|
||||
* (c) 2010-2019 Highsoft AS
|
||||
*
|
||||
* Author: Daniel Studencki
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
|
||||
var addEvent = H.addEvent,
|
||||
extend = H.extend,
|
||||
defined = H.defined,
|
||||
LegendSymbolMixin = H.LegendSymbolMixin,
|
||||
TrackerMixin = H.TrackerMixin,
|
||||
merge = H.merge,
|
||||
pick = H.pick,
|
||||
Point = H.Point,
|
||||
Series = H.Series,
|
||||
undocumentedSeriesType = H.seriesType;
|
||||
|
||||
/* *
|
||||
* The timeline series type.
|
||||
*
|
||||
* @private
|
||||
* @class
|
||||
* @name Highcharts.seriesTypes.timeline
|
||||
*
|
||||
* @augments Highcharts.Series
|
||||
*/
|
||||
undocumentedSeriesType('timeline', 'line',
|
||||
|
||||
/* *
|
||||
* The timeline series presents given events along a drawn line.
|
||||
*
|
||||
* @sample highcharts/series-timeline/alternate-labels Timeline series
|
||||
*
|
||||
* @extends plotOptions.line
|
||||
* @since 7.0.0
|
||||
* @product highcharts
|
||||
* @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
|
||||
* cropThreshold, dashStyle, findNearestPointBy,
|
||||
* getExtremesFromAll, lineWidth, negativeColor,
|
||||
* pointInterval, pointIntervalUnit, pointPlacement,
|
||||
* pointStart, softThreshold, stacking, step, threshold,
|
||||
* turboThreshold, zoneAxis, zones
|
||||
* @optionparent plotOptions.timeline
|
||||
*/
|
||||
{
|
||||
colorByPoint: true,
|
||||
stickyTracking: false,
|
||||
ignoreHiddenPoint: true,
|
||||
legendType: 'point',
|
||||
lineWidth: 0,
|
||||
tooltip: {
|
||||
headerFormat: '<span style="color:{point.color}">● </span>' +
|
||||
'<span style="font-weight: bold;">{point.point.date}</span><br/>',
|
||||
pointFormat: '{point.description}'
|
||||
},
|
||||
states: {
|
||||
hover: {
|
||||
lineWidthPlus: 5,
|
||||
halo: {
|
||||
size: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
allowOverlap: true,
|
||||
/* *
|
||||
* The width of the line connecting the data label to the point.
|
||||
*
|
||||
*
|
||||
* In styled mode, the connector stroke width is given in the
|
||||
* `.highcharts-data-label-connector` class.
|
||||
*
|
||||
* @type {Number}
|
||||
* @default 1
|
||||
* @sample {highcharts} highcharts/series-timeline/connector-styles
|
||||
* Custom connector width and color
|
||||
*/
|
||||
connectorWidth: 1,
|
||||
/* *
|
||||
* The color of the line connecting the data label to the point.
|
||||
*
|
||||
* In styled mode, the connector stroke is given in the
|
||||
* `.highcharts-data-label-connector` class.
|
||||
*
|
||||
* @type {String}
|
||||
* @sample {highcharts} highcharts/series-timeline/connector-styles
|
||||
* Custom connector width and color
|
||||
*/
|
||||
connectorColor: '#000000',
|
||||
backgroundColor: '#ffffff',
|
||||
/* *
|
||||
* @type {Highcharts.FormatterCallbackFunction<object>}
|
||||
* @default function () {
|
||||
* var format;
|
||||
*
|
||||
* if (!this.series.chart.styledMode) {
|
||||
* format = '<span style="color:' + this.point.color +
|
||||
* '">● </span><span style="font-weight: bold;" > ' +
|
||||
* (this.point.date || '') + '</span><br/>' +
|
||||
* (this.point.label || '');
|
||||
* } else {
|
||||
* format = '<span>● </span>' +
|
||||
* '<span>' + (this.point.date || '') +
|
||||
* '</span><br/>' + (this.point.label || '');
|
||||
* }
|
||||
* return format;
|
||||
* }
|
||||
* @apioption plotOptions.timeline.dataLabels.formatter
|
||||
*/
|
||||
formatter: function () {
|
||||
var format;
|
||||
|
||||
if (!this.series.chart.styledMode) {
|
||||
format = '<span style="color:' + this.point.color +
|
||||
'">● </span><span style="font-weight: bold;" > ' +
|
||||
(this.point.date || '') + '</span><br/>' +
|
||||
(this.point.label || '');
|
||||
} else {
|
||||
format = '<span>● </span>' +
|
||||
'<span>' + (this.point.date || '') +
|
||||
'</span><br/>' + (this.point.label || '');
|
||||
}
|
||||
return format;
|
||||
},
|
||||
borderWidth: 1,
|
||||
borderColor: '#666666',
|
||||
/* *
|
||||
* A pixel value defining the distance between the data label
|
||||
* and the point. Negative numbers puts the label on top
|
||||
* of the point.
|
||||
*
|
||||
* @type {Number}
|
||||
* @default 100
|
||||
*/
|
||||
distance: 100,
|
||||
/* *
|
||||
* Whether to position data labels alternately. For example, if
|
||||
* [distance](#plotOptions.timeline.dataLabels.distance) is set
|
||||
* equal to `100`, then the first data label 's distance will be
|
||||
* set equal to `100`, the second one equal to `-100`, and so on.
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
* @sample {highcharts} highcharts/series-timeline/alternate-disabled
|
||||
* Alternate disabled
|
||||
*/
|
||||
alternate: true,
|
||||
verticalAlign: 'middle',
|
||||
color: '#333333'
|
||||
},
|
||||
marker: {
|
||||
enabledThreshold: 0,
|
||||
symbol: 'square',
|
||||
height: 15
|
||||
}
|
||||
},
|
||||
/* *
|
||||
* @lends Highcharts.Series#
|
||||
*/
|
||||
{
|
||||
requireSorting: false,
|
||||
trackerGroups: ['markerGroup', 'dataLabelsGroup'],
|
||||
// Use a simple symbol from LegendSymbolMixin
|
||||
drawLegendSymbol: LegendSymbolMixin.drawRectangle,
|
||||
// Use a group of trackers from TrackerMixin
|
||||
drawTracker: TrackerMixin.drawTrackerPoint,
|
||||
init: function () {
|
||||
var series = this;
|
||||
|
||||
Series.prototype.init.apply(series, arguments);
|
||||
|
||||
// Distribute data labels before rendering them. Distribution is
|
||||
// based on the 'dataLabels.distance' and 'dataLabels.alternate'
|
||||
// property.
|
||||
addEvent(series, 'drawDataLabels', function () {
|
||||
|
||||
// Delete the oldTextWidth parameter, in order to force
|
||||
// adjusting data label wrapper box width. It's needed only when
|
||||
// useHTML is enabled. This prevents the data label text getting
|
||||
// out of the box range.
|
||||
if (series.options.dataLabels.useHTML) {
|
||||
series.points.forEach(function (p) {
|
||||
if (p.visible && p.dataLabel) {
|
||||
delete p.dataLabel.text.oldTextWidth;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Distribute data labels basing on defined algorithm.
|
||||
series.distributeDL();
|
||||
});
|
||||
|
||||
addEvent(series, 'afterDrawDataLabels', function () {
|
||||
var seriesOptions = series.options,
|
||||
options = seriesOptions.dataLabels,
|
||||
hasRendered = series.hasRendered || 0,
|
||||
defer = pick(options.defer, !!seriesOptions.animation),
|
||||
connectorsGroup = series.connectorsGroup,
|
||||
dataLabel;
|
||||
|
||||
// Create (or redraw) the group for all connectors.
|
||||
connectorsGroup = series.plotGroup(
|
||||
'connectorsGroup',
|
||||
'data-labels-connectors',
|
||||
defer && !hasRendered ? 'hidden' : 'visible',
|
||||
options.zIndex || 5
|
||||
);
|
||||
|
||||
// Draw or align connector for each point.
|
||||
series.points.forEach(function (point) {
|
||||
dataLabel = point.dataLabel;
|
||||
|
||||
if (dataLabel) {
|
||||
// Within this wrap method is necessary to save the
|
||||
// current animation params, because the data label
|
||||
// target position (after animation) is needed to align
|
||||
// connectors.
|
||||
dataLabel.animate = function (params) {
|
||||
if (this.targetPosition) {
|
||||
this.targetPosition = params;
|
||||
}
|
||||
return H.SVGElement.prototype.animate.apply(
|
||||
this,
|
||||
arguments
|
||||
);
|
||||
};
|
||||
|
||||
// Initialize the targetPosition field within data label
|
||||
// object. It's necessary because there is need to know
|
||||
// expected position of specific data label, when
|
||||
// aligning connectors. This field is overrided inside
|
||||
// of SVGElement.animate() wrapped method.
|
||||
if (!dataLabel.targetPosition) {
|
||||
dataLabel.targetPosition = {};
|
||||
}
|
||||
|
||||
return !point.connector ?
|
||||
point.drawConnector() :
|
||||
point.alignConnector();
|
||||
}
|
||||
});
|
||||
// Animate connectors group. It's animated in the same way like
|
||||
// dataLabels, and also depends on dataLabels.defer parameter.
|
||||
if (defer) {
|
||||
connectorsGroup.attr({
|
||||
opacity: +hasRendered
|
||||
});
|
||||
if (!hasRendered) {
|
||||
addEvent(series, 'afterAnimate', function () {
|
||||
if (series.visible) {
|
||||
connectorsGroup.show(true);
|
||||
}
|
||||
connectorsGroup[
|
||||
seriesOptions.animation ? 'animate' : 'attr'
|
||||
]({
|
||||
opacity: 1
|
||||
}, {
|
||||
duration: 200
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
alignDataLabel: function (point, dataLabel) {
|
||||
var series = this,
|
||||
isInverted = series.chart.inverted,
|
||||
visiblePoints = series.visibilityMap.filter(function (point) {
|
||||
return point;
|
||||
}),
|
||||
visiblePointsCount = series.visiblePointsCount,
|
||||
pointIndex = visiblePoints.indexOf(point),
|
||||
isFirstOrLast = !pointIndex ||
|
||||
pointIndex === visiblePointsCount - 1,
|
||||
dataLabelsOptions = series.options.dataLabels,
|
||||
userDLOptions = point.userDLOptions || {},
|
||||
// Define multiplier which is used to calculate data label
|
||||
// width. If data labels are alternate, they have two times more
|
||||
// space to adapt (excepting first and last ones, which has only
|
||||
// one and half), than in case of placing all data labels side
|
||||
// by side.
|
||||
multiplier = dataLabelsOptions.alternate ?
|
||||
(isFirstOrLast ? 1.5 : 2) :
|
||||
1,
|
||||
distance,
|
||||
availableSpace = Math.floor(
|
||||
series.xAxis.len / visiblePointsCount
|
||||
),
|
||||
pad = dataLabel.padding,
|
||||
targetDLWidth,
|
||||
styles;
|
||||
|
||||
// Adjust data label width to the currently available space.
|
||||
if (point.visible) {
|
||||
distance = Math.abs(
|
||||
userDLOptions.x || point.options.dataLabels.x
|
||||
);
|
||||
if (isInverted) {
|
||||
targetDLWidth = (
|
||||
(distance - pad) * 2 - (point.itemHeight / 2)
|
||||
);
|
||||
styles = {
|
||||
width: targetDLWidth,
|
||||
// Apply ellipsis when data label height is exceeded.
|
||||
textOverflow: dataLabel.width / targetDLWidth *
|
||||
dataLabel.height / 2 > availableSpace * multiplier ?
|
||||
'ellipsis' : 'none'
|
||||
};
|
||||
} else {
|
||||
styles = {
|
||||
width: userDLOptions.width ||
|
||||
dataLabelsOptions.width ||
|
||||
availableSpace * multiplier - (pad * 2)
|
||||
};
|
||||
}
|
||||
dataLabel.css(styles);
|
||||
|
||||
if (!series.chart.styledMode) {
|
||||
dataLabel.shadow({});
|
||||
}
|
||||
}
|
||||
Series.prototype.alignDataLabel.apply(series, arguments);
|
||||
},
|
||||
processData: function () {
|
||||
var series = this,
|
||||
xMap = [],
|
||||
base,
|
||||
visiblePoints = 0,
|
||||
i;
|
||||
|
||||
series.visibilityMap = series.getVisibilityMap();
|
||||
|
||||
// Calculate currently visible points.
|
||||
series.visibilityMap.forEach(function (point) {
|
||||
if (point) {
|
||||
visiblePoints++;
|
||||
}
|
||||
});
|
||||
|
||||
series.visiblePointsCount = visiblePoints;
|
||||
base = series.xAxis.options.max / visiblePoints;
|
||||
|
||||
// Generate xData map.
|
||||
for (i = 1; i <= visiblePoints; i++) {
|
||||
xMap.push(
|
||||
(base * i) - (base / 2)
|
||||
);
|
||||
}
|
||||
|
||||
// Set all hidden points y values as negatives, in order to move
|
||||
// them away from plot area. It is necessary to avoid hiding data
|
||||
// labels, when dataLabels.allowOverlap is set to false.
|
||||
series.visibilityMap.forEach(function (vis, i) {
|
||||
if (!vis) {
|
||||
xMap.splice(i, 0, series.yData[i] === null ? null : -99);
|
||||
}
|
||||
});
|
||||
|
||||
series.xData = xMap;
|
||||
series.yData = xMap.map(function (data) {
|
||||
return defined(data) ? 1 : null;
|
||||
});
|
||||
|
||||
Series.prototype.processData.call(this, arguments);
|
||||
},
|
||||
generatePoints: function () {
|
||||
var series = this;
|
||||
|
||||
Series.prototype.generatePoints.apply(series);
|
||||
series.points.forEach(function (point, i) {
|
||||
point.applyOptions({
|
||||
x: series.xData[i]
|
||||
});
|
||||
});
|
||||
},
|
||||
getVisibilityMap: function () {
|
||||
var series = this,
|
||||
map = (series.data.length ?
|
||||
series.data : series.userOptions.data
|
||||
).map(function (point) {
|
||||
return (
|
||||
point &&
|
||||
point.visible !== false &&
|
||||
!point.isNull
|
||||
) ? point : false;
|
||||
});
|
||||
|
||||
return map;
|
||||
},
|
||||
distributeDL: function () {
|
||||
var series = this,
|
||||
dataLabelsOptions = series.options.dataLabels,
|
||||
options,
|
||||
pointDLOptions,
|
||||
newOptions = {},
|
||||
visibilityIndex = 1,
|
||||
distance = dataLabelsOptions.distance;
|
||||
|
||||
series.points.forEach(function (point) {
|
||||
if (point.visible && !point.isNull) {
|
||||
options = point.options;
|
||||
pointDLOptions = point.options.dataLabels;
|
||||
|
||||
if (!series.hasRendered) {
|
||||
point.userDLOptions = merge({}, pointDLOptions);
|
||||
}
|
||||
|
||||
newOptions[series.chart.inverted ? 'x' : 'y'] =
|
||||
dataLabelsOptions.alternate && visibilityIndex % 2 ?
|
||||
-distance : distance;
|
||||
|
||||
options.dataLabels = merge(newOptions, point.userDLOptions);
|
||||
visibilityIndex++;
|
||||
}
|
||||
});
|
||||
},
|
||||
markerAttribs: function (point, state) {
|
||||
var series = this,
|
||||
seriesMarkerOptions = series.options.marker,
|
||||
seriesStateOptions,
|
||||
pointMarkerOptions = point.marker || {},
|
||||
symbol = (
|
||||
pointMarkerOptions.symbol || seriesMarkerOptions.symbol
|
||||
),
|
||||
pointStateOptions,
|
||||
width = pick(
|
||||
pointMarkerOptions.width,
|
||||
seriesMarkerOptions.width,
|
||||
series.xAxis.len / series.visiblePointsCount
|
||||
),
|
||||
height = pick(
|
||||
pointMarkerOptions.height,
|
||||
seriesMarkerOptions.height
|
||||
),
|
||||
radius = 0,
|
||||
attribs;
|
||||
|
||||
// Handle hover and select states
|
||||
if (state) {
|
||||
seriesStateOptions = seriesMarkerOptions.states[state] || {};
|
||||
pointStateOptions = pointMarkerOptions.states &&
|
||||
pointMarkerOptions.states[state] || {};
|
||||
|
||||
radius = pick(
|
||||
pointStateOptions.radius,
|
||||
seriesStateOptions.radius,
|
||||
radius + (
|
||||
seriesStateOptions.radiusPlus ||
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
point.hasImage = symbol && symbol.indexOf('url') === 0;
|
||||
|
||||
attribs = {
|
||||
x: Math.floor(point.plotX) - (width / 2) - (radius / 2),
|
||||
y: point.plotY - (height / 2) - (radius / 2),
|
||||
width: width + radius,
|
||||
height: height + radius
|
||||
};
|
||||
|
||||
return attribs;
|
||||
|
||||
},
|
||||
bindAxes: function () {
|
||||
var series = this,
|
||||
timelineXAxis = {
|
||||
gridLineWidth: 0,
|
||||
lineWidth: 0,
|
||||
min: 0,
|
||||
dataMin: 0,
|
||||
minPadding: 0,
|
||||
max: 100,
|
||||
dataMax: 100,
|
||||
maxPadding: 0,
|
||||
title: null,
|
||||
tickPositions: []
|
||||
},
|
||||
timelineYAxis = {
|
||||
gridLineWidth: 0,
|
||||
min: 0.5,
|
||||
dataMin: 0.5,
|
||||
minPadding: 0,
|
||||
max: 1.5,
|
||||
dataMax: 1.5,
|
||||
maxPadding: 0,
|
||||
title: null,
|
||||
labels: {
|
||||
enabled: false
|
||||
}
|
||||
};
|
||||
|
||||
Series.prototype.bindAxes.call(series);
|
||||
extend(series.xAxis.options, timelineXAxis);
|
||||
extend(series.yAxis.options, timelineYAxis);
|
||||
}
|
||||
},
|
||||
/* *
|
||||
* @lends Highcharts.Point#
|
||||
*/
|
||||
{
|
||||
init: function () {
|
||||
var point = Point.prototype.init.apply(this, arguments);
|
||||
|
||||
point.name = pick(point.name, point.date, 'Event');
|
||||
point.y = 1;
|
||||
|
||||
return point;
|
||||
},
|
||||
// The setVisible method is taken from Pie series prototype, in order to
|
||||
// prevent importing whole Pie series.
|
||||
setVisible: function (vis, redraw) {
|
||||
var point = this,
|
||||
series = point.series,
|
||||
chart = series.chart,
|
||||
ignoreHiddenPoint = series.options.ignoreHiddenPoint;
|
||||
|
||||
redraw = pick(redraw, ignoreHiddenPoint);
|
||||
|
||||
if (vis !== point.visible) {
|
||||
|
||||
// If called without an argument, toggle visibility
|
||||
point.visible = point.options.visible = vis =
|
||||
vis === undefined ? !point.visible : vis;
|
||||
// update userOptions.data
|
||||
series.options.data[series.data.indexOf(point)] = point.options;
|
||||
|
||||
// Show and hide associated elements. This is performed
|
||||
// regardless of redraw or not, because chart.redraw only
|
||||
// handles full series.
|
||||
['graphic', 'dataLabel', 'connector'].forEach(
|
||||
function (key) {
|
||||
if (point[key]) {
|
||||
point[key][vis ? 'show' : 'hide'](true);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (point.legendItem) {
|
||||
chart.legend.colorizeItem(point, vis);
|
||||
}
|
||||
|
||||
// #4170, hide halo after hiding point
|
||||
if (!vis && point.state === 'hover') {
|
||||
point.setState('');
|
||||
}
|
||||
|
||||
// Handle ignore hidden slices
|
||||
if (ignoreHiddenPoint) {
|
||||
series.isDirty = true;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
chart.redraw();
|
||||
}
|
||||
}
|
||||
},
|
||||
setState: function () {
|
||||
var proceed = Series.prototype.pointClass.prototype.setState;
|
||||
|
||||
// Prevent triggering the setState method on null points.
|
||||
if (!this.isNull) {
|
||||
proceed.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
getConnectorPath: function () {
|
||||
var point = this,
|
||||
chart = point.series.chart,
|
||||
xAxisLen = point.series.xAxis.len,
|
||||
inverted = chart.inverted,
|
||||
direction = inverted ? 'x2' : 'y2',
|
||||
dl = point.dataLabel,
|
||||
targetDLPos = dl.targetPosition,
|
||||
coords = {
|
||||
x1: point.plotX,
|
||||
y1: point.plotY,
|
||||
x2: point.plotX,
|
||||
y2: targetDLPos.y || dl.y
|
||||
},
|
||||
negativeDistance = (
|
||||
coords[direction] < point.series.yAxis.len / 2
|
||||
),
|
||||
path;
|
||||
|
||||
// Recalculate coords when the chart is inverted.
|
||||
if (inverted) {
|
||||
coords = {
|
||||
x1: point.plotY,
|
||||
y1: xAxisLen - point.plotX,
|
||||
x2: targetDLPos.x || dl.x,
|
||||
y2: xAxisLen - point.plotX
|
||||
};
|
||||
}
|
||||
|
||||
// Subtract data label width or height from expected coordinate so
|
||||
// that the connector would start from the appropriate edge.
|
||||
if (negativeDistance) {
|
||||
coords[direction] += dl[inverted ? 'width' : 'height'];
|
||||
}
|
||||
|
||||
path = chart.renderer.crispLine([
|
||||
'M',
|
||||
coords.x1,
|
||||
coords.y1,
|
||||
'L',
|
||||
coords.x2,
|
||||
coords.y2
|
||||
], dl.options.connectorWidth || 1);
|
||||
|
||||
return path;
|
||||
},
|
||||
drawConnector: function () {
|
||||
var point = this,
|
||||
series = point.series,
|
||||
dlOptions = point.dataLabel.options = merge(
|
||||
{}, series.options.dataLabels,
|
||||
point.options.dataLabels
|
||||
);
|
||||
|
||||
point.connector = series.chart.renderer
|
||||
.path(point.getConnectorPath())
|
||||
.add(series.connectorsGroup);
|
||||
|
||||
if (!series.chart.styledMode) {
|
||||
point.connector.attr({
|
||||
stroke: dlOptions.connectorColor,
|
||||
'stroke-width': dlOptions.connectorWidth,
|
||||
opacity: point.dataLabel.opacity
|
||||
});
|
||||
}
|
||||
},
|
||||
alignConnector: function () {
|
||||
var point = this,
|
||||
connector = point.connector,
|
||||
bBox = connector.getBBox(),
|
||||
isVisible = bBox.y > 0;
|
||||
|
||||
connector[isVisible ? 'animate' : 'attr']({
|
||||
d: point.getConnectorPath()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Hide/show connector related with a specific data label, after overlapping
|
||||
// detected.
|
||||
addEvent(H.Chart, 'afterHideOverlappingLabels', function () {
|
||||
var series = this.series,
|
||||
dataLabel,
|
||||
connector;
|
||||
|
||||
series.forEach(function (series) {
|
||||
if (series.points) {
|
||||
series.points.forEach(function (point) {
|
||||
dataLabel = point.dataLabel;
|
||||
connector = point.connector;
|
||||
|
||||
if (
|
||||
dataLabel &&
|
||||
dataLabel.targetPosition &&
|
||||
connector
|
||||
) {
|
||||
connector.attr({
|
||||
opacity: dataLabel.targetPosition.opacity ||
|
||||
dataLabel.newOpacity
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* *
|
||||
* The `timeline` series. If the [type](#series.timeline.type) option is
|
||||
* not specified, it is inherited from [chart.type](#chart.type).
|
||||
*
|
||||
* @extends series,plotOptions.timeline
|
||||
* @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
|
||||
* cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy,
|
||||
* getExtremesFromAll, lineWidth, negativeColor,
|
||||
* pointInterval, pointIntervalUnit, pointPlacement, pointStart,
|
||||
* softThreshold, stacking, stack, step, threshold, turboThreshold,
|
||||
* zoneAxis, zones
|
||||
* @product highcharts
|
||||
* @apioption series.timeline
|
||||
*/
|
||||
|
||||
/* *
|
||||
* An array of data points for the series. For the `timeline` series type,
|
||||
* points can be given with three general parameters, `date`, `label`,
|
||||
* and `description`:
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```js
|
||||
* series: [{
|
||||
* type: 'timeline',
|
||||
* data: [{
|
||||
* date: 'Jan 2018',
|
||||
* label: 'Some event label',
|
||||
* description: 'Description to show in tooltip'
|
||||
* }]
|
||||
* }]
|
||||
* ```
|
||||
*
|
||||
* @sample {highcharts} highcharts/series-timeline/alternate-labels
|
||||
* Alternate labels
|
||||
*
|
||||
* @type {Array<number|*>}
|
||||
* @extends series.line.data
|
||||
* @excluding marker, x, y
|
||||
* @product highcharts
|
||||
* @apioption series.timeline.data
|
||||
*/
|
||||
|
||||
/* *
|
||||
* The date of event.
|
||||
*
|
||||
* @type {string}
|
||||
* @product highcharts
|
||||
* @apioption series.timeline.data.date
|
||||
*/
|
||||
|
||||
/* *
|
||||
* The label of event.
|
||||
*
|
||||
* @type {string}
|
||||
* @product highcharts
|
||||
* @apioption series.timeline.data.label
|
||||
*/
|
||||
|
||||
/* *
|
||||
* The description of event. This description will be shown in tooltip.
|
||||
*
|
||||
* @type {string}
|
||||
* @product highcharts
|
||||
* @apioption series.timeline.data.description
|
||||
*/
|
||||
|
||||
}(Highcharts));
|
||||
return (function () {
|
||||
|
||||
|
||||
}());
|
||||
}));
|
||||
Reference in New Issue
Block a user