highcharts-rails 4.2.4 → 4.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 97714de447dedd03f4f7d06964a96824433b7915
4
- data.tar.gz: e14b8a7a89bf5de5a48bb2c2118036292fc4e96d
3
+ metadata.gz: 2939d4feed91c6aa1664e68c33af311c52c7bccc
4
+ data.tar.gz: cee7f47daf110070a74c538933732d46f056e8ad
5
5
  SHA512:
6
- metadata.gz: 38bb75286a35565c01ae20b6785d962a7ba5f4b9d2792807d490a89950838b2f1db2c1ba67bc3f3b9f3beeadaeea32cc0ddcbe1d4341ac6e674ce8c3b20cbe40
7
- data.tar.gz: 8d4f48c2627791d0ca196f4084adea4c9ab94306d7efa1373996e113c62ea76b36946121755b08c0beb4d4669008d4ad425a02016f7e388efa0ccf187b435f15
6
+ metadata.gz: df01b55b3c3e82c15e846e5f7f35fd0cfad67cbdbc67570ae7ebd737ff58d2c4cd19829ce599a08fb142ba771337f914b9079b688eef55dc8ae8e1079675fb1e
7
+ data.tar.gz: 54e18726fabf8b724ce627bd2538d4a8c6948d0da8fac305405e32eec19bd32229461455a11cb11a3895c21d1aab8d1602f58199775e45c7ef33cdbc92f45258
@@ -1,6 +1,33 @@
1
+ # 4.2.5 / 2016-05-06
2
+
3
+ * Updated Highcharts to 4.2.5 (2016-05-06)
4
+ * Added new option, exporting.printMaxWidth, to prevent printed charts cut off on the right side. Closes #2088.
5
+ * Added new option, title.widthAdjust and subtitle.widthAdjust, to prevent titles from flowing over elements.
6
+ * Added support for JPEG in offline download module, ref #5157
7
+ * Fixed #3070, verticalAlign didn't work with rotated data labels on column series.
8
+ * Fixed #4087, error 11 was not described on the website.
9
+ * Fixed #4670, zones colors were not applied for markers on hover.
10
+ * Fixed #5211, titleSetter in combination with buildText added duplicate content to the title.
11
+ * Fixed #5220, a regression causing JS error when resizing polar charts.
12
+ * Fixed #5221, support for minPointLength in xrange study.
13
+ * Fixed #5226, polar chart with no data failed with error.
14
+ * Fixed #5228, scroller.getUnionExtremes did not consider navigation axis min and max.
15
+ * Fixed #5230, a horizontal and opposite axis used to have wrong alignment for its title.
16
+ * Fixed #5234, x value of null cancelled rendering of all points.
17
+ * Fixed #5236, last point was not always visible due to rounding errors.
18
+ * Fixed #5237, inverted should not have an effect on polar charts.
19
+ * Fixed #5250, columns were not visible in IE10.
20
+ * Fixed #5254, data labels were not aligned to the point box in heatmaps.
21
+ * Fixed #5259, crosshair prevented point hover when drawn above points.
22
+ * Fixed #5261, break at the end of a label caused wrong bounding box.
23
+ * Fixed #5266, pinchDown was sometimes empty on Android.
24
+ * Fixed #5269, crosshairs on wrong point with multiple series and non-shared tooltip.
25
+ * Fixed #5274, dataLabels.overflow not always respected on heatmaps.
26
+ * Fixed issue in the xrange study with axis extremes when there were other, more extended series in the same chart.
27
+
1
28
  # 4.2.4 / 2016-05-06
2
29
 
3
- * Updated Highcharts to 4.2.4
30
+ * Updated Highcharts to 4.2.4 (2016-04-14)
4
31
  * Added support for polar columnrange series.
5
32
  * Added e.originalEvent to drilldown event in order to catch modifier keys and other properties. Closes #5113.
6
33
  * Added new drilldown event, chart.events.drillupall, that is triggered after multiple single drillup events. Closes #5158. Closes #5159.
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v4.2.4 (2016-04-14)
5
+ * @license Highcharts JS v4.2.5 (2016-05-06)
6
6
  *
7
7
  * (c) 2009-2016 Torstein Honsi
8
8
  *
@@ -59,7 +59,7 @@
59
59
  charts = [],
60
60
  chartCount = 0,
61
61
  PRODUCT = 'Highcharts',
62
- VERSION = '4.2.4',
62
+ VERSION = '4.2.5',
63
63
 
64
64
  // some constants for frequently used strings
65
65
  DIV = 'div',
@@ -482,9 +482,9 @@
482
482
  * Check for number
483
483
  * @param {Object} n
484
484
  */
485
- function isNumber(n) {
486
- return typeof n === 'number';
487
- }
485
+ var isNumber = Highcharts.isNumber = function isNumber(n) {
486
+ return typeof n === 'number' && !isNaN(n);
487
+ };
488
488
 
489
489
  /**
490
490
  * Remove last occurence of an item from an array
@@ -676,7 +676,7 @@
676
676
  * @param {Boolean} capitalize
677
677
  */
678
678
  dateFormat = function (format, timestamp, capitalize) {
679
- if (!defined(timestamp) || isNaN(timestamp)) {
679
+ if (!isNumber(timestamp)) {
680
680
  return defaultOptions.lang.invalidDate || '';
681
681
  }
682
682
  format = pick(format, '%Y-%m-%d %H:%M:%S');
@@ -1019,6 +1019,7 @@
1019
1019
  Highcharts.numberFormat = function (number, decimals, decimalPoint, thousandsSep) {
1020
1020
 
1021
1021
  number = +number || 0;
1022
+ decimals = +decimals;
1022
1023
 
1023
1024
  var lang = defaultOptions.lang,
1024
1025
  origDec = (number.toString().split('.')[1] || '').length,
@@ -1030,7 +1031,7 @@
1030
1031
 
1031
1032
  if (decimals === -1) {
1032
1033
  decimals = Math.min(origDec, 20); // Preserve decimals. Not huge numbers (#3793).
1033
- } else if (isNaN(decimals)) {
1034
+ } else if (!isNumber(decimals)) {
1034
1035
  decimals = 2;
1035
1036
  }
1036
1037
 
@@ -1055,7 +1056,7 @@
1055
1056
  ret += strinteger.substr(thousands).replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep);
1056
1057
 
1057
1058
  // Add the decimal point and the decimal component
1058
- if (+decimals) {
1059
+ if (decimals) {
1059
1060
  // Get the decimal component, and add power to avoid rounding errors with float numbers (#4573)
1060
1061
  decimalComponent = Math.abs(absNumber - strinteger + Math.pow(10, -Math.max(decimals, origDec) - 1));
1061
1062
  ret += decimalPoint + decimalComponent.toFixed(decimals).slice(2);
@@ -1534,7 +1535,7 @@
1534
1535
  useUTC: true,
1535
1536
  //timezoneOffset: 0,
1536
1537
  canvasToolsURL: 'http://code.highcharts.com/modules/canvas-tools.js',
1537
- VMLRadialGradientURL: 'http://code.highcharts.com/4.2.4/gfx/vml-radial-gradient.png'
1538
+ VMLRadialGradientURL: 'http://code.highcharts.com/4.2.5/gfx/vml-radial-gradient.png'
1538
1539
  },
1539
1540
  chart: {
1540
1541
  //animation: true,
@@ -1593,7 +1594,8 @@
1593
1594
  style: {
1594
1595
  color: '#333333',
1595
1596
  fontSize: '18px'
1596
- }
1597
+ },
1598
+ widthAdjust: -44
1597
1599
 
1598
1600
  },
1599
1601
  subtitle: {
@@ -1605,7 +1607,8 @@
1605
1607
  // y: null,
1606
1608
  style: {
1607
1609
  color: '#555555'
1608
- }
1610
+ },
1611
+ widthAdjust: -44
1609
1612
  },
1610
1613
 
1611
1614
  plotOptions: {
@@ -2016,7 +2019,7 @@
2016
2019
  });
2017
2020
 
2018
2021
  // it's NaN if gradient colors on a column chart
2019
- } else if (rgba && !isNaN(rgba[0])) {
2022
+ } else if (rgba && isNumber(rgba[0])) {
2020
2023
  if (format === 'rgb' || (!format && rgba[3] === 1)) {
2021
2024
  ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')';
2022
2025
  } else if (format === 'a') {
@@ -3179,6 +3182,12 @@
3179
3182
  titleNode = doc.createElementNS(SVG_NS, 'title');
3180
3183
  this.element.appendChild(titleNode);
3181
3184
  }
3185
+
3186
+ // Remove text content if it exists
3187
+ if (titleNode.firstChild) {
3188
+ titleNode.removeChild(titleNode.firstChild);
3189
+ }
3190
+
3182
3191
  titleNode.appendChild(
3183
3192
  doc.createTextNode(
3184
3193
  (String(pick(value), '')).replace(/<[^>]*>/g, '') // #3276, #3895
@@ -3474,6 +3483,7 @@
3474
3483
  childNodes = textNode.childNodes,
3475
3484
  styleRegex,
3476
3485
  hrefRegex,
3486
+ wasTooLong,
3477
3487
  parentX = attr(textNode, 'x'),
3478
3488
  textStyles = wrapper.styles,
3479
3489
  width = wrapper.textWidth,
@@ -3529,18 +3539,20 @@
3529
3539
  }
3530
3540
 
3531
3541
 
3532
- // remove empty line at end
3533
- if (lines[lines.length - 1] === '') {
3534
- lines.pop();
3535
- }
3542
+ // Trim empty lines (#5261)
3543
+ lines = grep(lines, function (line) {
3544
+ return line !== '';
3545
+ });
3536
3546
 
3537
3547
 
3538
3548
  // build the lines
3539
3549
  each(lines, function buildTextLines(line, lineNo) {
3540
3550
  var spans,
3541
3551
  spanNo = 0;
3542
-
3543
- line = line.replace(/<span/g, '|||<span').replace(/<\/span>/g, '</span>|||');
3552
+ line = line
3553
+ .replace(/^\s+|\s+$/g, '') // Trim to prevent useless/costly process on the spaces (#5258)
3554
+ .replace(/<span/g, '|||<span')
3555
+ .replace(/<\/span>/g, '</span>|||');
3544
3556
  spans = line.split('|||');
3545
3557
 
3546
3558
  each(spans, function buildTextSpans(span) {
@@ -3605,7 +3617,6 @@
3605
3617
  var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
3606
3618
  hasWhiteSpace = spans.length > 1 || lineNo || (words.length > 1 && textStyles.whiteSpace !== 'nowrap'),
3607
3619
  tooLong,
3608
- wasTooLong,
3609
3620
  actualWidth,
3610
3621
  rest = [],
3611
3622
  dy = getLineHeight(tspan),
@@ -3637,9 +3648,6 @@
3637
3648
  if (wordStr === '' || (!tooLong && cursor < 0.5)) {
3638
3649
  words = []; // All ok, break out
3639
3650
  } else {
3640
- if (tooLong) {
3641
- wasTooLong = true;
3642
- }
3643
3651
  wordStr = span.substring(0, wordStr.length + (tooLong ? -1 : 1) * mathCeil(cursor));
3644
3652
  words = [wordStr + (width > 3 ? '\u2026' : '')];
3645
3653
  tspan.removeChild(tspan.firstChild);
@@ -3675,9 +3683,6 @@
3675
3683
  tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
3676
3684
  }
3677
3685
  }
3678
- if (wasTooLong) {
3679
- wrapper.attr('title', wrapper.textStr);
3680
- }
3681
3686
  wrapper.rotation = rotation;
3682
3687
  }
3683
3688
 
@@ -3686,6 +3691,10 @@
3686
3691
  }
3687
3692
  });
3688
3693
  });
3694
+
3695
+ if (wasTooLong) {
3696
+ wrapper.attr('title', wrapper.textStr);
3697
+ }
3689
3698
  if (tempParent) {
3690
3699
  tempParent.removeChild(textNode); // attach it to the DOM to read offset width
3691
3700
  }
@@ -6576,7 +6585,7 @@
6576
6585
  }
6577
6586
 
6578
6587
  // the label is created on init - now move it into place
6579
- if (label && !isNaN(x)) {
6588
+ if (label && isNumber(x)) {
6580
6589
  label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
6581
6590
 
6582
6591
  // Apply show first and show last. If the tick is both first and last, it is
@@ -6597,7 +6606,7 @@
6597
6606
  }
6598
6607
 
6599
6608
  // Set the new position, and show or hide
6600
- if (show && !isNaN(xy.y)) {
6609
+ if (show && isNumber(xy.y)) {
6601
6610
  xy.opacity = opacity;
6602
6611
  label[tick.isNew ? 'attr' : 'animate'](xy);
6603
6612
  tick.isNew = false;
@@ -7347,8 +7356,20 @@
7347
7356
  if (axis.isXAxis) {
7348
7357
  xData = series.xData;
7349
7358
  if (xData.length) {
7350
- axis.dataMin = mathMin(pick(axis.dataMin, xData[0]), arrayMin(xData));
7359
+ // If xData contains values which is not numbers, then filter them out.
7360
+ // To prevent performance hit, we only do this after we have already
7361
+ // found seriesDataMin because in most cases all data is valid. #5234.
7362
+ seriesDataMin = arrayMin(xData);
7363
+ if (!isNumber(seriesDataMin) && !(seriesDataMin instanceof Date)) { // Date for #5010
7364
+ xData = grep(xData, function (x) {
7365
+ return isNumber(x);
7366
+ });
7367
+ seriesDataMin = arrayMin(xData); // Do it again with valid data
7368
+ }
7369
+
7370
+ axis.dataMin = mathMin(pick(axis.dataMin, xData[0]), seriesDataMin);
7351
7371
  axis.dataMax = mathMax(pick(axis.dataMax, xData[0]), arrayMax(xData));
7372
+
7352
7373
  }
7353
7374
 
7354
7375
  // Get dataMin and dataMax for Y axes, as well as handle stacking and processed data
@@ -7494,8 +7515,7 @@
7494
7515
  translatedValue = pick(translatedValue, axis.translate(value, null, null, old));
7495
7516
  x1 = x2 = mathRound(translatedValue + transB);
7496
7517
  y1 = y2 = mathRound(cHeight - translatedValue - transB);
7497
-
7498
- if (isNaN(translatedValue)) { // no min or max
7518
+ if (!isNumber(translatedValue)) { // no min or max
7499
7519
  skip = true;
7500
7520
 
7501
7521
  } else if (axis.horiz) {
@@ -7862,6 +7882,9 @@
7862
7882
  axis.range = null; // don't use it when running setExtremes
7863
7883
  }
7864
7884
 
7885
+ // Hook for Highstock Scroller. Consider combining with beforePadding.
7886
+ fireEvent(axis, 'foundExtremes');
7887
+
7865
7888
  // Hook for adjusting this.min and this.max. Used by bubble series.
7866
7889
  if (axis.beforePadding) {
7867
7890
  axis.beforePadding();
@@ -8674,6 +8697,7 @@
8674
8697
  clip,
8675
8698
  directionFactor = [-1, 1, 1, -1][side],
8676
8699
  n,
8700
+ textAlign,
8677
8701
  axisParent = axis.axisParent, // Used in color axis
8678
8702
  lineHeightCorrection,
8679
8703
  tickSize = this.tickSize('tick');
@@ -8741,6 +8765,18 @@
8741
8765
 
8742
8766
  if (axisTitleOptions && axisTitleOptions.text && axisTitleOptions.enabled !== false) {
8743
8767
  if (!axis.axisTitle) {
8768
+ textAlign = axisTitleOptions.textAlign;
8769
+ if (!textAlign) {
8770
+ textAlign = (horiz ? {
8771
+ low: 'left',
8772
+ middle: 'center',
8773
+ high: 'right'
8774
+ } : {
8775
+ low: opposite ? 'right' : 'left',
8776
+ middle: 'center',
8777
+ high: opposite ? 'left' : 'right'
8778
+ })[axisTitleOptions.align];
8779
+ }
8744
8780
  axis.axisTitle = renderer.text(
8745
8781
  axisTitleOptions.text,
8746
8782
  0,
@@ -8750,12 +8786,7 @@
8750
8786
  .attr({
8751
8787
  zIndex: 7,
8752
8788
  rotation: axisTitleOptions.rotation || 0,
8753
- align:
8754
- axisTitleOptions.textAlign || {
8755
- low: opposite ? 'right' : 'left',
8756
- middle: 'center',
8757
- high: opposite ? 'left' : 'right'
8758
- }[axisTitleOptions.align]
8789
+ align: textAlign
8759
8790
  })
8760
8791
  .addClass(PREFIX + this.coll.toLowerCase() + '-title')
8761
8792
  .css(axisTitleOptions.style)
@@ -8902,7 +8933,7 @@
8902
8933
  lineWidth = options.lineWidth,
8903
8934
  linePath,
8904
8935
  hasRendered = chart.hasRendered,
8905
- slideInTicks = hasRendered && defined(axis.oldMin) && !isNaN(axis.oldMin),
8936
+ slideInTicks = hasRendered && isNumber(axis.oldMin),
8906
8937
  showAxis = axis.showAxis,
8907
8938
  animation = animObject(renderer.globalAnimation),
8908
8939
  from,
@@ -9198,6 +9229,7 @@
9198
9229
  });
9199
9230
  } else {
9200
9231
  attribs = {
9232
+ 'pointer-events': 'none', // #5259
9201
9233
  'stroke-width': strokeWidth,
9202
9234
  stroke: options.color || (categorized ? 'rgba(155,200,255,0.2)' : '#C0C0C0'),
9203
9235
  zIndex: pick(options.zIndex, 2)
@@ -10233,7 +10265,7 @@
10233
10265
  if (p) {
10234
10266
  // Store both closest points, using point.dist and point.distX comparisons (#4645):
10235
10267
  each(['dist', 'distX'], function (dist, k) {
10236
- if (typeof p[dist] === 'number') {
10268
+ if (isNumber(p[dist])) {
10237
10269
  var
10238
10270
  // It is closer than the reference point
10239
10271
  isCloser = p[dist] < distance[k],
@@ -10304,7 +10336,7 @@
10304
10336
 
10305
10337
  // Crosshair. For each hover point, loop over axes and draw cross if that point
10306
10338
  // belongs to the axis (#4927).
10307
- each(shared ? kdpoints : [pick(kdpoint[1], hoverPoint)], function (point) {
10339
+ each(shared ? kdpoints : [pick(hoverPoint, kdpoint[1])], function (point) { // #5269
10308
10340
  each(chart.axes, function (axis) {
10309
10341
  // In case of snap = false, point is undefined, and we draw the crosshair anyway (#5066)
10310
10342
  if (!point || point.series[axis.coll] === axis) {
@@ -10995,10 +11027,10 @@
10995
11027
  // moved, and cancelling on small distances. #3450.
10996
11028
  if (e.type === 'touchmove') {
10997
11029
  pinchDown = this.pinchDown;
10998
- hasMoved = Math.sqrt(
11030
+ hasMoved = pinchDown[0] ? Math.sqrt( // #5266
10999
11031
  Math.pow(pinchDown[0].chartX - e.chartX, 2) +
11000
11032
  Math.pow(pinchDown[0].chartY - e.chartY, 2)
11001
- ) >= 4;
11033
+ ) >= 4 : false;
11002
11034
  }
11003
11035
 
11004
11036
  if (pick(hasMoved, true)) {
@@ -12169,6 +12201,9 @@
12169
12201
  redrawLegend = true;
12170
12202
  }
12171
12203
  }
12204
+ if (serie.isDirtyData) {
12205
+ fireEvent(serie, 'updatedData');
12206
+ }
12172
12207
  });
12173
12208
 
12174
12209
  // handle added or removed series
@@ -12395,6 +12430,7 @@
12395
12430
  })
12396
12431
  .css(chartTitleOptions.style)
12397
12432
  .add();
12433
+
12398
12434
  }
12399
12435
  });
12400
12436
  chart.layOutTitles(redraw);
@@ -12412,14 +12448,14 @@
12412
12448
  subtitleOptions = options.subtitle,
12413
12449
  requiresDirtyBox,
12414
12450
  renderer = this.renderer,
12415
- autoWidth = this.spacingBox.width - 44; // 44 makes room for default context button
12451
+ spacingBox = this.spacingBox;
12416
12452
 
12417
12453
  if (title) {
12418
12454
  title
12419
- .css({ width: (titleOptions.width || autoWidth) + PX })
12455
+ .css({ width: (titleOptions.width || spacingBox.width + titleOptions.widthAdjust) + PX })
12420
12456
  .align(extend({
12421
12457
  y: renderer.fontMetrics(titleOptions.style.fontSize, title).b - 3
12422
- }, titleOptions), false, 'spacingBox');
12458
+ }, titleOptions), false, spacingBox);
12423
12459
 
12424
12460
  if (!titleOptions.floating && !titleOptions.verticalAlign) {
12425
12461
  titleOffset = title.getBBox().height;
@@ -12427,10 +12463,10 @@
12427
12463
  }
12428
12464
  if (subtitle) {
12429
12465
  subtitle
12430
- .css({ width: (subtitleOptions.width || autoWidth) + PX })
12466
+ .css({ width: (subtitleOptions.width || spacingBox.width + subtitleOptions.widthAdjust) + PX })
12431
12467
  .align(extend({
12432
12468
  y: titleOffset + (titleOptions.margin - 13) + renderer.fontMetrics(subtitleOptions.style.fontSize, title).b
12433
- }, subtitleOptions), false, 'spacingBox');
12469
+ }, subtitleOptions), false, spacingBox);
12434
12470
 
12435
12471
  if (!subtitleOptions.floating && !subtitleOptions.verticalAlign) {
12436
12472
  titleOffset = mathCeil(titleOffset + subtitle.getBBox().height);
@@ -12545,7 +12581,7 @@
12545
12581
  // attribute and the SVG contents, but not an interactive chart. So in this case,
12546
12582
  // charts[oldChartIndex] will point to the wrong chart if any (#2609).
12547
12583
  oldChartIndex = pInt(attr(renderTo, indexAttrName));
12548
- if (!isNaN(oldChartIndex) && charts[oldChartIndex] && charts[oldChartIndex].hasRendered) {
12584
+ if (isNumber(oldChartIndex) && charts[oldChartIndex] && charts[oldChartIndex].hasRendered) {
12549
12585
  charts[oldChartIndex].destroy();
12550
12586
  }
12551
12587
 
@@ -13473,7 +13509,7 @@
13473
13509
  if (pointValKey) {
13474
13510
  point.y = point[pointValKey];
13475
13511
  }
13476
- point.isNull = point.y === null;
13512
+ point.isNull = point.x === null || point.y === null;
13477
13513
 
13478
13514
  // If no x is set by now, get auto incremented value. All points must have an
13479
13515
  // x value, however the y value can be null to create a gap in the series
@@ -13497,7 +13533,7 @@
13497
13533
  i = 0,
13498
13534
  j = 0;
13499
13535
 
13500
- if (typeof options === 'number' || options === null) {
13536
+ if (isNumber(options) || options === null) {
13501
13537
  ret[pointArrayMap[0]] = options;
13502
13538
 
13503
13539
  } else if (isArray(options)) {
@@ -13827,7 +13863,7 @@
13827
13863
  updateParallelArrays: function (point, i) {
13828
13864
  var series = point.series,
13829
13865
  args = arguments,
13830
- fn = typeof i === 'number' ?
13866
+ fn = isNumber(i) ?
13831
13867
  // Insert the value in the given position
13832
13868
  function (key) {
13833
13869
  var val = key === 'y' && series.toYData ? series.toYData(point) : point[key];
@@ -14325,7 +14361,7 @@
14325
14361
  i,
14326
14362
  j;
14327
14363
 
14328
- yData = yData || this.stackedYData || this.processedYData;
14364
+ yData = yData || this.stackedYData || this.processedYData || [];
14329
14365
  yDataLength = yData.length;
14330
14366
 
14331
14367
  for (i = 0; i < yDataLength; i++) {
@@ -14403,8 +14439,9 @@
14403
14439
  }
14404
14440
 
14405
14441
  // Get the plotX translation
14406
- point.plotX = plotX = mathMin(mathMax(-1e5, xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')), 1e5); // #3923
14407
-
14442
+ point.plotX = plotX = correctFloat( // #5236
14443
+ mathMin(mathMax(-1e5, xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')), 1e5) // #3923
14444
+ );
14408
14445
 
14409
14446
  // Calculate the bottom y value for stacked series
14410
14447
  if (stacking && series.visible && !point.isNull && stack && stack[xValue]) {
@@ -14632,7 +14669,7 @@
14632
14669
  isInside = point.isInside;
14633
14670
 
14634
14671
  // only draw the point if y is defined
14635
- if (enabled && plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {
14672
+ if (enabled && isNumber(plotY) && point.y !== null) {
14636
14673
 
14637
14674
  // shortcuts
14638
14675
  pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE] || seriesPointAttr;
@@ -14730,6 +14767,7 @@
14730
14767
  turboThreshold = seriesOptions.turboThreshold,
14731
14768
  zones = series.zones,
14732
14769
  zoneAxis = series.zoneAxis || 'y',
14770
+ zoneColor,
14733
14771
  attr,
14734
14772
  key;
14735
14773
 
@@ -14778,6 +14816,7 @@
14778
14816
  normalOptions.radius = 0;
14779
14817
  }
14780
14818
 
14819
+ zoneColor = null;
14781
14820
  if (zones.length) {
14782
14821
  j = 0;
14783
14822
  threshold = zones[j];
@@ -14785,7 +14824,7 @@
14785
14824
  threshold = zones[++j];
14786
14825
  }
14787
14826
 
14788
- point.color = point.fillColor = pick(threshold.color, series.color); // #3636, #4267, #4430 - inherit color from series, when color is undefined
14827
+ point.color = point.fillColor = zoneColor = pick(threshold.color, series.color); // #3636, #4267, #4430 - inherit color from series, when color is undefined
14789
14828
 
14790
14829
  }
14791
14830
 
@@ -14829,6 +14868,12 @@
14829
14868
  if (normalOptions.hasOwnProperty('color') && !normalOptions.color) {
14830
14869
  delete normalOptions.color;
14831
14870
  }
14871
+
14872
+ // When zone is set, but series.states.hover.color is not set, apply zone color on hover, #4670:
14873
+ if (zoneColor && !stateOptionsHover.fillColor) {
14874
+ pointStateOptionsHover.fillColor = zoneColor;
14875
+ }
14876
+
14832
14877
  pointAttr[NORMAL_STATE] = series.convertAttribs(extend(attr, normalOptions), seriesPointAttr[NORMAL_STATE]);
14833
14878
 
14834
14879
  // inherit from point normal and series hover
@@ -15386,8 +15431,7 @@
15386
15431
  redraw: function () {
15387
15432
  var series = this,
15388
15433
  chart = series.chart,
15389
- wasDirtyData = series.isDirtyData, // cache it here as it is set to false in render, but used after
15390
- wasDirty = series.isDirty,
15434
+ wasDirty = series.isDirty || series.isDirtyData, // cache it here as it is set to false in render, but used after
15391
15435
  group = series.group,
15392
15436
  xAxis = series.xAxis,
15393
15437
  yAxis = series.yAxis;
@@ -15409,11 +15453,8 @@
15409
15453
 
15410
15454
  series.translate();
15411
15455
  series.render();
15412
- if (wasDirtyData) {
15413
- fireEvent(series, 'updatedData');
15414
- }
15415
- if (wasDirty || wasDirtyData) { // #3945 recalculate the kdtree when dirty
15416
- delete this.kdTree; // #3868 recalculate the kdtree with dirty data
15456
+ if (wasDirty) { // #3868, #3945
15457
+ delete this.kdTree;
15417
15458
  }
15418
15459
  },
15419
15460
 
@@ -17207,7 +17248,7 @@
17207
17248
  graphic = point.graphic,
17208
17249
  borderAttr;
17209
17250
 
17210
- if (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {
17251
+ if (isNumber(plotY) && point.y !== null) {
17211
17252
  shapeArgs = point.shapeArgs;
17212
17253
 
17213
17254
  borderAttr = defined(series.borderWidth) ? {
@@ -17264,7 +17305,7 @@
17264
17305
  // Do the scale synchronously to ensure smooth updating (#5030)
17265
17306
  step: function (val, fx) {
17266
17307
  series.group.attr({
17267
- scaleY: fx.pos
17308
+ scaleY: mathMax(0.001, fx.pos) // #5250
17268
17309
  });
17269
17310
  }
17270
17311
  }));
@@ -18015,11 +18056,11 @@
18015
18056
  rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723
18016
18057
  alignAttr = {
18017
18058
  x: alignTo.x + options.x + alignTo.width / 2 + rotCorr.x,
18018
- y: alignTo.y + options.y + alignTo.height / 2
18059
+ y: alignTo.y + options.y + { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] * alignTo.height
18019
18060
  };
18020
18061
  dataLabel[isNew ? 'attr' : 'animate'](alignAttr)
18021
18062
  .attr({ // #3003
18022
- align: options.align
18063
+ align: align
18023
18064
  });
18024
18065
 
18025
18066
  // Compensate for the rotated label sticking out on the sides
@@ -18246,7 +18287,7 @@
18246
18287
  var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0),
18247
18288
  slotY = pos + chart.plotTop;
18248
18289
 
18249
- if (!isNaN(slotX)) {
18290
+ if (isNumber(slotX)) {
18250
18291
  series.slotElements.push(chart.renderer.rect(slotX, slotY - 7, 100, labelHeight, 1)
18251
18292
  .attr({
18252
18293
  'stroke-width': 1,
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v4.2.4 (2016-04-14)
5
+ * @license Highcharts JS v4.2.5 (2016-05-06)
6
6
  *
7
7
  * 3D features for Highcharts JS
8
8
  *
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v4.2.4 (2016-04-14)
5
+ * @license Highcharts JS v4.2.5 (2016-05-06)
6
6
  *
7
7
  * (c) 2009-2016 Torstein Honsi
8
8
  *
@@ -20,6 +20,7 @@ var arrayMin = Highcharts.arrayMin,
20
20
  arrayMax = Highcharts.arrayMax,
21
21
  each = Highcharts.each,
22
22
  extend = Highcharts.extend,
23
+ isNumber = Highcharts.isNumber,
23
24
  merge = Highcharts.merge,
24
25
  map = Highcharts.map,
25
26
  pick = Highcharts.pick,
@@ -525,6 +526,12 @@ var arrayMin = Highcharts.arrayMin,
525
526
 
526
527
  }
527
528
 
529
+ // Disable certain features on angular and polar axes
530
+ if (angular || polar) {
531
+ chart.inverted = false;
532
+ chartOptions.chart.zoomType = null;
533
+ }
534
+
528
535
  // Run prototype.init
529
536
  proceed.call(this, chart, userOptions);
530
537
 
@@ -542,11 +549,6 @@ var arrayMin = Highcharts.arrayMin,
542
549
  );
543
550
  paneOptions = pane.options;
544
551
 
545
-
546
- // Disable certain features on angular and polar axes
547
- chart.inverted = false;
548
- chartOptions.chart.zoomType = null;
549
-
550
552
  // Start and end angle options are
551
553
  // given in degrees relative to top, while internal computations are
552
554
  // in radians relative to right (like SVG).
@@ -1144,7 +1146,7 @@ var arrayMin = Highcharts.arrayMin,
1144
1146
  rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
1145
1147
 
1146
1148
  // Handle the wrap and overshoot options
1147
- if (overshoot && typeof overshoot === 'number') {
1149
+ if (isNumber(overshoot)) {
1148
1150
  overshoot = overshoot / 180 * Math.PI;
1149
1151
  rotation = Math.max(yAxis.startAngleRad - overshoot, Math.min(yAxis.endAngleRad + overshoot, rotation));
1150
1152
 
@@ -2085,7 +2087,7 @@ var arrayMin = Highcharts.arrayMin,
2085
2087
  point = data[i];
2086
2088
  radius = radii ? radii[i] : 0; // #1737
2087
2089
 
2088
- if (typeof radius === 'number' && radius >= this.minPxSize / 2) {
2090
+ if (isNumber(radius) && radius >= this.minPxSize / 2) {
2089
2091
  // Shape arguments
2090
2092
  point.shapeType = 'circle';
2091
2093
  point.shapeArgs = {
@@ -2213,7 +2215,7 @@ var arrayMin = Highcharts.arrayMin,
2213
2215
 
2214
2216
  if (range > 0) {
2215
2217
  while (i--) {
2216
- if (typeof data[i] === 'number' && axis.dataMin <= data[i] && data[i] <= axis.dataMax) {
2218
+ if (isNumber(data[i]) && axis.dataMin <= data[i] && data[i] <= axis.dataMax) {
2217
2219
  radius = series.radii[i];
2218
2220
  pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
2219
2221
  pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
@@ -2459,8 +2461,8 @@ var arrayMin = Highcharts.arrayMin,
2459
2461
  // Connect the path
2460
2462
  if (this.chart.polar) {
2461
2463
  points = points || this.points;
2462
-
2463
- if (this.options.connectEnds !== false && points[0].y !== null) {
2464
+
2465
+ if (this.options.connectEnds !== false && points[0] && points[0].y !== null) {
2464
2466
  this.connectEnds = true; // re-used in splines
2465
2467
  points.splice(points.length, 0, points[0]);
2466
2468
  }
@@ -2597,7 +2599,9 @@ var arrayMin = Highcharts.arrayMin,
2597
2599
  point = points[i];
2598
2600
  start = point.barX + startAngleRad;
2599
2601
  point.shapeType = 'path';
2600
- point.shapeArgs = this.polarArc(point.yBottom, point.plotY, start, start + point.pointWidth);
2602
+ point.shapeArgs = {
2603
+ d: this.polarArc(point.yBottom, point.plotY, start, start + point.pointWidth)
2604
+ };
2601
2605
  // Provide correct plotX, plotY for tooltip
2602
2606
  this.toXY(point);
2603
2607
  point.tooltipPos = [point.plotX, point.plotY];
@@ -67,6 +67,7 @@
67
67
  addEvent = H.addEvent,
68
68
  fireEvent = H.fireEvent,
69
69
  grep = H.grep,
70
+ isNumber = H.isNumber,
70
71
  merge = H.merge,
71
72
  pick = H.pick,
72
73
  wrap = H.wrap,
@@ -169,8 +170,8 @@
169
170
  data = options.data,
170
171
  xAxis = this.xAxis && this.xAxis.options,
171
172
  yAxis = this.yAxis && this.yAxis.options;
172
- return data.length > (options.boostThreshold || Number.MAX_VALUE) && typeof yAxis.min === 'number' && typeof yAxis.max === 'number' &&
173
- (!checkX || (typeof xAxis.min === 'number' && typeof xAxis.max === 'number'));
173
+ return data.length > (options.boostThreshold || Number.MAX_VALUE) && isNumber(yAxis.min) && isNumber(yAxis.max) &&
174
+ (!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
174
175
  },
175
176
 
176
177
  /**
@@ -275,7 +276,7 @@
275
276
  lastPoint,
276
277
  threshold = options.threshold,
277
278
  yBottom = yAxis.getThreshold(threshold),
278
- hasThreshold = typeof threshold === 'number',
279
+ hasThreshold = isNumber(threshold),
279
280
  translatedThreshold = yBottom,
280
281
  doFill = this.fill,
281
282
  isRange = series.pointArrayMap && series.pointArrayMap.join(',') === 'low,high',
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Highcharts JS v4.2.4 (2016-04-14)
2
+ * Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Highcharts Broken Axis module
4
4
  *
5
5
  * License: www.highcharts.com/license
@@ -2908,7 +2908,7 @@ if (CanvasRenderingContext2D) {
2908
2908
  });
2909
2909
  }
2910
2910
  }/**
2911
- * @license Highcharts JS v4.2.4 (2016-04-14)
2911
+ * @license Highcharts JS v4.2.5 (2016-05-06)
2912
2912
  * CanVGRenderer Extension module
2913
2913
  *
2914
2914
  * (c) 2011-2016 Torstein Honsi, Erik Olsson
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Data module
4
4
  *
5
5
  * (c) 2012-2016 Torstein Honsi
@@ -22,6 +22,7 @@
22
22
  each = Highcharts.each,
23
23
  pick = Highcharts.pick,
24
24
  inArray = Highcharts.inArray,
25
+ isNumber = Highcharts.isNumber,
25
26
  splat = Highcharts.splat,
26
27
  SeriesBuilder;
27
28
 
@@ -424,7 +425,7 @@
424
425
  } else {
425
426
  dateVal = this.parseDate(val);
426
427
  // Only allow parsing of dates if this column is an x-column
427
- if (isXColumn && typeof dateVal === 'number' && !isNaN(dateVal) && columnType !== 'float') { // is date
428
+ if (isXColumn && isNumber(dateVal) && columnType !== 'float') { // is date
428
429
  backup[row] = val;
429
430
  column[row] = dateVal;
430
431
  column.isDatetime = true;
@@ -557,7 +558,7 @@
557
558
  ret = match.getTime() - match.getTimezoneOffset() * 60000;
558
559
 
559
560
  // Timestamp
560
- } else if (typeof match === 'number' && !isNaN(match)) {
561
+ } else if (isNumber(match)) {
561
562
  ret = match - (new Date(match)).getTimezoneOffset() * 60000;
562
563
  }
563
564
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Exporting module
4
4
  *
5
5
  * (c) 2010-2016 Torstein Honsi
@@ -104,6 +104,7 @@ defaultOptions.exporting = {
104
104
  type: 'image/png',
105
105
  url: 'http://export.highcharts.com/',
106
106
  //width: undefined,
107
+ printMaxWidth: 780,
107
108
  //scale: 2
108
109
  buttons: {
109
110
  contextButton: {
@@ -424,7 +425,11 @@ extend(Chart.prototype, {
424
425
  origDisplay = [],
425
426
  origParent = container.parentNode,
426
427
  body = doc.body,
427
- childNodes = body.childNodes;
428
+ childNodes = body.childNodes,
429
+ printMaxWidth = chart.options.exporting.printMaxWidth,
430
+ hasUserSize,
431
+ resetParams,
432
+ handleMaxWidth;
428
433
 
429
434
  if (chart.isPrinting) { // block the button while in printing mode
430
435
  return;
@@ -435,6 +440,14 @@ extend(Chart.prototype, {
435
440
 
436
441
  fireEvent(chart, 'beforePrint');
437
442
 
443
+ // Handle printMaxWidth
444
+ handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth;
445
+ if (handleMaxWidth) {
446
+ hasUserSize = chart.hasUserSize;
447
+ resetParams = [chart.chartWidth, chart.chartHeight, false];
448
+ chart.setSize(printMaxWidth, chart.chartHeight, false);
449
+ }
450
+
438
451
  // hide all body content
439
452
  each(childNodes, function (node, i) {
440
453
  if (node.nodeType === 1) {
@@ -465,6 +478,12 @@ extend(Chart.prototype, {
465
478
 
466
479
  chart.isPrinting = false;
467
480
 
481
+ // Reset printMaxWidth
482
+ if (handleMaxWidth) {
483
+ chart.setSize.apply(chart, resetParams);
484
+ chart.hasUserSize = hasUserSize;
485
+ }
486
+
468
487
  fireEvent(chart, 'afterPrint');
469
488
 
470
489
  }, 1000);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  *
4
4
  * (c) 2011-2016 Torstein Honsi
5
5
  *
@@ -28,6 +28,7 @@
28
28
  each = Highcharts.each,
29
29
  extend = Highcharts.extend,
30
30
  extendClass = Highcharts.extendClass,
31
+ isNumber = Highcharts.isNumber,
31
32
  merge = Highcharts.merge,
32
33
  pick = Highcharts.pick,
33
34
  seriesTypes = Highcharts.seriesTypes,
@@ -383,7 +384,7 @@
383
384
  }
384
385
  },
385
386
  getPlotLinePath: function (a, b, c, d, pos) {
386
- return typeof pos === 'number' ? // crosshairs only // #3969 pos can be 0 !!
387
+ return isNumber(pos) ? // crosshairs only // #3969 pos can be 0 !!
387
388
  (this.horiz ?
388
389
  ['M', pos - 4, this.top - 6, 'L', pos + 4, this.top - 6, pos, this.top, 'Z'] :
389
390
  ['M', this.left, pos, 'L', this.left - 6, pos + 6, this.left - 6, pos - 6, 'Z']
@@ -663,10 +664,10 @@
663
664
  each(series.points, function (point) {
664
665
  var xPad = (options.colsize || 1) / 2,
665
666
  yPad = (options.rowsize || 1) / 2,
666
- x1 = between(Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)), 0, xAxis.len),
667
- x2 = between(Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)), 0, xAxis.len),
668
- y1 = between(Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)), 0, yAxis.len),
669
- y2 = between(Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1)), 0, yAxis.len);
667
+ x1 = between(Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len),
668
+ x2 = between(Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len),
669
+ y1 = between(Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len),
670
+ y2 = between(Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len);
670
671
 
671
672
  // Set plotX and plotY for use in K-D-Tree and more
672
673
  point.plotX = point.clientX = (x1 + x2) / 2;
@@ -694,7 +695,7 @@
694
695
  animate: noop,
695
696
  getBox: noop,
696
697
  drawLegendSymbol: LegendSymbolMixin.drawRectangle,
697
-
698
+ alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
698
699
  getExtremes: function () {
699
700
  // Get the extremes from the value data
700
701
  Series.prototype.getExtremes.call(this, this.valueData);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Plugin for displaying a message when there is no data visible in chart.
4
4
  *
5
5
  * (c) 2010-2016 Highsoft AS
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Client side exporting module
4
4
  *
5
5
  * (c) 2015 Torstein Honsi / Oystein Moseng
@@ -68,8 +68,8 @@
68
68
  },
69
69
  // Get data:URL from image URL
70
70
  // Pass in callbacks to handle results. finallyCallback is always called at the end of the process. Supplying this callback is optional.
71
- // All callbacks receive two arguments: imageURL, and callbackArgs. callbackArgs is used only by callbacks and can contain whatever.
72
- imageToDataUrl = function (imageURL, callbackArgs, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) {
71
+ // All callbacks receive three arguments: imageURL, imageType, and callbackArgs. callbackArgs is used only by callbacks and can contain whatever.
72
+ imageToDataUrl = function (imageURL, imageType, callbackArgs, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) {
73
73
  var img = new win.Image(),
74
74
  taintedHandler,
75
75
  loadHandler = function () {
@@ -78,7 +78,7 @@
78
78
  dataURL;
79
79
  try {
80
80
  if (!ctx) {
81
- noCanvasSupportCallback(imageURL, callbackArgs);
81
+ noCanvasSupportCallback(imageURL, imageType, callbackArgs);
82
82
  } else {
83
83
  canvas.height = img.height * scale;
84
84
  canvas.width = img.width * scale;
@@ -86,12 +86,12 @@
86
86
 
87
87
  // Now we try to get the contents of the canvas.
88
88
  try {
89
- dataURL = canvas.toDataURL();
90
- successCallback(dataURL, callbackArgs);
89
+ dataURL = canvas.toDataURL(imageType);
90
+ successCallback(dataURL, imageType, callbackArgs);
91
91
  } catch (e) {
92
92
  // Failed - either tainted canvas or something else went horribly wrong
93
93
  if (e.name === 'SecurityError' || e.name === 'SECURITY_ERR' || e.message === 'SecurityError') {
94
- taintedHandler(imageURL, callbackArgs);
94
+ taintedHandler(imageURL, imageType, callbackArgs);
95
95
  } else {
96
96
  throw e;
97
97
  }
@@ -99,15 +99,15 @@
99
99
  }
100
100
  } finally {
101
101
  if (finallyCallback) {
102
- finallyCallback(imageURL, callbackArgs);
102
+ finallyCallback(imageURL, imageType, callbackArgs);
103
103
  }
104
104
  }
105
105
  },
106
106
  // Image load failed (e.g. invalid URL)
107
107
  errorHandler = function () {
108
- failedLoadCallback(imageURL, callbackArgs);
108
+ failedLoadCallback(imageURL, imageType, callbackArgs);
109
109
  if (finallyCallback) {
110
- finallyCallback(imageURL, callbackArgs);
110
+ finallyCallback(imageURL, imageType, callbackArgs);
111
111
  }
112
112
  };
113
113
 
@@ -176,10 +176,12 @@
176
176
  initiateDownload = function () {
177
177
  var svgurl,
178
178
  blob,
179
+ imageType = options && options.type || 'image/png',
180
+ imageExtension = imageType.split('/')[1],
179
181
  svg = chart.sanitizeSVG(chartCopyContainer.innerHTML); // SVG of chart copy
180
182
 
181
183
  // Initiate download depending on file type
182
- if (options && options.type === 'image/svg+xml') {
184
+ if (imageType === 'image/svg+xml') {
183
185
  // SVG download. In this case, we want to use Microsoft specific Blob if available
184
186
  try {
185
187
  if (nav.msSaveOrOpenBlob) {
@@ -194,14 +196,14 @@
194
196
  fallbackToExportServer();
195
197
  }
196
198
  } else {
197
- // PNG download - create bitmap from SVG
199
+ // PNG/JPEG download - create bitmap from SVG
198
200
 
199
201
  // First, try to get PNG by rendering on canvas
200
202
  svgurl = svgToDataUrl(svg);
201
- imageToDataUrl(svgurl, { /* args */ }, function (imageURL) {
203
+ imageToDataUrl(svgurl, imageType, { /* args */ }, function (imageURL) {
202
204
  // Success
203
205
  try {
204
- download(imageURL, 'png');
206
+ download(imageURL, imageExtension);
205
207
  } catch (e) {
206
208
  fallbackToExportServer();
207
209
  }
@@ -215,7 +217,7 @@
215
217
  downloadWithCanVG = function () {
216
218
  ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight);
217
219
  try {
218
- download(nav.msSaveOrOpenBlob ? canvas.msToBlob() : canvas.toDataURL('image/png'), 'png');
220
+ download(nav.msSaveOrOpenBlob ? canvas.msToBlob() : canvas.toDataURL(imageType), imageExtension);
219
221
  } catch (e) {
220
222
  fallbackToExportServer();
221
223
  }
@@ -250,7 +252,7 @@
250
252
  }
251
253
  },
252
254
  // Success handler, we converted image to base64!
253
- embeddedSuccess = function (imageURL, callbackArgs) {
255
+ embeddedSuccess = function (imageURL, imageType, callbackArgs) {
254
256
  ++imagesEmbedded;
255
257
 
256
258
  // Change image href in chart copy
@@ -281,7 +283,7 @@
281
283
  // Go through the images we want to embed
282
284
  for (i = 0, l = images.length; i < l; ++i) {
283
285
  el = images[i];
284
- imageToDataUrl(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), { imageElement: el },
286
+ imageToDataUrl(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), 'image/png', { imageElement: el },
285
287
  embeddedSuccess,
286
288
  // Tainted canvas
287
289
  fallbackToExportServer,
@@ -309,6 +311,13 @@
309
311
  onclick: function () {
310
312
  this.exportChartLocal();
311
313
  }
314
+ }, {
315
+ textKey: 'downloadJPEG',
316
+ onclick: function () {
317
+ this.exportChartLocal({
318
+ type: 'image/jpeg'
319
+ });
320
+ }
312
321
  }, {
313
322
  textKey: 'downloadSVG',
314
323
  onclick: function () {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  * Solid angular gauge module
4
4
  *
5
5
  * (c) 2010-2016 Torstein Honsi
@@ -20,6 +20,7 @@
20
20
  pInt = H.pInt,
21
21
  pick = H.pick,
22
22
  each = H.each,
23
+ isNumber = H.isNumber,
23
24
  colorAxisMethods,
24
25
  UNDEFINED;
25
26
 
@@ -191,7 +192,7 @@
191
192
  options = series.options,
192
193
  renderer = series.chart.renderer,
193
194
  overshoot = options.overshoot,
194
- overshootVal = overshoot && typeof overshoot === 'number' ? overshoot / 180 * Math.PI : 0;
195
+ overshootVal = isNumber(overshoot) ? overshoot / 180 * Math.PI : 0;
195
196
 
196
197
  H.each(series.points, function (point) {
197
198
  var graphic = point.graphic,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v4.2.4 (2016-04-14)
2
+ * @license Highcharts JS v4.2.5 (2016-05-06)
3
3
  *
4
4
  * (c) 2014 Highsoft AS
5
5
  * Authors: Jon Arild Nygard / Oystein Moseng
@@ -5,7 +5,7 @@
5
5
 
6
6
  // Load the fonts
7
7
  Highcharts.createElement('link', {
8
- href: '//fonts.googleapis.com/css?family=Unica+One',
8
+ href: 'https://fonts.googleapis.com/css?family=Unica+One',
9
9
  rel: 'stylesheet',
10
10
  type: 'text/css'
11
11
  }, null, document.getElementsByTagName('head')[0]);
@@ -5,7 +5,7 @@
5
5
 
6
6
  // Load the fonts
7
7
  Highcharts.createElement('link', {
8
- href: '//fonts.googleapis.com/css?family=Dosis:400,600',
8
+ href: 'https://fonts.googleapis.com/css?family=Dosis:400,600',
9
9
  rel: 'stylesheet',
10
10
  type: 'text/css'
11
11
  }, null, document.getElementsByTagName('head')[0]);
@@ -5,7 +5,7 @@
5
5
 
6
6
  // Load the fonts
7
7
  Highcharts.createElement('link', {
8
- href: '//fonts.googleapis.com/css?family=Signika:400,700',
8
+ href: 'https://fonts.googleapis.com/css?family=Signika:400,700',
9
9
  rel: 'stylesheet',
10
10
  type: 'text/css'
11
11
  }, null, document.getElementsByTagName('head')[0]);
@@ -1,3 +1,3 @@
1
1
  module Highcharts
2
- VERSION = "4.2.4"
2
+ VERSION = "4.2.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: highcharts-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.4
4
+ version: 4.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Per Christian B. Viken