UNPKG

10.6 kBJavaScriptView Raw
1/**
2 * @license Highcharts JS v5.0.2 (2016-10-26)
3 * X-range series
4 *
5 * (c) 2010-2016 Torstein Honsi, Lars A. V. Cabrera
6 *
7 * --- WORK IN PROGRESS ---
8 *
9 * License: www.highcharts.com/license
10 */
11(function(factory) {
12 if (typeof module === 'object' && module.exports) {
13 module.exports = factory;
14 } else {
15 factory(Highcharts);
16 }
17}(function(Highcharts) {
18 (function(H) {
19 /**
20 * (c) 2014-2016 Highsoft AS
21 * Authors: Torstein Honsi, Lars A. V. Cabrera
22 *
23 * License: www.highcharts.com/license
24 */
25 'use strict';
26
27 var defaultPlotOptions = H.getOptions().plotOptions,
28 color = H.Color,
29 columnType = H.seriesTypes.column,
30 each = H.each,
31 extendClass = H.extendClass,
32 isNumber = H.isNumber,
33 isObject = H.isObject,
34 merge = H.merge,
35 pick = H.pick,
36 seriesTypes = H.seriesTypes,
37 stop = H.stop,
38 wrap = H.wrap,
39 Axis = H.Axis,
40 Point = H.Point,
41 Series = H.Series,
42 pointFormat = '<span style="color:{point.color}">' +
43 '\u25CF' +
44 '</span> {series.name}: <b>{point.yCategory}</b><br/>',
45 xrange = 'xrange';
46
47 defaultPlotOptions.xrange = merge(defaultPlotOptions.column, {
48 tooltip: {
49 pointFormat: pointFormat
50 }
51 });
52 seriesTypes.xrange = extendClass(columnType, {
53 pointClass: extendClass(Point, {
54 // Add x2 and yCategory to the available properties for tooltip formats
55 getLabelConfig: function() {
56 var cfg = Point.prototype.getLabelConfig.call(this);
57
58 cfg.x2 = this.x2;
59 cfg.yCategory = this.yCategory = this.series.yAxis.categories && this.series.yAxis.categories[this.y];
60 return cfg;
61 }
62 }),
63 type: xrange,
64 forceDL: true,
65 parallelArrays: ['x', 'x2', 'y'],
66 requireSorting: false,
67 animate: seriesTypes.line.prototype.animate,
68
69 /**
70 * Borrow the column series metrics, but with swapped axes. This gives free access
71 * to features like groupPadding, grouping, pointWidth etc.
72 */
73 getColumnMetrics: function() {
74 var metrics,
75 chart = this.chart;
76
77 function swapAxes() {
78 each(chart.series, function(s) {
79 var xAxis = s.xAxis;
80 s.xAxis = s.yAxis;
81 s.yAxis = xAxis;
82 });
83 }
84
85 swapAxes();
86
87 this.yAxis.closestPointRange = 1;
88 metrics = columnType.prototype.getColumnMetrics.call(this);
89
90 swapAxes();
91
92 return metrics;
93 },
94
95 /**
96 * Override cropData to show a point where x is outside visible range
97 * but x2 is outside.
98 */
99 cropData: function(xData, yData, min, max) {
100
101 // Replace xData with x2Data to find the appropriate cropStart
102 var cropData = Series.prototype.cropData,
103 crop = cropData.call(this, this.x2Data, yData, min, max);
104
105 // Re-insert the cropped xData
106 crop.xData = xData.slice(crop.start, crop.end);
107
108 return crop;
109 },
110
111 translate: function() {
112 columnType.prototype.translate.apply(this, arguments);
113 var series = this,
114 xAxis = series.xAxis,
115 metrics = series.columnMetrics,
116 minPointLength = series.options.minPointLength || 0;
117
118 each(series.points, function(point) {
119 var plotX = point.plotX,
120 posX = pick(point.x2, point.x + (point.len || 0)),
121 plotX2 = xAxis.toPixels(posX, true),
122 width = plotX2 - plotX,
123 widthDifference,
124 shapeArgs,
125 partialFill;
126
127 if (minPointLength) {
128 widthDifference = minPointLength - width;
129 if (widthDifference < 0) {
130 widthDifference = 0;
131 }
132 plotX -= widthDifference / 2;
133 plotX2 += widthDifference / 2;
134 }
135
136 plotX = Math.max(plotX, -10);
137 plotX2 = Math.min(Math.max(plotX2, -10), xAxis.len + 10);
138
139 point.shapeArgs = {
140 x: plotX,
141 y: point.plotY + metrics.offset,
142 width: plotX2 - plotX,
143 height: metrics.width
144 };
145 point.tooltipPos[0] += width / 2;
146 point.tooltipPos[1] -= metrics.width / 2;
147
148 // Add a partShapeArgs to the point, based on the shapeArgs property
149 partialFill = point.partialFill;
150 if (partialFill) {
151 // Get the partial fill amount
152 if (isObject(partialFill)) {
153 partialFill = partialFill.amount;
154 }
155 // If it was not a number, assume 0
156 if (!isNumber(partialFill)) {
157 partialFill = 0;
158 }
159 shapeArgs = point.shapeArgs;
160 point.partShapeArgs = {
161 x: shapeArgs.x,
162 y: shapeArgs.y + 1,
163 width: shapeArgs.width * partialFill,
164 height: shapeArgs.height - 2
165 };
166 }
167 });
168 },
169
170 drawPoints: function() {
171 var series = this,
172 chart = this.chart,
173 options = series.options,
174 renderer = chart.renderer,
175 animationLimit = options.animationLimit || 250,
176 verb = chart.pointCount < animationLimit ? 'animate' : 'attr';
177
178 // draw the columns
179 each(series.points, function(point) {
180 var plotY = point.plotY,
181 graphic = point.graphic,
182 type = point.shapeType,
183 shapeArgs = point.shapeArgs,
184 partShapeArgs = point.partShapeArgs,
185 seriesOpts = series.options,
186 pfOptions = point.partialFill,
187 fill,
188 state = point.selected && 'select',
189 cutOff = options.stacking && !options.borderRadius;
190
191 if (isNumber(plotY) && point.y !== null) {
192 if (graphic) { // update
193 stop(graphic);
194 point.graphicOriginal[verb](
195 merge(shapeArgs)
196 );
197 if (partShapeArgs) {
198 point.graphicOverlay[verb](
199 merge(partShapeArgs)
200 );
201 }
202
203 } else {
204 point.graphic = graphic = renderer.g('point')
205 .attr({
206 'class': point.getClassName()
207 })
208 .add(point.group || series.group);
209
210 point.graphicOriginal = renderer[type](shapeArgs)
211 .addClass('highcharts-partfill-original')
212 .add(graphic);
213 if (partShapeArgs) {
214 point.graphicOverlay = renderer[type](partShapeArgs)
215 .addClass('highcharts-partfill-overlay')
216 .add(graphic);
217 }
218 }
219
220
221 // Presentational
222 point.graphicOriginal
223 .attr(series.pointAttribs(point, state))
224 .shadow(options.shadow, null, cutOff);
225 if (partShapeArgs) {
226 // Ensure pfOptions is an object
227 if (!isObject(pfOptions)) {
228 pfOptions = {};
229 }
230 if (isObject(seriesOpts.partialFill)) {
231 pfOptions = merge(pfOptions, seriesOpts.partialFill);
232 }
233
234 fill = pfOptions.fill ||
235 color(series.color).brighten(-0.3).get('rgb');
236 point.graphicOverlay
237 .attr(series.pointAttribs(point, state))
238 .attr('fill', fill)
239 .attr('stroke-width', 0)
240 .shadow(options.shadow, null, cutOff);
241 }
242
243
244 } else if (graphic) {
245 point.graphic = graphic.destroy(); // #1269
246 }
247 });
248 }
249 });
250
251 /**
252 * Max x2 should be considered in xAxis extremes
253 */
254 wrap(Axis.prototype, 'getSeriesExtremes', function(proceed) {
255 var axis = this,
256 series = axis.series,
257 dataMax,
258 modMax;
259
260 proceed.call(this);
261 if (axis.isXAxis && series.type === xrange) {
262 dataMax = pick(axis.dataMax, Number.MIN_VALUE);
263 each(this.series, function(series) {
264 each(series.x2Data || [], function(val) {
265 if (val > dataMax) {
266 dataMax = val;
267 modMax = true;
268 }
269 });
270 });
271 if (modMax) {
272 axis.dataMax = dataMax;
273 }
274 }
275 });
276
277 }(Highcharts));
278}));