highcharts-rails 3.0.1.5 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 ? [