highcharts-rails 3.0.1.5 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.asc CHANGED
@@ -2,17 +2,17 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.19 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQIcBAABAgAGBQJRijrwAAoJEH1ncb0Txu7X4B0P/1BCK86rcxzHmFJRrx5B5PYd
6
- mo341OI+YCiAmPCYVzh02uoYZ59vq8EkWSZ4CuN2fVEiNqgv/lbxiJjfnLChkex+
7
- XBdHZ2GgwwFw6LRoqXz/KI2G0I6TBTnLwFjIW9qO7S8GGS4nC0XTYrJ0JneyKrRm
8
- j90IS1XLILnHg5+5uV6D2+Yh47lmCri1e5dudFdnGW/gjgioZEcMFQsMPdB0e8Fn
9
- 1AQDb7NtbDeq5H8F8FwIaXGvOU6YQVYwbyfjWebKJiFjWQdy0sSS/dpZzbnJbUl0
10
- 9SDFFl9LsNFEZmvAFdfDEbv+gm9nceAkk0G0pep0bC+8uhPVGMSz8+gjV219Fk+i
11
- zusTKcD7xF/4tHdMqUDRQaxFdYaB6XbT4SyS8h7AO8FWsjwOhB6YvPheRHYHZS6y
12
- ffr1xYMP13SWR4NoZDTJUuDIIOQ7O68GEcMs+BF3HOs+5DTJNFcidQ8266rw8EQG
13
- OiIhXwcP12y2uJpWZSB7eUG5vRcM2RIaTAUdTTnSVmJDtJwov4XBcKyqOJc9CMr+
14
- tHLyFg0g4dZzvriPXaM5Qs+bSsqiTYtbIw0CFZeQ8c8vF7hCwVDtpc8EepS3mjUg
15
- rDZsPf7Yy6G/GDVklskBnSNvXlWePyRvleRkjs7qxebmd2pYNR/nyzFqOjjLu3ko
16
- C1/ClppvIekC/dr04rk9
17
- =jNQk
5
+ iQIcBAABAgAGBQJRsdkzAAoJEH1ncb0Txu7XH/AP/1a0aFi65fj2/7kP2aW8Wh88
6
+ Eii6rsVmsDbUt480BskzXqFnksDOg2X8FwhX7ze0GwkHfADHbsoddf0WZ/NssLG6
7
+ O3C5AzX/695zPKxfGVd1IX6dmJCWroKqadz/HAJ7vNQRADhLlIpu97VRe79qRydQ
8
+ uV/zJnRcjSlOyGAukMw5KVvyUgpoWYOUPDB84coZJ7Nnw5RSNvJG7DduvLcABljJ
9
+ muMUG70To9Ei3KZOyGG39jBQXePuDrRaqUbgsofoypTQW6qFx91p3FCyH7eoUDTr
10
+ HU2zmBW3NAJXMlwPwtJO0y7OK8oFUXHpxX1rx99BVo3Xh/l+cLbPQuWV1zP2CEh4
11
+ JUry+JNpCIvVZtozhynCyxjQOWALW6hJ1cT2dfoKoz2ED2qOSJ0XG8SQac8bfel0
12
+ Tvico/ZWE+k6WQw/w60xmXQZEtlx6ovwHE4269bAH5zoAxef4F0PYqe/afZP3dDA
13
+ 1XRrJpUbVffvtXeDz9kVY1aKu9gpFHgw1P1qqeCSdfqJSfXbrvzlmkkpfOwUGsVC
14
+ 2DW6aXlVF1mCDCTNMZenlDUa4Vn3Tpdo5TjfFCsMRM3uUOE/Z37w7wyRzybTbPWa
15
+ +8S1Xmlgt77IZY1uuy1/Jts1i45Fn9gGvSqHmoNKqC5pXeWwOtKVkgRFlM1JP07e
16
+ VlXJlAfX7Bu5x5CxAB8r
17
+ =U2ji
18
18
  -----END PGP SIGNATURE-----
@@ -1,4 +1,10 @@
1
- # 3.0.1.5 / unreleased
1
+ # 3.0.2 / 2013-06-07
2
+
3
+ * Updated Highcharts to 3.0.2
4
+ * Removed the Rack endpoint
5
+ (https://github.com/PerfectlyNormal/highcharts-rails/issues/9)
6
+
7
+ # 3.0.1.5 / 2013-05-08
2
8
 
3
9
  * Add a Rack endpoint for exporting charts to image files
4
10
 
@@ -45,54 +45,6 @@ Or one of the themes
45
45
 
46
46
  Other than that, refer to the [Highcharts documentation](http://docs.highcharts.com/#home)
47
47
 
48
- ## Export endpoint
49
-
50
- This gem contains a Rack endpoint for converting the chart to a downloadable file.
51
- It is not required by default, so to use it, `require
52
- 'highcharts/export_endpoint'`
53
-
54
- The endpoint is basically a port of the [PHP version made available](https://github.com/highslide-software/highcharts.com/blob/master/exporting-server/php/php-batik/index.php).
55
- It currently needs a lot of cleanup, but it is working fine for me. Your milage
56
- may vary.
57
-
58
- It uses [Apache Batik](http://xmlgraphics.apache.org/batik/) for the conversion, which must be
59
- installed separately, as well as a Java Runtime Environment.
60
-
61
- It expects to find a JRE in `/usr/bin/java`, and Batik in
62
- `/usr/share/java/batik-rasterizer.jar`, but both paths are configurable.
63
-
64
- Example usage in Rails:
65
-
66
- # config/routes.rb
67
- require 'highcharts/export_endpoint'
68
-
69
- MyRailsApp::Application.routes.draw do
70
- ...
71
- mount Highcharts::ExportEndpoint.new({
72
- java_path: "/usr/bin/java",
73
- batik: "/usr/share/java/batik-rasterizer.jar"
74
- }), at: "highcharts-export"
75
- ...
76
- end
77
-
78
- # When rendering the chart
79
- new Highcharts.Chart({
80
- ...
81
- exporting: {
82
- url: "/highcharts-export",
83
- ...
84
- }
85
- })
86
-
87
- ### Cocaine
88
-
89
- The exporting endpoint uses [Cocaine](https://github.com/thoughtbot/cocaine) for
90
- handling the command lines and arguments and so on.
91
-
92
- I don't know a way to get optional dependencies in the gemspec, so for now
93
- that gets added whether you want it or not. I'd like to get this fixed,
94
- but would also like to avoid `begin; require 'cocaine'; rescue LoadError; ...; end` and similar hacks.
95
-
96
48
  ## Licensing
97
49
 
98
50
  Highcharts, which makes up the majority of this gem, has [its own, separate licensing](http://shop.highsoft.com/highcharts.html).
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v3.0.1 (2013-04-09)
5
+ * @license Highcharts JS v3.0.2 (2013-06-05)
6
6
  *
7
7
  * (c) 2009-2013 Torstein Hønsi
8
8
  *
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  // JSLint options:
13
- /*global Highcharts, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
13
+ /*global Highcharts, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console, each, grep */
14
14
 
15
15
  (function () {
16
16
  // encapsulated variables
@@ -55,7 +55,7 @@ var UNDEFINED,
55
55
  noop = function () {},
56
56
  charts = [],
57
57
  PRODUCT = 'Highcharts',
58
- VERSION = '3.0.1',
58
+ VERSION = '3.0.2',
59
59
 
60
60
  // some constants for frequently used strings
61
61
  DIV = 'div',
@@ -782,14 +782,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
782
782
 
783
783
  // else, the interval is fixed and we use simple addition
784
784
  } else {
785
-
786
- // mark new days if the time is dividable by day
787
- if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset) {
788
- higherRanks[time] = DAY;
789
- }
790
-
791
785
  time += interval * count;
792
-
793
786
  }
794
787
 
795
788
  i++;
@@ -797,8 +790,17 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
797
790
 
798
791
  // push the last time
799
792
  tickPositions.push(time);
793
+
794
+
795
+ // mark new days if the time is dividible by day (#1649, #1760)
796
+ each(grep(tickPositions, function (time) {
797
+ return interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset;
798
+ }), function (time) {
799
+ higherRanks[time] = DAY;
800
+ });
800
801
  }
801
802
 
803
+
802
804
  // record information on the chosen unit - for dynamic label formatter
803
805
  tickPositions.info = extend(normalizedInterval, {
804
806
  higherRanks: higherRanks,
@@ -1094,7 +1096,8 @@ pathAnim = {
1094
1096
  Step = Fx.step,
1095
1097
  dSetter,
1096
1098
  Tween = $.Tween,
1097
- propHooks = Tween && Tween.propHooks;
1099
+ propHooks = Tween && Tween.propHooks,
1100
+ opacityHook = $.cssHooks.opacity;
1098
1101
 
1099
1102
  /*jslint unparam: true*//* allow unused param x in this function */
1100
1103
  $.extend($.easing, {
@@ -1104,7 +1107,6 @@ pathAnim = {
1104
1107
  });
1105
1108
  /*jslint unparam: false*/
1106
1109
 
1107
-
1108
1110
  // extend some methods to check for elem.attr, which means it is a Highcharts SVG object
1109
1111
  $.each(['cur', '_default', 'width', 'height', 'opacity'], function (i, fn) {
1110
1112
  var obj = Step,
@@ -1141,6 +1143,11 @@ pathAnim = {
1141
1143
  };
1142
1144
  }
1143
1145
  });
1146
+
1147
+ // Extend the opacity getter, needed for fading opacity with IE9 and jQuery 1.10+
1148
+ wrap(opacityHook, 'get', function (proceed, elem, computed) {
1149
+ return elem.attr ? (elem.opacity || 0) : proceed.call(this, elem, computed);
1150
+ });
1144
1151
 
1145
1152
 
1146
1153
  // Define the setter function for d (path definitions)
@@ -1396,15 +1403,15 @@ pathAnim = {
1396
1403
  */
1397
1404
  animate: function (el, params, options) {
1398
1405
  var $el = $(el);
1406
+ if (!el.style) {
1407
+ el.style = {}; // #1881
1408
+ }
1399
1409
  if (params.d) {
1400
1410
  el.toD = params.d; // keep the array form for paths, used in $.fx.step.d
1401
1411
  params.d = 1; // because in jQuery, animating to an array has a different meaning
1402
1412
  }
1403
1413
 
1404
1414
  $el.stop();
1405
- if (params.opacity !== UNDEFINED && el.attr) {
1406
- params.opacity += 'px'; // force jQuery to use same logic as width and height
1407
- }
1408
1415
  $el.animate(params, options);
1409
1416
 
1410
1417
  },
@@ -1487,8 +1494,8 @@ defaultOptions = {
1487
1494
  },
1488
1495
  global: {
1489
1496
  useUTC: true,
1490
- canvasToolsURL: 'http://code.highcharts.com/3.0.1/modules/canvas-tools.js',
1491
- VMLRadialGradientURL: 'http://code.highcharts.com/3.0.1/gfx/vml-radial-gradient.png'
1497
+ canvasToolsURL: 'http://code.highcharts.com/3.0.2/modules/canvas-tools.js',
1498
+ VMLRadialGradientURL: 'http://code.highcharts.com/3.0.2/gfx/vml-radial-gradient.png'
1492
1499
  },
1493
1500
  chart: {
1494
1501
  //animation: true,
@@ -1603,7 +1610,7 @@ defaultOptions = {
1603
1610
  dataLabels: merge(defaultLabelOptions, {
1604
1611
  enabled: false,
1605
1612
  formatter: function () {
1606
- return this.y;
1613
+ return numberFormat(this.y, -1);
1607
1614
  },
1608
1615
  verticalAlign: 'bottom', // above singular point
1609
1616
  y: 0
@@ -2291,7 +2298,13 @@ SVGElement.prototype = {
2291
2298
  });
2292
2299
 
2293
2300
  wrapper.attr({
2294
- d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper)
2301
+ d: wrapper.renderer.symbols[wrapper.symbolName](
2302
+ wrapper.x,
2303
+ wrapper.y,
2304
+ wrapper.width,
2305
+ wrapper.height,
2306
+ wrapper
2307
+ )
2295
2308
  });
2296
2309
  },
2297
2310
 
@@ -2383,9 +2396,7 @@ SVGElement.prototype = {
2383
2396
  for (n in styles) {
2384
2397
  serializedCss += n.replace(/([A-Z])/g, hyphenate) + ':' + styles[n] + ';';
2385
2398
  }
2386
- elemWrapper.attr({
2387
- style: serializedCss
2388
- });
2399
+ attr(elem, 'style', serializedCss); // #1881
2389
2400
  }
2390
2401
 
2391
2402
 
@@ -2525,19 +2536,17 @@ SVGElement.prototype = {
2525
2536
  shadows = wrapper.shadows;
2526
2537
 
2527
2538
  // apply translate
2528
- if (translateX || translateY) {
2529
- css(elem, {
2530
- marginLeft: translateX,
2531
- marginTop: translateY
2532
- });
2533
- if (shadows) { // used in labels/tooltip
2534
- each(shadows, function (shadow) {
2535
- css(shadow, {
2536
- marginLeft: translateX + 1,
2537
- marginTop: translateY + 1
2538
- });
2539
+ css(elem, {
2540
+ marginLeft: translateX,
2541
+ marginTop: translateY
2542
+ });
2543
+ if (shadows) { // used in labels/tooltip
2544
+ each(shadows, function (shadow) {
2545
+ css(shadow, {
2546
+ marginLeft: translateX + 1,
2547
+ marginTop: translateY + 1
2539
2548
  });
2540
- }
2549
+ });
2541
2550
  }
2542
2551
 
2543
2552
  // apply inversion
@@ -2655,7 +2664,7 @@ SVGElement.prototype = {
2655
2664
  scaleY = wrapper.scaleY,
2656
2665
  inverted = wrapper.inverted,
2657
2666
  rotation = wrapper.rotation,
2658
- transform = [];
2667
+ transform;
2659
2668
 
2660
2669
  // flipping affects translate as adjustment for flipping around the group's axis
2661
2670
  if (inverted) {
@@ -2663,10 +2672,9 @@ SVGElement.prototype = {
2663
2672
  translateY += wrapper.attr('height');
2664
2673
  }
2665
2674
 
2666
- // apply translate
2667
- if (translateX || translateY) {
2668
- transform.push('translate(' + translateX + ',' + translateY + ')');
2669
- }
2675
+ // Apply translate. Nearly all transformed elements have translation, so instead
2676
+ // of checking for translate = 0, do it always (#1767, #1846).
2677
+ transform = ['translate(' + translateX + ',' + translateY + ')'];
2670
2678
 
2671
2679
  // apply rotation
2672
2680
  if (inverted) {
@@ -4374,7 +4382,7 @@ SVGRenderer.prototype = {
4374
4382
  if (styles) {
4375
4383
  var textStyles = {};
4376
4384
  styles = merge(styles); // create a copy to avoid altering the original object (#537)
4377
- each(['fontSize', 'fontWeight', 'fontFamily', 'color', 'lineHeight', 'width'], function (prop) {
4385
+ each(['fontSize', 'fontWeight', 'fontFamily', 'color', 'lineHeight', 'width', 'textDecoration'], function (prop) {
4378
4386
  if (styles[prop] !== UNDEFINED) {
4379
4387
  textStyles[prop] = styles[prop];
4380
4388
  delete styles[prop];
@@ -5303,12 +5311,14 @@ var VMLRendererExtension = { // inherit SVGRenderer
5303
5311
  * @param {Number} r
5304
5312
  */
5305
5313
  circle: function (x, y, r) {
5314
+ var circle = this.symbol('circle');
5306
5315
  if (isObject(x)) {
5307
5316
  r = x.r;
5308
5317
  y = x.y;
5309
5318
  x = x.x;
5310
5319
  }
5311
- return this.symbol('circle').attr({ x: x - r, y: y - r, width: 2 * r, height: 2 * r });
5320
+ circle.isCircle = true; // Causes x and y to mean center (#1682)
5321
+ return circle.attr({ x: x, y: y, width: 2 * r, height: 2 * r });
5312
5322
  },
5313
5323
 
5314
5324
  /**
@@ -5450,8 +5460,14 @@ var VMLRendererExtension = { // inherit SVGRenderer
5450
5460
 
5451
5461
  },
5452
5462
  // Add circle symbol path. This performs significantly faster than v:oval.
5453
- circle: function (x, y, w, h) {
5463
+ circle: function (x, y, w, h, wrapper) {
5464
+ // Center correction, #1682
5465
+ if (wrapper && wrapper.isCircle) {
5466
+ x -= w / 2;
5467
+ y -= h / 2;
5468
+ }
5454
5469
 
5470
+ // Return the path
5455
5471
  return [
5456
5472
  'wa', // clockwisearcto
5457
5473
  x, // left
@@ -6244,7 +6260,10 @@ StackItem.prototype = {
6244
6260
  */
6245
6261
  render: function (group) {
6246
6262
  var options = this.options,
6247
- str = options.formatter.call(this); // format the text in the label
6263
+ formatOption = options.format, // docs: added stackLabel.format option
6264
+ str = formatOption ?
6265
+ format(formatOption, this) :
6266
+ options.formatter.call(this); // format the text in the label
6248
6267
 
6249
6268
  // Change the text to reflect the new total and set visibility to hidden in case the serie is hidden
6250
6269
  if (this.label) {
@@ -6424,7 +6443,7 @@ Axis.prototype = {
6424
6443
  //textAlign: dynamic,
6425
6444
  //rotation: 0,
6426
6445
  formatter: function () {
6427
- return this.total;
6446
+ return numberFormat(this.total, -1);
6428
6447
  },
6429
6448
  style: defaultLabelOptions.style
6430
6449
  }
@@ -6699,6 +6718,9 @@ Axis.prototype = {
6699
6718
  erase(chart.axes, this);
6700
6719
  erase(chart[key], this);
6701
6720
  chart.options[key].splice(this.options.index, 1);
6721
+ each(chart[key], function (axis, i) { // Re-index, #1706
6722
+ axis.options.index = i;
6723
+ });
6702
6724
  this.destroy();
6703
6725
  chart.isDirtyBox = true;
6704
6726
 
@@ -7399,7 +7421,7 @@ Axis.prototype = {
7399
7421
  }
7400
7422
 
7401
7423
  // Record minPointOffset and pointRangePadding
7402
- ordinalCorrection = axis.ordinalSlope ? axis.ordinalSlope / closestPointRange : 1; // #988
7424
+ ordinalCorrection = axis.ordinalSlope && closestPointRange ? axis.ordinalSlope / closestPointRange : 1; // #988, #1853
7403
7425
  axis.minPointOffset = minPointOffset = minPointOffset * ordinalCorrection;
7404
7426
  axis.pointRangePadding = pointRangePadding = pointRangePadding * ordinalCorrection;
7405
7427
 
@@ -8462,6 +8484,8 @@ Tooltip.prototype = {
8462
8484
  if (this.label) {
8463
8485
  this.label = this.label.destroy();
8464
8486
  }
8487
+ clearTimeout(this.hideTimer);
8488
+ clearTimeout(this.tooltipTimeout);
8465
8489
  },
8466
8490
 
8467
8491
  /**
@@ -8511,7 +8535,8 @@ Tooltip.prototype = {
8511
8535
  hide: function () {
8512
8536
  var tooltip = this,
8513
8537
  hoverPoints;
8514
-
8538
+
8539
+ clearTimeout(this.hideTimer); // disallow duplicate timers (#1728, #1766)
8515
8540
  if (!this.isHidden) {
8516
8541
  hoverPoints = this.chart.hoverPoints;
8517
8542
 
@@ -9076,7 +9101,7 @@ Pointer.prototype = {
9076
9101
 
9077
9102
  // Scale each series
9078
9103
  each(chart.series, function (series) {
9079
- if (series.xAxis.zoomEnabled) {
9104
+ if (series.xAxis && series.xAxis.zoomEnabled) {
9080
9105
  series.group.attr(attribs);
9081
9106
  if (series.markerGroup) {
9082
9107
  series.markerGroup.attr(attribs);
@@ -9179,7 +9204,7 @@ Pointer.prototype = {
9179
9204
  var self = this,
9180
9205
  chart = self.chart,
9181
9206
  pinchDown = self.pinchDown,
9182
- followTouchMove = chart.tooltip.options.followTouchMove,
9207
+ followTouchMove = chart.tooltip && chart.tooltip.options.followTouchMove,
9183
9208
  touches = e.touches,
9184
9209
  touchesLength = touches.length,
9185
9210
  lastValidTouch = self.lastValidTouch,
@@ -9191,12 +9216,8 @@ Pointer.prototype = {
9191
9216
  clip = {};
9192
9217
 
9193
9218
  // On touch devices, only proceed to trigger click if a handler is defined
9194
- if (e.type === 'touchstart' && followTouchMove) {
9195
- if (self.inClass(e.target, PREFIX + 'tracker')) {
9196
- if (!chart.runTrackerClick || touchesLength > 1) {
9197
- e.preventDefault();
9198
- }
9199
- } else if (!chart.runChartClick || touchesLength > 1) {
9219
+ if (e.type === 'touchstart') {
9220
+ if (followTouchMove || hasZoom) {
9200
9221
  e.preventDefault();
9201
9222
  }
9202
9223
  }
@@ -9383,9 +9404,8 @@ Pointer.prototype = {
9383
9404
  each(chart.axes, function (axis) {
9384
9405
  if (axis.zoomEnabled) {
9385
9406
  var horiz = axis.horiz,
9386
- minPixelPadding = axis.minPixelPadding,
9387
- selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) + minPixelPadding),
9388
- selectionMax = axis.toValue((horiz ? selectionLeft + selectionBox.width : selectionTop + selectionBox.height) - minPixelPadding);
9407
+ selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop)),
9408
+ selectionMax = axis.toValue((horiz ? selectionLeft + selectionBox.width : selectionTop + selectionBox.height));
9389
9409
 
9390
9410
  if (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859
9391
9411
  selectionData[axis.xOrY + 'Axis'].push({
@@ -9420,7 +9440,7 @@ Pointer.prototype = {
9420
9440
  // Reset all
9421
9441
  if (chart) { // it may be destroyed on mouse up - #877
9422
9442
  css(chart.container, { cursor: chart._cursor });
9423
- chart.cancelClick = this.hasDragged; // #370
9443
+ chart.cancelClick = this.hasDragged > 10; // #370
9424
9444
  chart.mouseIsDown = this.hasDragged = this.hasPinched = false;
9425
9445
  this.pinchDown = [];
9426
9446
  }
@@ -9488,8 +9508,8 @@ Pointer.prototype = {
9488
9508
  this.drag(e);
9489
9509
  }
9490
9510
 
9491
- // Show the tooltip and run mouse over events (#977)
9492
- if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) {
9511
+ // Show the tooltip and run mouse over events (#977)
9512
+ if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop) && !chart.openMenu) {
9493
9513
  this.runPointActions(e);
9494
9514
  }
9495
9515
  },
@@ -9556,7 +9576,9 @@ Pointer.prototype = {
9556
9576
  }));
9557
9577
 
9558
9578
  // the point click event
9559
- hoverPoint.firePointEvent('click', e);
9579
+ if (chart.hoverPoint) { // it may be destroyed (#1844)
9580
+ hoverPoint.firePointEvent('click', e);
9581
+ }
9560
9582
 
9561
9583
  // When clicking outside a tracker, fire a chart event
9562
9584
  } else {
@@ -10065,8 +10087,6 @@ Legend.prototype = {
10065
10087
  .add(legendGroup);
10066
10088
  legend.scrollGroup = renderer.g()
10067
10089
  .add(legend.contentGroup);
10068
- legend.clipRect = renderer.clipRect(0, 0, 9999, chart.chartHeight);
10069
- legend.contentGroup.clip(legend.clipRect);
10070
10090
  }
10071
10091
 
10072
10092
  legend.renderTitle();
@@ -10210,12 +10230,17 @@ Legend.prototype = {
10210
10230
 
10211
10231
  // Reset the legend height and adjust the clipping rectangle
10212
10232
  if (legendHeight > spaceHeight && !options.useHTML) {
10213
-
10233
+
10214
10234
  this.clipHeight = clipHeight = spaceHeight - 20 - this.titleHeight;
10215
10235
  this.pageCount = pageCount = mathCeil(legendHeight / clipHeight);
10216
10236
  this.currentPage = pick(this.currentPage, 1);
10217
10237
  this.fullHeight = legendHeight;
10218
10238
 
10239
+ // Only apply clipping if needed. Clipping causes blurred legend in PDF export (#1787)
10240
+ if (!clipRect) {
10241
+ clipRect = legend.clipRect = renderer.clipRect(0, 0, 9999, 0);
10242
+ legend.contentGroup.clip(clipRect);
10243
+ }
10219
10244
  clipRect.attr({
10220
10245
  height: clipHeight
10221
10246
  });
@@ -11112,7 +11137,8 @@ Chart.prototype = {
11112
11137
  height: chartHeight + PX,
11113
11138
  textAlign: 'left',
11114
11139
  lineHeight: 'normal', // #427
11115
- zIndex: 0 // #1072
11140
+ zIndex: 0, // #1072
11141
+ '-webkit-tap-highlight-color': 'rgba(0,0,0,0)'
11116
11142
  }, optionsChart.style),
11117
11143
  chart.renderToClone || renderTo
11118
11144
  );
@@ -12117,7 +12143,7 @@ Point.prototype = {
12117
12143
  // Insert options for valueDecimals, valuePrefix, and valueSuffix
12118
12144
  var series = this.series,
12119
12145
  seriesTooltipOptions = series.tooltipOptions,
12120
- valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''),
12146
+ valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''),
12121
12147
  valuePrefix = seriesTooltipOptions.valuePrefix || '',
12122
12148
  valueSuffix = seriesTooltipOptions.valueSuffix || '';
12123
12149
 
@@ -12518,7 +12544,7 @@ Series.prototype = {
12518
12544
 
12519
12545
  // The series needs an X and an Y axis
12520
12546
  if (!series[AXIS]) {
12521
- error(17, true);
12547
+ error(18, true);
12522
12548
  }
12523
12549
 
12524
12550
  });
@@ -13129,13 +13155,18 @@ Series.prototype = {
13129
13155
  dataLength = points.length,
13130
13156
  hasModifyValue = !!series.modifyValue,
13131
13157
  isBottomSeries,
13132
- allStackSeries = yAxis.series,
13133
- i = allStackSeries.length,
13158
+ allStackSeries,
13159
+ i,
13134
13160
  placeBetween = options.pointPlacement === 'between',
13135
13161
  threshold = options.threshold;
13136
13162
  //nextSeriesDown;
13137
13163
 
13138
- // Is it the last visible series?
13164
+ // Is it the last visible series? (#809, #1722).
13165
+ // TODO: After merging in the 'stacking' branch, this logic should probably be moved to Chart.getStacks
13166
+ allStackSeries = yAxis.series.sort(function (a, b) {
13167
+ return a.index - b.index;
13168
+ });
13169
+ i = allStackSeries.length;
13139
13170
  while (i--) {
13140
13171
  if (allStackSeries[i].visible) {
13141
13172
  if (allStackSeries[i] === series) { // #809
@@ -13278,19 +13309,25 @@ Series.prototype = {
13278
13309
  var series = this,
13279
13310
  tooltipOptions = series.tooltipOptions,
13280
13311
  xDateFormat = tooltipOptions.xDateFormat,
13312
+ dateTimeLabelFormats = tooltipOptions.dateTimeLabelFormats,
13281
13313
  xAxis = series.xAxis,
13282
13314
  isDateTime = xAxis && xAxis.options.type === 'datetime',
13283
13315
  headerFormat = tooltipOptions.headerFormat,
13316
+ closestPointRange = xAxis && xAxis.closestPointRange,
13284
13317
  n;
13285
13318
 
13286
13319
  // Guess the best date format based on the closest point distance (#568)
13287
13320
  if (isDateTime && !xDateFormat) {
13288
- for (n in timeUnits) {
13289
- if (timeUnits[n] >= xAxis.closestPointRange) {
13290
- xDateFormat = tooltipOptions.dateTimeLabelFormats[n];
13291
- break;
13292
- }
13293
- }
13321
+ if (closestPointRange) {
13322
+ for (n in timeUnits) {
13323
+ if (timeUnits[n] >= closestPointRange) {
13324
+ xDateFormat = dateTimeLabelFormats[n];
13325
+ break;
13326
+ }
13327
+ }
13328
+ } else {
13329
+ xDateFormat = dateTimeLabelFormats.day;
13330
+ }
13294
13331
  }
13295
13332
 
13296
13333
  // Insert the header date format if any
@@ -13480,7 +13517,7 @@ Series.prototype = {
13480
13517
  graphic = point.graphic;
13481
13518
  pointMarkerOptions = point.marker || {};
13482
13519
  enabled = (seriesMarkerOptions.enabled && pointMarkerOptions.enabled === UNDEFINED) || pointMarkerOptions.enabled;
13483
- isInside = chart.isInsidePlot(plotX, plotY, chart.inverted);
13520
+ isInside = chart.isInsidePlot(mathRound(plotX), plotY, chart.inverted); // #1858
13484
13521
 
13485
13522
  // only draw the point if y is defined
13486
13523
  if (enabled && plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {
@@ -13669,7 +13706,7 @@ Series.prototype = {
13669
13706
  );
13670
13707
 
13671
13708
  // Force the fill to negativeColor on markers
13672
- if (point.negative && seriesOptions.marker) {
13709
+ if (point.negative && seriesOptions.marker && negativeColor) {
13673
13710
  pointAttr[NORMAL_STATE].fill = pointAttr[HOVER_STATE].fill = pointAttr[SELECT_STATE].fill =
13674
13711
  series.convertAttribs({ fillColor: negativeColor }).fill;
13675
13712
  }
@@ -14110,6 +14147,8 @@ Series.prototype = {
14110
14147
  translatedThreshold,
14111
14148
  posAttr,
14112
14149
  negAttr,
14150
+ graph = this.graph,
14151
+ area = this.area,
14113
14152
  posClip = this.posClip,
14114
14153
  negClip = this.negClip,
14115
14154
  chartWidth = chart.chartWidth,
@@ -14118,7 +14157,7 @@ Series.prototype = {
14118
14157
  above,
14119
14158
  below;
14120
14159
 
14121
- if (negativeColor && this.graph) {
14160
+ if (negativeColor && (graph || area)) {
14122
14161
  translatedThreshold = mathCeil(this.yAxis.len - this.yAxis.translate(options.threshold || 0));
14123
14162
  above = {
14124
14163
  x: 0,
@@ -14160,14 +14199,17 @@ Series.prototype = {
14160
14199
  posClip.animate(posAttr);
14161
14200
  negClip.animate(negAttr);
14162
14201
  } else {
14163
- this.posClip = posClip = renderer.clipRect(posAttr);
14164
- this.graph.clip(posClip);
14165
14202
 
14203
+ this.posClip = posClip = renderer.clipRect(posAttr);
14166
14204
  this.negClip = negClip = renderer.clipRect(negAttr);
14167
- this.graphNeg.clip(negClip);
14168
14205
 
14169
- if (this.area) {
14170
- this.area.clip(posClip);
14206
+ if (graph) {
14207
+ graph.clip(posClip);
14208
+ this.graphNeg.clip(negClip);
14209
+ }
14210
+
14211
+ if (area) {
14212
+ area.clip(posClip);
14171
14213
  this.areaNeg.clip(negClip);
14172
14214
  }
14173
14215
  }
@@ -14180,6 +14222,11 @@ Series.prototype = {
14180
14222
  invertGroups: function () {
14181
14223
  var series = this,
14182
14224
  chart = series.chart;
14225
+
14226
+ // Pie, go away (#1736)
14227
+ if (!series.xAxis) {
14228
+ return;
14229
+ }
14183
14230
 
14184
14231
  // A fixed size is needed for inversion to work
14185
14232
  function setInvert() {
@@ -14234,7 +14281,6 @@ Series.prototype = {
14234
14281
  scaleX: 1, // #1623
14235
14282
  scaleY: 1
14236
14283
  });
14237
-
14238
14284
  return group;
14239
14285
 
14240
14286
  },
@@ -14281,8 +14327,8 @@ Series.prototype = {
14281
14327
  // cache attributes for shapes
14282
14328
  series.getAttribs();
14283
14329
 
14284
- // SVGRenderer needs to know this before drawing elements (#1089)
14285
- group.inverted = chart.inverted;
14330
+ // SVGRenderer needs to know this before drawing elements (#1089, #1795)
14331
+ group.inverted = series.isCartesian ? chart.inverted : false;
14286
14332
 
14287
14333
  // draw the graph if any
14288
14334
  if (series.drawGraph) {
@@ -16077,6 +16123,7 @@ var PieSeries = {
16077
16123
  dataLabel = point.dataLabel;
16078
16124
 
16079
16125
  if (dataLabel && dataLabel._pos) {
16126
+ visibility = dataLabel._attr.visibility;
16080
16127
  x = dataLabel.connX;
16081
16128
  y = dataLabel.connY;
16082
16129
  connectorPath = softConnector ? [