highcharts-rails 3.0.10 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v3.0.10 (2014-03-10)
5
+ * @license Highcharts JS v4.0.0 (2014-04-22)
6
6
  *
7
7
  * (c) 2009-2014 Torstein Honsi
8
8
  *
@@ -30,7 +30,6 @@ var arrayMin = Highcharts.arrayMin,
30
30
  Tick = Highcharts.Tick,
31
31
  Point = Highcharts.Point,
32
32
  Pointer = Highcharts.Pointer,
33
- TrackerMixin = Highcharts.TrackerMixin,
34
33
  CenteredSeriesMixin = Highcharts.CenteredSeriesMixin,
35
34
  Series = Highcharts.Series,
36
35
  math = Math,
@@ -323,14 +322,9 @@ var radialAxisMixin = {
323
322
  * from center
324
323
  */
325
324
  getPosition: function (value, length) {
326
- if (!this.isCircular) {
327
- length = this.translate(value);
328
- value = this.min;
329
- }
330
-
331
325
  return this.postTranslate(
332
- this.translate(value),
333
- pick(length, this.center[2] / 2) - this.offset
326
+ this.isCircular ? this.translate(value) : 0, // #2848
327
+ pick(this.isCircular ? length : this.translate(value), this.center[2] / 2) - this.offset
334
328
  );
335
329
  },
336
330
 
@@ -343,7 +337,7 @@ var radialAxisMixin = {
343
337
  center = this.center;
344
338
 
345
339
  angle = this.startAngleRad + angle;
346
-
340
+
347
341
  return {
348
342
  x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
349
343
  y: chart.plotTop + center[1] + Math.sin(angle) * radius
@@ -444,7 +438,12 @@ var radialAxisMixin = {
444
438
  }
445
439
  // Concentric polygons
446
440
  } else {
447
- xAxis = chart.xAxis[0];
441
+ // Find the X axis in the same pane
442
+ each(chart.xAxis, function (a) {
443
+ if (a.pane === axis.pane) {
444
+ xAxis = a;
445
+ }
446
+ });
448
447
  ret = [];
449
448
  value = axis.translate(value);
450
449
  tickPositions = xAxis.tickPositions;
@@ -577,7 +576,7 @@ wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, label
577
576
  ret,
578
577
  align = labelOptions.align,
579
578
  angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
580
-
579
+
581
580
  if (axis.isRadial) {
582
581
  ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
583
582
 
@@ -654,7 +653,7 @@ defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
654
653
  marker: null,
655
654
  threshold: null,
656
655
  tooltip: {
657
- pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'
656
+ pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>' // docs
658
657
  },
659
658
  trackByArea: true,
660
659
  dataLabels: {
@@ -663,6 +662,11 @@ defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
663
662
  xHigh: 0,
664
663
  yLow: 0,
665
664
  yHigh: 0
665
+ },
666
+ states: {
667
+ hover: {
668
+ halo: false
669
+ }
666
670
  }
667
671
  });
668
672
 
@@ -909,6 +913,7 @@ seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
909
913
  height,
910
914
  y;
911
915
 
916
+ point.tooltipPos = null; // don't inherit from column
912
917
  point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
913
918
  point.plotLow = point.plotY;
914
919
 
@@ -947,6 +952,7 @@ seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
947
952
  defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
948
953
  dataLabels: {
949
954
  enabled: true,
955
+ defer: false,
950
956
  y: 15,
951
957
  borderWidth: 1,
952
958
  borderColor: 'silver',
@@ -1169,8 +1175,7 @@ var GaugeSeries = {
1169
1175
  if (pick(redraw, true)) {
1170
1176
  this.chart.redraw();
1171
1177
  }
1172
- },
1173
- drawTracker: TrackerMixin.drawTrackerPoint
1178
+ }
1174
1179
  };
1175
1180
  seriesTypes.gauge = extendClass(seriesTypes.line, GaugeSeries);
1176
1181
 
@@ -1194,7 +1199,7 @@ defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
1194
1199
  //stemWidth: null,
1195
1200
  threshold: null,
1196
1201
  tooltip: {
1197
- pointFormat: '<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>' +
1202
+ pointFormat: '<span style="color:{series.color}">\u25CF</span> <b> {series.name}</b><br/>' + // docs
1198
1203
  'Maximum: {point.high}<br/>' +
1199
1204
  'Upper quartile: {point.q3}<br/>' +
1200
1205
  'Median: {point.median}<br/>' +
@@ -1338,8 +1343,7 @@ seriesTypes.boxplot = extendClass(seriesTypes.column, {
1338
1343
  'M',
1339
1344
  crispX, q1Plot,
1340
1345
  'L',
1341
- crispX, lowPlot,
1342
- 'z'
1346
+ crispX, lowPlot
1343
1347
  ];
1344
1348
 
1345
1349
  // The box
@@ -1398,8 +1402,7 @@ seriesTypes.boxplot = extendClass(seriesTypes.column, {
1398
1402
  medianPlot,
1399
1403
  'L',
1400
1404
  right,
1401
- medianPlot,
1402
- 'z'
1405
+ medianPlot
1403
1406
  ];
1404
1407
 
1405
1408
  // Create or update the graphics
@@ -1457,7 +1460,7 @@ defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
1457
1460
  grouping: false,
1458
1461
  linkedTo: ':previous',
1459
1462
  tooltip: {
1460
- pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'
1463
+ pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
1461
1464
  },
1462
1465
  whiskerWidth: null
1463
1466
  });
@@ -1536,8 +1539,7 @@ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1536
1539
  y,
1537
1540
  previousY,
1538
1541
  stackPoint,
1539
- threshold = options.threshold,
1540
- crispCorr = (options.borderWidth % 2) / 2;
1542
+ threshold = options.threshold;
1541
1543
 
1542
1544
  // run column series translate
1543
1545
  seriesTypes.column.prototype.translate.apply(this);
@@ -1552,7 +1554,7 @@ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1552
1554
 
1553
1555
  // get current stack
1554
1556
  stack = series.getStack(i);
1555
- stackPoint = stack.points[series.index];
1557
+ stackPoint = stack.points[series.index + ',' + i];
1556
1558
 
1557
1559
  // override point value for sums
1558
1560
  if (isNaN(point.y)) {
@@ -1580,7 +1582,7 @@ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1580
1582
  shapeArgs.height *= -1;
1581
1583
  }
1582
1584
 
1583
- point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;
1585
+ point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - (series.borderWidth % 2) / 2;
1584
1586
  shapeArgs.height = mathRound(shapeArgs.height);
1585
1587
  point.yBottom = shapeArgs.y + shapeArgs.height;
1586
1588
  }
@@ -1676,7 +1678,7 @@ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1676
1678
 
1677
1679
  var data = this.data,
1678
1680
  length = data.length,
1679
- lineWidth = this.options.lineWidth + this.options.borderWidth,
1681
+ lineWidth = this.options.lineWidth + this.borderWidth,
1680
1682
  normalizer = mathRound(lineWidth) % 2 / 2,
1681
1683
  path = [],
1682
1684
  M = 'M',
@@ -1741,6 +1743,7 @@ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1741
1743
  // 1 - set default options
1742
1744
  defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
1743
1745
  dataLabels: {
1746
+ format: '{point.z}', // docs?
1744
1747
  inside: true,
1745
1748
  style: {
1746
1749
  color: 'white',
@@ -1758,6 +1761,13 @@ defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
1758
1761
  maxSize: '20%',
1759
1762
  // negativeColor: null,
1760
1763
  // sizeBy: 'area'
1764
+ states: {
1765
+ hover: {
1766
+ halo: {
1767
+ size: 5 // docs
1768
+ }
1769
+ }
1770
+ },
1761
1771
  tooltip: {
1762
1772
  pointFormat: '({point.x}, {point.y}), Size: {point.z}'
1763
1773
  },
@@ -1765,9 +1775,16 @@ defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
1765
1775
  zThreshold: 0
1766
1776
  });
1767
1777
 
1778
+ var BubblePoint = extendClass(Point, {
1779
+ haloPath: function () {
1780
+ return Point.prototype.haloPath.call(this, this.shapeArgs.r + this.series.options.states.hover.halo.size);
1781
+ }
1782
+ });
1783
+
1768
1784
  // 2 - Create the series object
1769
1785
  seriesTypes.bubble = extendClass(seriesTypes.scatter, {
1770
1786
  type: 'bubble',
1787
+ pointClass: BubblePoint,
1771
1788
  pointArrayMap: ['y', 'z'],
1772
1789
  parallelArrays: ['x', 'y', 'z'],
1773
1790
  trackerGroups: ['group', 'dataLabelsGroup'],
@@ -2309,7 +2326,7 @@ Axis.prototype.beforePadding = function () {
2309
2326
 
2310
2327
  group.attr(attribs);
2311
2328
  if (markerGroup) {
2312
- markerGroup.attrSetters = group.attrSetters;
2329
+ //markerGroup.attrSetters = group.attrSetters;
2313
2330
  markerGroup.attr(attribs);
2314
2331
  }
2315
2332
 
@@ -2406,7 +2423,10 @@ Axis.prototype.beforePadding = function () {
2406
2423
  }
2407
2424
  )
2408
2425
  };
2409
- this.toXY(point); // provide correct plotX, plotY for tooltip
2426
+ // Provide correct plotX, plotY for tooltip
2427
+ this.toXY(point);
2428
+ point.tooltipPos = [point.plotX, point.plotY];
2429
+ point.ttBelow = point.plotY > center[1];
2410
2430
  }
2411
2431
  }
2412
2432
  });
@@ -2908,7 +2908,7 @@ if (CanvasRenderingContext2D) {
2908
2908
  });
2909
2909
  }
2910
2910
  }/**
2911
- * @license Highcharts JS v3.0.10 (2014-03-10)
2911
+ * @license Highcharts JS v4.0.0 (2014-04-22)
2912
2912
  * CanVGRenderer Extension module
2913
2913
  *
2914
2914
  * (c) 2011-2012 Torstein Honsi, Erik Olsson
@@ -583,10 +583,14 @@
583
583
  complete: function (dataOptions) {
584
584
 
585
585
  // Merge series configs
586
- if (userOptions.series) {
587
- each(userOptions.series, function (series, i) {
588
- userOptions.series[i] = Highcharts.merge(series, dataOptions.series[i]);
589
- });
586
+ if (userOptions.hasOwnProperty('series')) {
587
+ if (typeof userOptions.series === 'object') {
588
+ each(userOptions.series, function (series, i) {
589
+ userOptions.series[i] = Highcharts.merge(series, dataOptions.series[i]);
590
+ });
591
+ } else { // Allow merging in dataOptions.series (#2856)
592
+ delete userOptions.series;
593
+ }
590
594
  }
591
595
 
592
596
  // Do the merge
@@ -108,7 +108,7 @@
108
108
 
109
109
  // Record options for all current series
110
110
  each(oldSeries.chart.series, function (series) {
111
- if (series.xAxis === xAxis && series.yAxis === yAxis) {
111
+ if (series.xAxis === xAxis) {
112
112
  levelSeries.push(series);
113
113
  levelSeriesOptions.push(series.userOptions);
114
114
  series.levelNumber = series.levelNumber || 0;
@@ -223,13 +223,15 @@
223
223
  drilldownLevels = chart.drilldownLevels,
224
224
  levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
225
225
  i = drilldownLevels.length,
226
+ chartSeries = chart.series,
227
+ seriesI = chartSeries.length,
226
228
  level,
227
229
  oldSeries,
228
230
  newSeries,
229
231
  oldExtremes,
230
232
  addSeries = function (seriesOptions) {
231
233
  var addedSeries;
232
- each(chart.series, function (series) {
234
+ each(chartSeries, function (series) {
233
235
  if (series.userOptions === seriesOptions) {
234
236
  addedSeries = series;
235
237
  }
@@ -250,7 +252,16 @@
250
252
  if (level.levelNumber === levelNumber) {
251
253
  drilldownLevels.pop();
252
254
 
255
+ // Get the lower series by reference or id
253
256
  oldSeries = level.lowerSeries;
257
+ if (!oldSeries.chart) { // #2786
258
+ while (seriesI--) {
259
+ if (chartSeries[seriesI].options.id === level.lowerSeriesOptions.id) {
260
+ oldSeries = chartSeries[seriesI];
261
+ break;
262
+ }
263
+ }
264
+ }
254
265
 
255
266
  each(level.levelSeriesOptions, addSeries);
256
267
 
@@ -258,12 +269,13 @@
258
269
 
259
270
  if (newSeries.type === oldSeries.type) {
260
271
  newSeries.drilldownLevel = level;
261
- newSeries.options.animation = true;
272
+ newSeries.options.animation = chart.options.drilldown.animation;
262
273
 
263
274
  if (oldSeries.animateDrillupFrom) {
264
275
  oldSeries.animateDrillupFrom(level);
265
276
  }
266
277
  }
278
+ newSeries.levelNumber = levelNumber;
267
279
 
268
280
  oldSeries.remove(false);
269
281
 
@@ -369,35 +381,50 @@
369
381
  */
370
382
  ColumnSeries.prototype.animateDrillupFrom = function (level) {
371
383
  var animationOptions = this.chart.options.drilldown.animation,
372
- group = this.group;
384
+ group = this.group,
385
+ series = this;
386
+
387
+ // Cancel mouse events on the series group (#2787)
388
+ each(series.trackerGroups, function (key) {
389
+ if (series[key]) { // we don't always have dataLabelsGroup
390
+ series[key].on('mouseover');
391
+ }
392
+ });
393
+
373
394
 
374
395
  delete this.group;
375
396
  each(this.points, function (point) {
376
397
  var graphic = point.graphic,
377
- startColor = H.Color(point.color).rgba;
398
+ startColor = H.Color(point.color).rgba,
399
+ endColor = H.Color(level.color).rgba,
400
+ complete = function () {
401
+ graphic.destroy();
402
+ if (group) {
403
+ group = group.destroy();
404
+ }
405
+ };
378
406
 
379
407
  if (graphic) {
380
408
 
381
409
  delete point.graphic;
382
410
 
383
- /*jslint unparam: true*/
384
- graphic.animate(level.shapeArgs, H.merge(animationOptions, {
385
-
386
- step: function (val, fx) {
387
- if (fx.prop === 'start') {
388
- this.attr({
389
- fill: tweenColors(startColor, H.Color(level.color).rgba, fx.pos)
390
- });
391
- }
392
- },
393
- complete: function () {
394
- graphic.destroy();
395
- if (group) {
396
- group = group.destroy();
397
- }
398
- }
399
- }));
400
- /*jslint unparam: false*/
411
+ if (animationOptions) {
412
+ /*jslint unparam: true*/
413
+ graphic.animate(level.shapeArgs, H.merge(animationOptions, {
414
+ step: function (val, fx) {
415
+ if (fx.prop === 'start' && startColor.length === 4 && endColor.length === 4) {
416
+ this.attr({
417
+ fill: tweenColors(startColor, endColor, fx.pos)
418
+ });
419
+ }
420
+ },
421
+ complete: complete
422
+ }));
423
+ /*jslint unparam: false*/
424
+ } else {
425
+ graphic.attr(level.shapeArgs);
426
+ complete();
427
+ }
401
428
  }
402
429
  });
403
430
  };
@@ -426,10 +453,9 @@
426
453
  .attr(H.merge(animateFrom, {
427
454
  start: start + i * startAngle,
428
455
  end: start + (i + 1) * startAngle
429
- }))
430
- .animate(point.shapeArgs, H.merge(animationOptions, {
456
+ }))[animationOptions ? 'animate' : 'attr'](point.shapeArgs, H.merge(animationOptions, {
431
457
  step: function (val, fx) {
432
- if (fx.prop === 'start') {
458
+ if (fx.prop === 'start' && startColor.length === 4 && endColor.length === 4) {
433
459
  this.attr({
434
460
  fill: tweenColors(startColor, endColor, fx.pos)
435
461
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v3.0.10 (2014-03-10)
2
+ * @license Highcharts JS v4.0.0 (2014-04-22)
3
3
  * Exporting module
4
4
  *
5
5
  * (c) 2010-2014 Torstein Honsi
@@ -22,6 +22,7 @@ var defaultOptions = Highcharts.getOptions(),
22
22
 
23
23
  // set default options
24
24
  defaultPlotOptions.funnel = merge(defaultPlotOptions.pie, {
25
+ animation: false,
25
26
  center: ['50%', '50%'],
26
27
  width: '90%',
27
28
  neckWidth: '30%',
@@ -1,60 +1,606 @@
1
- (function (H) {
2
- var seriesTypes = H.seriesTypes,
3
- each = H.each;
1
+ /**
2
+ * @license Highcharts JS v4.0.0 (2014-04-22)
3
+ *
4
+ * (c) 2011-2014 Torstein Honsi
5
+ *
6
+ * License: www.highcharts.com/license
7
+ */
8
+
9
+ /*global HighchartsAdapter*/
10
+ (function (Highcharts) {
11
+
12
+
13
+ var UNDEFINED,
14
+ Axis = Highcharts.Axis,
15
+ Chart = Highcharts.Chart,
16
+ Color = Highcharts.Color,
17
+ Legend = Highcharts.Legend,
18
+ LegendSymbolMixin = Highcharts.LegendSymbolMixin,
19
+ Series = Highcharts.Series,
4
20
 
5
- seriesTypes.heatmap = H.extendClass(seriesTypes.map, {
6
- useMapGeometry: false,
7
- pointArrayMap: ['y', 'value'],
8
- init: function () {
9
- seriesTypes.map.prototype.init.apply(this, arguments);
10
- this.pointRange = this.options.colsize || 1;
11
- // TODO: similar logic for the Y axis
12
- },
13
- translate: function () {
14
- var series = this,
15
- options = series.options,
16
- xAxis = series.xAxis,
17
- yAxis = series.yAxis;
21
+ defaultOptions = Highcharts.getOptions(),
22
+ each = Highcharts.each,
23
+ extend = Highcharts.extend,
24
+ extendClass = Highcharts.extendClass,
25
+ merge = Highcharts.merge,
26
+ pick = Highcharts.pick,
27
+ numberFormat = Highcharts.numberFormat,
28
+ seriesTypes = Highcharts.seriesTypes,
29
+ wrap = Highcharts.wrap,
30
+ noop = function () {};
18
31
 
19
- series.generatePoints();
20
32
 
21
- each(series.points, function (point) {
22
- var xPad = (options.colsize || 1) / 2,
23
- yPad = (options.rowsize || 1) / 2,
24
- x1 = Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)),
25
- x2 = Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)),
26
- y1 = Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
27
- y2 = Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1));
28
-
29
-
30
- point.plotY = 1; // Pass test in Column.drawPoints
31
-
32
- point.shapeType = 'rect';
33
- point.shapeArgs = {
34
- x: Math.min(x1, x2),
35
- y: Math.min(y1, y2),
36
- width: Math.abs(x2 - x1),
37
- height: Math.abs(y2 - y1)
38
- };
39
- });
40
-
41
- series.pointRange = options.colsize || 1;
42
- series.translateColors();
33
+
34
+
35
+ /**
36
+ * The ColorAxis object for inclusion in gradient legends
37
+ */
38
+ var ColorAxis = Highcharts.ColorAxis = function () {
39
+ this.isColorAxis = true;
40
+ this.init.apply(this, arguments);
41
+ };
42
+ extend(ColorAxis.prototype, Axis.prototype);
43
+ extend(ColorAxis.prototype, {
44
+ defaultColorAxisOptions: {
45
+ lineWidth: 0,
46
+ gridLineWidth: 1,
47
+ tickPixelInterval: 72,
48
+ startOnTick: true,
49
+ endOnTick: true,
50
+ offset: 0,
51
+ marker: { // docs: use another name?
52
+ animation: {
53
+ duration: 50
54
+ },
55
+ color: 'gray',
56
+ width: 0.01
43
57
  },
44
-
45
- animate: function () {},
46
- getBox: function () {},
58
+ labels: {
59
+ overflow: 'justify'
60
+ },
61
+ minColor: '#EFEFFF',
62
+ maxColor: '#003875',
63
+ tickLength: 5
64
+ },
65
+ init: function (chart, userOptions) {
66
+ var horiz = chart.options.legend.layout !== 'vertical',
67
+ options;
68
+
69
+ // Build the options
70
+ options = merge(this.defaultColorAxisOptions, {
71
+ side: horiz ? 2 : 1,
72
+ reversed: !horiz
73
+ }, userOptions, {
74
+ isX: horiz,
75
+ opposite: !horiz,
76
+ showEmpty: false,
77
+ title: null,
78
+ isColor: true
79
+ });
80
+
81
+ Axis.prototype.init.call(this, chart, options);
47
82
 
48
- getExtremes: function () {
49
- // Get the extremes from the value data
50
- H.Series.prototype.getExtremes.call(this, this.valueData);
51
- this.valueMin = this.dataMin;
52
- this.valueMax = this.dataMax;
83
+ // Base init() pushes it to the xAxis array, now pop it again
84
+ //chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop();
53
85
 
54
- // Get the extremes from the y data
55
- H.Series.prototype.getExtremes.call(this);
86
+ // Prepare data classes
87
+ if (userOptions.dataClasses) {
88
+ this.initDataClasses(userOptions);
56
89
  }
90
+ this.initStops(userOptions);
91
+
92
+ // Override original axis properties
93
+ this.isXAxis = true;
94
+ this.horiz = horiz;
95
+ this.zoomEnabled = false;
96
+ },
97
+
98
+ /*
99
+ * Return an intermediate color between two colors, according to pos where 0
100
+ * is the from color and 1 is the to color
101
+ */
102
+ tweenColors: function (from, to, pos) {
103
+ // Check for has alpha, because rgba colors perform worse due to lack of
104
+ // support in WebKit.
105
+ var hasAlpha = (to.rgba[3] !== 1 || from.rgba[3] !== 1);
106
+ return (hasAlpha ? 'rgba(' : 'rgb(') +
107
+ Math.round(to.rgba[0] + (from.rgba[0] - to.rgba[0]) * (1 - pos)) + ',' +
108
+ Math.round(to.rgba[1] + (from.rgba[1] - to.rgba[1]) * (1 - pos)) + ',' +
109
+ Math.round(to.rgba[2] + (from.rgba[2] - to.rgba[2]) * (1 - pos)) +
110
+ (hasAlpha ? (',' + (to.rgba[3] + (from.rgba[3] - to.rgba[3]) * (1 - pos))) : '') + ')';
111
+ },
112
+
113
+ initDataClasses: function (userOptions) {
114
+ var axis = this,
115
+ chart = this.chart,
116
+ dataClasses,
117
+ colorCounter = 0,
118
+ options = this.options;
119
+ this.dataClasses = dataClasses = [];
120
+
121
+ each(userOptions.dataClasses, function (dataClass, i) {
122
+ var colors;
123
+
124
+ dataClass = merge(dataClass);
125
+ dataClasses.push(dataClass);
126
+ if (!dataClass.color) {
127
+ if (options.dataClassColor === 'category') {
128
+ colors = chart.options.colors;
129
+ dataClass.color = colors[colorCounter++];
130
+ // loop back to zero
131
+ if (colorCounter === colors.length) {
132
+ colorCounter = 0;
133
+ }
134
+ } else {
135
+ dataClass.color = axis.tweenColors(Color(options.minColor), Color(options.maxColor), i / (userOptions.dataClasses.length - 1));
136
+ }
137
+ }
138
+ });
139
+ },
140
+
141
+ initStops: function (userOptions) {
142
+ this.stops = userOptions.stops || [
143
+ [0, this.options.minColor],
144
+ [1, this.options.maxColor]
145
+ ];
146
+ each(this.stops, function (stop) {
147
+ stop.color = Color(stop[1]);
148
+ });
149
+ },
150
+
151
+ /**
152
+ * Extend the setOptions method to process extreme colors and color
153
+ * stops.
154
+ */
155
+ setOptions: function (userOptions) {
156
+ Axis.prototype.setOptions.call(this, userOptions);
157
+
158
+ this.options.crosshair = this.options.marker;
159
+ this.coll = 'colorAxis';
160
+ },
161
+
162
+ setAxisSize: function () {
163
+ var symbol = this.legendSymbol,
164
+ chart = this.chart,
165
+ x,
166
+ y,
167
+ width,
168
+ height;
169
+
170
+ if (symbol) {
171
+ this.left = x = symbol.attr('x');
172
+ this.top = y = symbol.attr('y');
173
+ this.width = width = symbol.attr('width');
174
+ this.height = height = symbol.attr('height');
175
+ this.right = chart.chartWidth - x - width;
176
+ this.bottom = chart.chartHeight - y - height;
177
+
178
+ this.len = this.horiz ? width : height;
179
+ this.pos = this.horiz ? x : y;
180
+ }
181
+ },
182
+
183
+ /**
184
+ * Translate from a value to a color
185
+ */
186
+ toColor: function (value, point) {
187
+ var pos,
188
+ stops = this.stops,
189
+ from,
190
+ to,
191
+ color,
192
+ dataClasses = this.dataClasses,
193
+ dataClass,
194
+ i;
195
+
196
+ if (dataClasses) {
197
+ i = dataClasses.length;
198
+ while (i--) {
199
+ dataClass = dataClasses[i];
200
+ from = dataClass.from;
201
+ to = dataClass.to;
202
+ if ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) {
203
+ color = dataClass.color;
204
+ if (point) {
205
+ point.dataClass = i;
206
+ }
207
+ break;
208
+ }
209
+ }
210
+
211
+ } else {
212
+
213
+ if (this.isLog) {
214
+ value = this.val2lin(value);
215
+ }
216
+ pos = 1 - ((this.max - value) / (this.max - this.min));
217
+ i = stops.length;
218
+ while (i--) {
219
+ if (pos > stops[i][0]) {
220
+ break;
221
+ }
222
+ }
223
+ from = stops[i] || stops[i + 1];
224
+ to = stops[i + 1] || from;
225
+
226
+ // The position within the gradient
227
+ pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1);
228
+
229
+ color = this.tweenColors(
230
+ from.color,
231
+ to.color,
232
+ pos
233
+ );
234
+ }
235
+ return color;
236
+ },
237
+
238
+ getOffset: function () {
239
+ var group = this.legendGroup;
240
+ if (group) {
241
+
242
+ Axis.prototype.getOffset.call(this);
57
243
 
58
- });
244
+ if (!this.axisGroup.parentGroup) {
245
+
246
+ // Move the axis elements inside the legend group
247
+ this.axisGroup.add(group);
248
+ this.gridGroup.add(group);
249
+ this.labelGroup.add(group);
250
+
251
+ this.added = true;
252
+ }
253
+ }
254
+ },
255
+
256
+ /**
257
+ * Create the color gradient
258
+ */
259
+ setLegendColor: function () {
260
+ var grad,
261
+ horiz = this.horiz,
262
+ options = this.options;
263
+
264
+ grad = horiz ? [0, 0, 1, 0] : [0, 0, 0, 1];
265
+ this.legendColor = {
266
+ linearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },
267
+ stops: options.stops || [
268
+ [0, options.minColor],
269
+ [1, options.maxColor]
270
+ ]
271
+ };
272
+ },
273
+
274
+ /**
275
+ * The color axis appears inside the legend and has its own legend symbol
276
+ */
277
+ drawLegendSymbol: function (legend, item) {
278
+ var padding = legend.padding,
279
+ legendOptions = legend.options,
280
+ horiz = this.horiz,
281
+ box,
282
+ width = pick(legendOptions.symbolWidth, horiz ? 200 : 12),
283
+ height = pick(legendOptions.symbolHeight, horiz ? 12 : 200),
284
+ labelPadding = pick(legendOptions.labelPadding, horiz ? 10 : 30);
285
+
286
+ this.setLegendColor();
287
+
288
+ // Create the gradient
289
+ item.legendSymbol = this.chart.renderer.rect(
290
+ 0,
291
+ legend.baseline - 11,
292
+ width,
293
+ height
294
+ ).attr({
295
+ zIndex: 1
296
+ }).add(item.legendGroup);
297
+ box = item.legendSymbol.getBBox();
298
+
299
+ // Set how much space this legend item takes up
300
+ this.legendItemWidth = width + padding + (horiz ? 0 : labelPadding);
301
+ this.legendItemHeight = height + padding + (horiz ? labelPadding : 0);
302
+ },
303
+ /**
304
+ * Fool the legend
305
+ */
306
+ setState: noop,
307
+ visible: true,
308
+ setVisible: noop,
309
+ getSeriesExtremes: function () {
310
+ var series;
311
+ if (this.series.length) {
312
+ series = this.series[0];
313
+ this.dataMin = series.valueMin;
314
+ this.dataMax = series.valueMax;
315
+ }
316
+ },
317
+ drawCrosshair: function (e, point) {
318
+ var newCross = !this.cross,
319
+ plotX = point && point.plotX,
320
+ plotY = point && point.plotY,
321
+ crossPos,
322
+ axisPos = this.pos,
323
+ axisLen = this.len;
324
+
325
+ if (point) {
326
+ crossPos = this.toPixels(point.value);
327
+ if (crossPos < axisPos) {
328
+ crossPos = axisPos - 2;
329
+ } else if (crossPos > axisPos + axisLen) {
330
+ crossPos = axisPos + axisLen + 2;
331
+ }
332
+
333
+ point.plotX = crossPos;
334
+ point.plotY = this.len - crossPos;
335
+ Axis.prototype.drawCrosshair.call(this, e, point);
336
+ point.plotX = plotX;
337
+ point.plotY = plotY;
338
+
339
+ if (!newCross && this.cross) {
340
+ this.cross
341
+ .attr({
342
+ fill: this.crosshair.color
343
+ })
344
+ .add(this.labelGroup);
345
+ }
346
+ }
347
+ },
348
+ getPlotLinePath: function (a, b, c, d, pos) {
349
+ if (pos) { // crosshairs only
350
+ return this.horiz ?
351
+ ['M', pos - 4, this.top - 6, 'L', pos + 4, this.top - 6, pos, this.top, 'Z'] :
352
+ ['M', this.left, pos, 'L', this.left - 6, pos + 6, this.left - 6, pos - 6, 'Z'];
353
+ } else {
354
+ return Axis.prototype.getPlotLinePath.call(this, a, b, c, d);
355
+ }
356
+ },
357
+
358
+ update: function (newOptions, redraw) {
359
+ each(this.series, function (series) {
360
+ series.isDirtyData = true; // Needed for Axis.update when choropleth colors change
361
+ });
362
+ Axis.prototype.update.call(this, newOptions, redraw);
363
+ if (this.legendItem) {
364
+ this.setLegendColor();
365
+ this.chart.legend.colorizeItem(this, true);
366
+ }
367
+ },
368
+
369
+ /**
370
+ * Get the legend item symbols for data classes
371
+ */
372
+ getDataClassLegendSymbols: function () {
373
+ var axis = this,
374
+ chart = this.chart,
375
+ legendItems = [],
376
+ legendOptions = chart.options.legend,
377
+ valueDecimals = legendOptions.valueDecimals,
378
+ valueSuffix = legendOptions.valueSuffix || '',
379
+ name;
380
+
381
+ each(this.dataClasses, function (dataClass, i) {
382
+ var vis = true,
383
+ from = dataClass.from,
384
+ to = dataClass.to;
385
+
386
+ // Assemble the default name. This can be overridden by legend.options.labelFormatter
387
+ name = '';
388
+ if (from === UNDEFINED) {
389
+ name = '< ';
390
+ } else if (to === UNDEFINED) {
391
+ name = '> ';
392
+ }
393
+ if (from !== UNDEFINED) {
394
+ name += numberFormat(from, valueDecimals) + valueSuffix;
395
+ }
396
+ if (from !== UNDEFINED && to !== UNDEFINED) {
397
+ name += ' - ';
398
+ }
399
+ if (to !== UNDEFINED) {
400
+ name += numberFormat(to, valueDecimals) + valueSuffix;
401
+ }
402
+
403
+ // Add a mock object to the legend items
404
+ legendItems.push(extend({
405
+ chart: chart,
406
+ name: name,
407
+ options: {},
408
+ drawLegendSymbol: LegendSymbolMixin.drawRectangle,
409
+ visible: true,
410
+ setState: noop,
411
+ setVisible: function () {
412
+ vis = this.visible = !vis;
413
+ each(axis.series, function (series) {
414
+ each(series.points, function (point) {
415
+ if (point.dataClass === i) {
416
+ point.setVisible(vis);
417
+ }
418
+ });
419
+ });
420
+
421
+ chart.legend.colorizeItem(this, vis);
422
+ }
423
+ }, dataClass));
424
+ });
425
+ return legendItems;
426
+ },
427
+ name: '' // Prevents 'undefined' in legend in IE8
428
+ });
429
+
430
+
431
+
432
+ /**
433
+ * Extend the chart getAxes method to also get the color axis
434
+ */
435
+ wrap(Chart.prototype, 'getAxes', function (proceed) {
436
+
437
+ var options = this.options,
438
+ colorAxisOptions = options.colorAxis;
439
+
440
+ proceed.call(this);
441
+
442
+ this.colorAxis = [];
443
+ if (colorAxisOptions) {
444
+ proceed = new ColorAxis(this, colorAxisOptions); // Fake assignment for jsLint
445
+ }
446
+ });
447
+
448
+
449
+ /**
450
+ * Wrap the legend getAllItems method to add the color axis. This also removes the
451
+ * axis' own series to prevent them from showing up individually.
452
+ */
453
+ wrap(Legend.prototype, 'getAllItems', function (proceed) {
454
+ var allItems = [],
455
+ colorAxis = this.chart.colorAxis[0];
456
+
457
+ if (colorAxis) {
458
+
459
+ // Data classes
460
+ if (colorAxis.options.dataClasses) {
461
+ allItems = allItems.concat(colorAxis.getDataClassLegendSymbols());
462
+ // Gradient legend
463
+ } else {
464
+ // Add this axis on top
465
+ allItems.push(colorAxis);
466
+ }
467
+
468
+ // Don't add the color axis' series
469
+ each(colorAxis.series, function (series) {
470
+ series.options.showInLegend = false;
471
+ });
472
+ }
473
+
474
+ return allItems.concat(proceed.call(this));
475
+ });/**
476
+ * Mixin for maps and heatmaps
477
+ */
478
+ var colorSeriesMixin = {
479
+
480
+ pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
481
+ stroke: 'borderColor',
482
+ 'stroke-width': 'borderWidth',
483
+ fill: 'color',
484
+ dashstyle: 'dashStyle'
485
+ },
486
+ pointArrayMap: ['value'],
487
+ axisTypes: ['xAxis', 'yAxis', 'colorAxis'],
488
+ optionalAxis: 'colorAxis',
489
+ trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
490
+ getSymbol: noop,
491
+ parallelArrays: ['x', 'y', 'value'],
59
492
 
493
+ /**
494
+ * In choropleth maps, the color is a result of the value, so this needs translation too
495
+ */
496
+ translateColors: function () {
497
+ var series = this,
498
+ nullColor = this.options.nullColor,
499
+ colorAxis = this.colorAxis;
500
+
501
+ each(this.data, function (point) {
502
+ var value = point.value,
503
+ color;
504
+
505
+ color = value === null ? nullColor : colorAxis ? colorAxis.toColor(value, point) : (point.color) || series.color;
506
+
507
+ if (color) {
508
+ point.color = color;
509
+ }
510
+ });
511
+ }
512
+ };
513
+ /**
514
+ * Extend the default options with map options
515
+ */
516
+ defaultOptions.plotOptions.heatmap = merge(defaultOptions.plotOptions.scatter, {
517
+ animation: false,
518
+ borderWidth: 0,
519
+ nullColor: '#F8F8F8',
520
+ dataLabels: {
521
+ format: '{point.value}',
522
+ verticalAlign: 'middle',
523
+ crop: false,
524
+ overflow: false,
525
+ style: {
526
+ color: 'white',
527
+ fontWeight: 'bold',
528
+ textShadow: '0 0 5px black'
529
+ }
530
+ },
531
+ marker: null,
532
+ tooltip: {
533
+ pointFormat: '{point.x}, {point.y}: {point.value}<br/>'
534
+ },
535
+ states: {
536
+ normal: {
537
+ animation: true
538
+ },
539
+ hover: {
540
+ brightness: 0.2
541
+ }
542
+ }
543
+ });
544
+
545
+ // The Heatmap series type
546
+ seriesTypes.heatmap = extendClass(seriesTypes.scatter, merge(colorSeriesMixin, {
547
+ type: 'heatmap',
548
+ pointArrayMap: ['y', 'value'],
549
+ hasPointSpecificOptions: true,
550
+ supportsDrilldown: true,
551
+ getExtremesFromAll: true,
552
+ init: function () {
553
+ seriesTypes.scatter.prototype.init.apply(this, arguments);
554
+ this.pointRange = this.options.colsize || 1;
555
+ this.yAxis.axisPointRange = this.options.rowsize || 1; // general point range
556
+ },
557
+ translate: function () {
558
+ var series = this,
559
+ options = series.options,
560
+ xAxis = series.xAxis,
561
+ yAxis = series.yAxis;
562
+
563
+ series.generatePoints();
564
+
565
+ each(series.points, function (point) {
566
+ var xPad = (options.colsize || 1) / 2,
567
+ yPad = (options.rowsize || 1) / 2,
568
+ x1 = Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)),
569
+ x2 = Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)),
570
+ y1 = Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
571
+ y2 = Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1));
572
+
573
+ // Set plotX and plotY for use in K-D-Tree and more
574
+ point.plotX = (x1 + x2) / 2;
575
+ point.plotY = (y1 + y2) / 2;
576
+
577
+ point.shapeType = 'rect';
578
+ point.shapeArgs = {
579
+ x: Math.min(x1, x2),
580
+ y: Math.min(y1, y2),
581
+ width: Math.abs(x2 - x1),
582
+ height: Math.abs(y2 - y1)
583
+ };
584
+ });
585
+
586
+ series.translateColors();
587
+ },
588
+ drawPoints: seriesTypes.column.prototype.drawPoints,
589
+ animate: noop,
590
+ getBox: noop,
591
+ drawLegendSymbol: LegendSymbolMixin.drawRectangle,
592
+
593
+ getExtremes: function () {
594
+ // Get the extremes from the value data
595
+ Series.prototype.getExtremes.call(this, this.valueData);
596
+ this.valueMin = this.dataMin;
597
+ this.valueMax = this.dataMax;
598
+
599
+ // Get the extremes from the y data
600
+ Series.prototype.getExtremes.call(this);
601
+ }
602
+
603
+ }));
604
+
605
+
60
606
  }(Highcharts));