corrade-nucleus-nucleons – Blame information for rev 31

Subversion Repositories:
Rev:
Rev Author Line No. Line
31 office 1 /**
2 * @license Highcharts JS v5.0.14 (2017-07-28)
3 * Highcharts funnel module
4 *
5 * (c) 2010-2017 Torstein Honsi
6 *
7 * License: www.highcharts.com/license
8 */
9 'use strict';
10 (function(factory) {
11 if (typeof module === 'object' && module.exports) {
12 module.exports = factory;
13 } else {
14 factory(Highcharts);
15 }
16 }(function(Highcharts) {
17 (function(Highcharts) {
18 /**
19 * Highcharts funnel module
20 *
21 * (c) 2010-2017 Torstein Honsi
22 *
23 * License: www.highcharts.com/license
24 */
25 /* eslint indent:0 */
26  
27 // create shortcuts
28 var seriesType = Highcharts.seriesType,
29 seriesTypes = Highcharts.seriesTypes,
30 noop = Highcharts.noop,
31 pick = Highcharts.pick,
32 each = Highcharts.each;
33  
34  
35 seriesType('funnel', 'pie',
36 /**
37 * Funnel charts are a type of chart often used to visualize stages in a sales
38 * project, where the top are the initial stages with the most clients.
39 * It requires that the modules/funnel.js file is loaded.
40 *
41 * @sample highcharts/demo/funnel/ Funnel demo
42 * @extends {plotOptions.pie}
43 * @optionparent plotOptions.funnel
44 */
45 {
46  
47 /**
48 */
49 animation: false,
50  
51 /**
52 * The center of the series. By default, it is centered in the middle
53 * of the plot area, so it fills the plot area height.
54 *
55 * @type {Array<String|Number>}
56 * @default ["50%", "50%"]
57 * @since 3.0
58 * @product highcharts
59 */
60 center: ['50%', '50%'],
61  
62 /**
63 * The width of the funnel compared to the width of the plot area,
64 * or the pixel width if it is a number.
65 *
66 * @type {Number|String}
67 * @default 90%
68 * @since 3.0
69 * @product highcharts
70 */
71 width: '90%',
72  
73 /**
74 * The width of the neck, the lower part of the funnel. A number defines
75 * pixel width, a percentage string defines a percentage of the plot
76 * area width.
77 *
78 * @type {Number|String}
79 * @sample {highcharts} highcharts/demo/funnel/ Funnel demo
80 * @default 30%
81 * @since 3.0
82 * @product highcharts
83 */
84 neckWidth: '30%',
85  
86 /**
87 * The height of the funnel or pyramid. If it is a number it defines
88 * the pixel height, if it is a percentage string it is the percentage
89 * of the plot area height.
90 *
91 * @type {Number|String}
92 * @sample {highcharts} highcharts/demo/funnel/ Funnel demo
93 * @since 3.0
94 * @product highcharts
95 */
96 height: '100%',
97  
98 /**
99 * The height of the neck, the lower part of the funnel. A number defines
100 * pixel width, a percentage string defines a percentage of the plot
101 * area height.
102 *
103 * @type {Number|String}
104 * @default 25%
105 * @product highcharts
106 */
107 neckHeight: '25%',
108  
109 /**
110 * A reversed funnel has the widest area down. A reversed funnel with
111 * no neck width and neck height is a pyramid.
112 *
113 * @type {Boolean}
114 * @default false
115 * @since 3.0.10
116 * @product highcharts
117 */
118 reversed: false,
119  
120 /**
121 */
122 size: true, // to avoid adapting to data label size in Pie.drawDataLabels
123  
124  
125 },
126  
127 // Properties
128 {
129 animate: noop,
130  
131 /**
132 * Overrides the pie translate method
133 */
134 translate: function() {
135  
136 var
137 // Get positions - either an integer or a percentage string must be given
138 getLength = function(length, relativeTo) {
139 return (/%$/).test(length) ?
140 relativeTo * parseInt(length, 10) / 100 :
141 parseInt(length, 10);
142 },
143  
144 sum = 0,
145 series = this,
146 chart = series.chart,
147 options = series.options,
148 reversed = options.reversed,
149 ignoreHiddenPoint = options.ignoreHiddenPoint,
150 plotWidth = chart.plotWidth,
151 plotHeight = chart.plotHeight,
152 cumulative = 0, // start at top
153 center = options.center,
154 centerX = getLength(center[0], plotWidth),
155 centerY = getLength(center[1], plotHeight),
156 width = getLength(options.width, plotWidth),
157 tempWidth,
158 getWidthAt,
159 height = getLength(options.height, plotHeight),
160 neckWidth = getLength(options.neckWidth, plotWidth),
161 neckHeight = getLength(options.neckHeight, plotHeight),
162 neckY = (centerY - height / 2) + height - neckHeight,
163 data = series.data,
164 path,
165 fraction,
166 half = options.dataLabels.position === 'left' ? 1 : 0,
167  
168 x1,
169 y1,
170 x2,
171 x3,
172 y3,
173 x4,
174 y5;
175  
176 // Return the width at a specific y coordinate
177 series.getWidthAt = getWidthAt = function(y) {
178 var top = (centerY - height / 2);
179  
180 return y > neckY || height === neckHeight ?
181 neckWidth :
182 neckWidth + (width - neckWidth) * (1 - (y - top) / (height - neckHeight));
183 };
184 series.getX = function(y, half, point) {
185 return centerX + (half ? -1 : 1) * ((getWidthAt(reversed ? 2 * centerY - y : y) / 2) + point.labelDistance);
186 };
187  
188 // Expose
189 series.center = [centerX, centerY, height];
190 series.centerX = centerX;
191  
192 /*
193 * Individual point coordinate naming:
194 *
195 * x1,y1 _________________ x2,y1
196 * \ /
197 * \ /
198 * \ /
199 * \ /
200 * \ /
201 * x3,y3 _________ x4,y3
202 *
203 * Additional for the base of the neck:
204 *
205 * | |
206 * | |
207 * | |
208 * x3,y5 _________ x4,y5
209 */
210  
211  
212  
213  
214 // get the total sum
215 each(data, function(point) {
216 if (!ignoreHiddenPoint || point.visible !== false) {
217 sum += point.y;
218 }
219 });
220  
221 each(data, function(point) {
222 // set start and end positions
223 y5 = null;
224 fraction = sum ? point.y / sum : 0;
225 y1 = centerY - height / 2 + cumulative * height;
226 y3 = y1 + fraction * height;
227 //tempWidth = neckWidth + (width - neckWidth) * ((height - neckHeight - y1) / (height - neckHeight));
228 tempWidth = getWidthAt(y1);
229 x1 = centerX - tempWidth / 2;
230 x2 = x1 + tempWidth;
231 tempWidth = getWidthAt(y3);
232 x3 = centerX - tempWidth / 2;
233 x4 = x3 + tempWidth;
234  
235 // the entire point is within the neck
236 if (y1 > neckY) {
237 x1 = x3 = centerX - neckWidth / 2;
238 x2 = x4 = centerX + neckWidth / 2;
239  
240 // the base of the neck
241 } else if (y3 > neckY) {
242 y5 = y3;
243  
244 tempWidth = getWidthAt(neckY);
245 x3 = centerX - tempWidth / 2;
246 x4 = x3 + tempWidth;
247  
248 y3 = neckY;
249 }
250  
251 if (reversed) {
252 y1 = 2 * centerY - y1;
253 y3 = 2 * centerY - y3;
254 y5 = (y5 ? 2 * centerY - y5 : null);
255 }
256 // save the path
257 path = [
258 'M',
259 x1, y1,
260 'L',
261 x2, y1,
262 x4, y3
263 ];
264 if (y5) {
265 path.push(x4, y5, x3, y5);
266 }
267 path.push(x3, y3, 'Z');
268  
269 // prepare for using shared dr
270 point.shapeType = 'path';
271 point.shapeArgs = {
272 d: path
273 };
274  
275  
276 // for tooltips and data labels
277 point.percentage = fraction * 100;
278 point.plotX = centerX;
279 point.plotY = (y1 + (y5 || y3)) / 2;
280  
281 // Placement of tooltips and data labels
282 point.tooltipPos = [
283 centerX,
284 point.plotY
285 ];
286  
287 // Slice is a noop on funnel points
288 point.slice = noop;
289  
290 // Mimicking pie data label placement logic
291 point.half = half;
292  
293 if (!ignoreHiddenPoint || point.visible !== false) {
294 cumulative += fraction;
295 }
296 });
297 },
298  
299 /**
300 * Funnel items don't have angles (#2289)
301 */
302 sortByAngle: function(points) {
303 points.sort(function(a, b) {
304 return a.plotY - b.plotY;
305 });
306 },
307  
308 /**
309 * Extend the pie data label method
310 */
311 drawDataLabels: function() {
312 var series = this,
313 data = series.data,
314 labelDistance = series.options.dataLabels.distance,
315 leftSide,
316 sign,
317 point,
318 i = data.length,
319 x,
320 y;
321  
322 // In the original pie label anticollision logic, the slots are distributed
323 // from one labelDistance above to one labelDistance below the pie. In funnels
324 // we don't want this.
325 series.center[2] -= 2 * labelDistance;
326  
327 // Set the label position array for each point.
328 while (i--) {
329 point = data[i];
330 leftSide = point.half;
331 sign = leftSide ? 1 : -1;
332 y = point.plotY;
333 point.labelDistance = pick(
334 point.options.dataLabels && point.options.dataLabels.distance,
335 labelDistance
336 );
337  
338 series.maxLabelDistance = Math.max(point.labelDistance, series.maxLabelDistance || 0);
339 x = series.getX(y, leftSide, point);
340  
341 // set the anchor point for data labels
342 point.labelPos = [
343 0, // first break of connector
344 y, // a/a
345 x + (point.labelDistance - 5) * sign, // second break, right outside point shape
346 y, // a/a
347 x + point.labelDistance * sign, // landing point for connector
348 y, // a/a
349 leftSide ? 'right' : 'left', // alignment
350  
351 ];
352 }
353  
354 seriesTypes.pie.prototype.drawDataLabels.call(this);
355 }
356  
357 });
358  
359 /**
360 * Pyramid series type.
361 */
362 seriesType('pyramid', 'funnel',
363 /**
364 * A pyramid series is a special type of funnel, without neck and reversed by default.
365 * @extends funnel
366 * @optionparent plotOptions.pyramid
367 */
368 {
369  
370 /**
371 */
372 neckWidth: '0%',
373  
374 /**
375 */
376 neckHeight: '0%',
377  
378 /**
379 * The pyramid is reversed by default, as opposed to the funnel, which
380 * shares the layout engine, and is not reversed.
381 *
382 * @type {Boolean}
383 * @default true
384 * @since 3.0.10
385 * @product highcharts
386 */
387 reversed: true
388 });
389  
390 }(Highcharts));
391 }));