highcharts-rails 4.0.1 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +60 -0
- data/app/assets/javascripts/highcharts.js +436 -412
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +1 -1
- data/app/assets/javascripts/highcharts/highcharts-3d.js +272 -168
- data/app/assets/javascripts/highcharts/highcharts-more.js +51 -21
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +1 -1
- data/app/assets/javascripts/highcharts/modules/data.js +27 -12
- data/app/assets/javascripts/highcharts/modules/drilldown.js +2 -1
- data/app/assets/javascripts/highcharts/modules/exporting.js +6 -2
- data/app/assets/javascripts/highcharts/modules/heatmap.js +125 -56
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +1 -1
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +15 -5
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +3 -0
- data/lib/highcharts/version.rb +1 -1
- metadata +3 -3
- checksums.yaml.gz.asc +0 -18
- data.tar.gz.asc +0 -18
- metadata.gz.asc +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 246fa26d563f5ebbff59b1fad5fd84c66c8139ed
|
4
|
+
data.tar.gz: c866482da07406051a1cf89456b8ffb981b8a2b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b22d1db2a1152606cb5fab1e3c3a7b073e6ee8f45bf1d84d686f4b7f251bc9d34373bff24336a14fd55be63ee55cdd4f32befa0c1f676bd4df8a3e3cbbd6b9f
|
7
|
+
data.tar.gz: 9a7c6ac887b3282e97490c4050b95505fd2c927a57937c3966b9c8648bd4a6b1448c8acd3a43503e615906deb4295c867936516889eb248acc1ec41e8daa3b2c
|
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,63 @@
|
|
1
|
+
# 4.0.3 / 2014-07-03
|
2
|
+
|
3
|
+
* Updated Highcharts to 4.0.3
|
4
|
+
* Added 3d options edgeColor and edgeWidth to distinguish from borders that have different defaults.
|
5
|
+
* Added option, chart.panKey, to allow panning and zooming on the same chart. The chart can now be configured so the user can pan by holding down the shift key while dragging.
|
6
|
+
* Added features zMin and zMax for bubble series, to set the Z value corresponding to minSize and maxSize independently from the data.
|
7
|
+
* Changed default top position for loading label to 45%, which results in a vertically centered label.
|
8
|
+
* Better handling of data label heights on pie charts, related to #2630.
|
9
|
+
* Better handling of dynamic font sizes. Adjust tooltip text-wrapping. Apply dynamic font size (em) on line breaks. Fixed placement of title and axis labels when using ems for font size. Added support for em font-size in legend.itemStyle.
|
10
|
+
* Fixed #2251, a regression since 3.0.8 causing text and graphic elements to become selected while zooming in old IE.
|
11
|
+
* Fixed #3195 where a short axis with startOnTick and endOnTick set to false would display no ticks at all.
|
12
|
+
* Fixed #2694 causing columns to overlap by one pixel in some cases when pointPadding is 0.
|
13
|
+
* Fixed #2227, waterfall breaking with more than one intermediate sum.
|
14
|
+
* Fixed #3163, pie chart data labels displaying outside plot area.
|
15
|
+
* Fixed #1991, a regression causing area stacks with null or missing values to draw incorrectly.
|
16
|
+
* Fixed #3158 causing wrong line wraps on text containing markup.
|
17
|
+
* Fixed #3151, waterfall columns not displaying a border when the rendered height was 0.
|
18
|
+
* Downloadbuilder missing metatags in SVG, added filterset, fixes #3106
|
19
|
+
* Fixed #3072 causing unexpected borders after hover on column series when borderWidth was 0.
|
20
|
+
* Fixed #3132 causing wrong line breaks in SVG text (pseudo HTML) containing markup.
|
21
|
+
* Enabled mouse tracking on data labels for some series types where it had been mistakenly disabled.
|
22
|
+
* Fixed #2697, JavaScript error in IE11 on destroying a chart containing useHTML elements after the chart container has first been emptied.
|
23
|
+
* Fixed #3126, waterfall graph getting wider on hover. Introduced new options, lineWidthPlus, radiusPlus for hover state of graphs and markers.
|
24
|
+
* Fixed #3116, halo failing to animate when a point was updated to a new position. Removed redundant pointer.reset call on Axis.redraw because Chart.redraw also calls the same method.
|
25
|
+
* Fixed #3113, roundoff error throwing off calculations of extremes on log axis.
|
26
|
+
* Fixed #3104, touch panning not being able to pan outside the data range even if the axis min and max options were outside the range.
|
27
|
+
* Fixed #3098, plot area size of a pie chart not being recalculated after the legend size changed.
|
28
|
+
* Fixed #3090 causing default 3d options not to be interpreted correctly.
|
29
|
+
* Fixed #3094 causing series Z index to change after Series.update.
|
30
|
+
* Fixed regression issue #3095, semi-transparent fills coming out as black in exports created by Batik.
|
31
|
+
* Fixed #3082, positioning of 3d pie datalabels.
|
32
|
+
* Fixed #3080 causing JS error on low chart due to negative height of the legend clip rectangle.
|
33
|
+
* Fixed #3051 causing wrong Z indexes for slices in 3d pie charts.
|
34
|
+
* Fixed #3075 causing touch panning on a categorized axis to alter range.
|
35
|
+
* Fixed #3039, series options was not read for 3D.
|
36
|
+
* Fixed #2893 causing heatmap point colors not to update after updating the color axis coloring.
|
37
|
+
* Fixed #1080, loading text not reflowing to changed chart size.
|
38
|
+
* Fixed #3056 with tooltip chevron not pointing exactly on the right point of the graph when animating between close positions.
|
39
|
+
* Fixed #3044 causing JS errors in some cases when axis label formatter returned null or undefined. Closes #3050.
|
40
|
+
* Fixed #3053 causing series to be cropped too tight on logarithmic X axis when the number of points exceeded the crop threshold.
|
41
|
+
* Fixed #2240 causing the point mouse out event not to fire when the tooltip is shared.
|
42
|
+
* Fixed #2997, solidgauge issue with points past ±360° or below yAxis.min.
|
43
|
+
* Fixed #3028 causing the last series to become unlinked when calling Series.update on several linked series in succession.
|
44
|
+
* Fixed #3027 causing truncation of axis labels when the axis title offset is set and the axis title is shorter than the labels.
|
45
|
+
* Fixed #3023 causing defered data labels to show even if series was hidden in the meantime while animating.
|
46
|
+
* Fixed #3003 causing rotated data labels to be misaligned after redraw when using Standalone Framework.
|
47
|
+
* Fixed #3017 causing centering of data labels on inverted range series not to work.
|
48
|
+
* Fixed #3007, with halo showing on invisible points in pies.
|
49
|
+
* Fixed #3016 causing halo on sliced pie series to diplay incorrectly.
|
50
|
+
* Fixed #3000, labels wrongly aligned on plot lines with multiple axes.
|
51
|
+
* Fixed #3014 causing wrong tooltip position in waterfall charts in Highcharts 4.
|
52
|
+
* Fixed #3006, prevent null and 0 points from rendering in 3D Pies.
|
53
|
+
* Fixed #2982 by returning the added plot line or plot band object after Axis.addPlotLine or Axis.addPlotBand.
|
54
|
+
* Fixed #2977, set mimimum view point distance for 3D.
|
55
|
+
* Fixed #2975 with clipping not being updated on column series and derived series types after chart resize.
|
56
|
+
* Fixed #2968, 3d columns not drawn correctly when equal to max.
|
57
|
+
* Fixed #2963 where columns were badly drawn in Chrome due to a rendering bug.
|
58
|
+
* Fixed #2962 causing data labels on gauges not to display unless defer is set to true.
|
59
|
+
* Fixed #2954 that caused invalid SVG attributes on animating in and out grid lines when running older jQuery versions or the Standalone Framework.
|
60
|
+
|
1
61
|
# 4.0.1 / 2014-04-24
|
2
62
|
|
3
63
|
* Updated Highcharts to 4.0.1
|
@@ -2,7 +2,7 @@
|
|
2
2
|
// @compilation_level SIMPLE_OPTIMIZATIONS
|
3
3
|
|
4
4
|
/**
|
5
|
-
* @license Highcharts JS v4.0.
|
5
|
+
* @license Highcharts JS v4.0.3 (2014-07-03)
|
6
6
|
*
|
7
7
|
* (c) 2009-2014 Torstein Honsi
|
8
8
|
*
|
@@ -11,7 +11,7 @@
|
|
11
11
|
|
12
12
|
// JSLint options:
|
13
13
|
/*global Highcharts, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console, each, grep */
|
14
|
-
|
14
|
+
/*jslint ass: true, sloppy: true, forin: true, plusplus: true, nomen: true, vars: true, regexp: true, newcap: true, browser: true, continue: true, white: true */
|
15
15
|
(function () {
|
16
16
|
// encapsulated variables
|
17
17
|
var UNDEFINED,
|
@@ -52,11 +52,12 @@ var UNDEFINED,
|
|
52
52
|
globalAnimation,
|
53
53
|
pathAnim,
|
54
54
|
timeUnits,
|
55
|
-
|
55
|
+
error,
|
56
|
+
noop = function () { return UNDEFINED; },
|
56
57
|
charts = [],
|
57
58
|
chartCount = 0,
|
58
59
|
PRODUCT = 'Highcharts',
|
59
|
-
VERSION = '4.0.
|
60
|
+
VERSION = '4.0.3',
|
60
61
|
|
61
62
|
// some constants for frequently used strings
|
62
63
|
DIV = 'div',
|
@@ -73,14 +74,6 @@ var UNDEFINED,
|
|
73
74
|
NORMAL_STATE = '',
|
74
75
|
HOVER_STATE = 'hover',
|
75
76
|
SELECT_STATE = 'select',
|
76
|
-
MILLISECOND = 'millisecond',
|
77
|
-
SECOND = 'second',
|
78
|
-
MINUTE = 'minute',
|
79
|
-
HOUR = 'hour',
|
80
|
-
DAY = 'day',
|
81
|
-
WEEK = 'week',
|
82
|
-
MONTH = 'month',
|
83
|
-
YEAR = 'year',
|
84
77
|
|
85
78
|
// Object for extending Axis
|
86
79
|
AxisPlotLineOrBandExtension,
|
@@ -105,11 +98,15 @@ var UNDEFINED,
|
|
105
98
|
|
106
99
|
|
107
100
|
// lookup over the types and the associated classes
|
108
|
-
seriesTypes = {}
|
101
|
+
seriesTypes = {},
|
102
|
+
Highcharts;
|
109
103
|
|
110
104
|
// The Highcharts namespace
|
111
|
-
|
112
|
-
|
105
|
+
if (win.Highcharts) {
|
106
|
+
error(16, true);
|
107
|
+
} else {
|
108
|
+
Highcharts = win.Highcharts = {};
|
109
|
+
}
|
113
110
|
/**
|
114
111
|
* Extend an object with the members of another
|
115
112
|
* @param {Object} a The object to be extended
|
@@ -179,22 +176,6 @@ function merge() {
|
|
179
176
|
return ret;
|
180
177
|
}
|
181
178
|
|
182
|
-
/**
|
183
|
-
* Take an array and turn into a hash with even number arguments as keys and odd numbers as
|
184
|
-
* values. Allows creating constants for commonly used style properties, attributes etc.
|
185
|
-
* Avoid it in performance critical situations like looping
|
186
|
-
*/
|
187
|
-
function hash() {
|
188
|
-
var i = 0,
|
189
|
-
args = arguments,
|
190
|
-
length = args.length,
|
191
|
-
obj = {};
|
192
|
-
for (; i < length; i++) {
|
193
|
-
obj[args[i++]] = args[i];
|
194
|
-
}
|
195
|
-
return obj;
|
196
|
-
}
|
197
|
-
|
198
179
|
/**
|
199
180
|
* Shortcut for parseInt
|
200
181
|
* @param {Object} s
|
@@ -217,7 +198,7 @@ function isString(s) {
|
|
217
198
|
* @param {Object} obj
|
218
199
|
*/
|
219
200
|
function isObject(obj) {
|
220
|
-
return typeof obj === 'object';
|
201
|
+
return obj && typeof obj === 'object';
|
221
202
|
}
|
222
203
|
|
223
204
|
/**
|
@@ -317,7 +298,7 @@ function pick() {
|
|
317
298
|
length = args.length;
|
318
299
|
for (i = 0; i < length; i++) {
|
319
300
|
arg = args[i];
|
320
|
-
if (
|
301
|
+
if (arg !== UNDEFINED && arg !== null) {
|
321
302
|
return arg;
|
322
303
|
}
|
323
304
|
}
|
@@ -368,7 +349,7 @@ function createElement(tag, attribs, styles, parent, nopad) {
|
|
368
349
|
* @param {Object} members
|
369
350
|
*/
|
370
351
|
function extendClass(parent, members) {
|
371
|
-
var object = function () {};
|
352
|
+
var object = function () { return UNDEFINED; };
|
372
353
|
object.prototype = new parent();
|
373
354
|
extend(object.prototype, members);
|
374
355
|
return object;
|
@@ -618,35 +599,6 @@ function normalizeTickInterval(interval, multiples, magnitude, options) {
|
|
618
599
|
}
|
619
600
|
|
620
601
|
|
621
|
-
/**
|
622
|
-
* Helper class that contains variuos counters that are local to the chart.
|
623
|
-
*/
|
624
|
-
function ChartCounters() {
|
625
|
-
this.color = 0;
|
626
|
-
this.symbol = 0;
|
627
|
-
}
|
628
|
-
|
629
|
-
ChartCounters.prototype = {
|
630
|
-
/**
|
631
|
-
* Wraps the color counter if it reaches the specified length.
|
632
|
-
*/
|
633
|
-
wrapColor: function (length) {
|
634
|
-
if (this.color >= length) {
|
635
|
-
this.color = 0;
|
636
|
-
}
|
637
|
-
},
|
638
|
-
|
639
|
-
/**
|
640
|
-
* Wraps the symbol counter if it reaches the specified length.
|
641
|
-
*/
|
642
|
-
wrapSymbol: function (length) {
|
643
|
-
if (this.symbol >= length) {
|
644
|
-
this.symbol = 0;
|
645
|
-
}
|
646
|
-
}
|
647
|
-
};
|
648
|
-
|
649
|
-
|
650
602
|
/**
|
651
603
|
* Utility method that sorts an object array and keeping the order of equal items.
|
652
604
|
* ECMA script standard does not specify the behaviour when items are equal.
|
@@ -748,14 +700,16 @@ function discardElement(element) {
|
|
748
700
|
/**
|
749
701
|
* Provide error messages for debugging, with links to online explanation
|
750
702
|
*/
|
751
|
-
function
|
703
|
+
error = function (code, stop) {
|
752
704
|
var msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code;
|
753
705
|
if (stop) {
|
754
706
|
throw msg;
|
755
|
-
}
|
707
|
+
}
|
708
|
+
// else ...
|
709
|
+
if (win.console) {
|
756
710
|
console.log(msg);
|
757
711
|
}
|
758
|
-
}
|
712
|
+
};
|
759
713
|
|
760
714
|
/**
|
761
715
|
* Fix JS round off float errors
|
@@ -780,18 +734,16 @@ function setAnimation(animation, chart) {
|
|
780
734
|
/**
|
781
735
|
* The time unit lookup
|
782
736
|
*/
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
);
|
794
|
-
/*jslint white: false*/
|
737
|
+
timeUnits = {
|
738
|
+
millisecond: 1,
|
739
|
+
second: 1000,
|
740
|
+
minute: 60000,
|
741
|
+
hour: 3600000,
|
742
|
+
day: 24 * 3600000,
|
743
|
+
week: 7 * 24 * 3600000,
|
744
|
+
month: 31 * 24 * 3600000,
|
745
|
+
year: 31556952000
|
746
|
+
};
|
795
747
|
/**
|
796
748
|
* Path interpolation algorithm used across adapters
|
797
749
|
*/
|
@@ -1006,9 +958,9 @@ pathAnim = {
|
|
1006
958
|
|
1007
959
|
} :
|
1008
960
|
function (arr, fn) { // legacy
|
1009
|
-
var i
|
961
|
+
var i,
|
1010
962
|
len = arr.length;
|
1011
|
-
for (; i < len; i++) {
|
963
|
+
for (i = 0; i < len; i++) {
|
1012
964
|
if (fn.call(arr[i], arr[i], i, arr) === false) {
|
1013
965
|
return i;
|
1014
966
|
}
|
@@ -1298,7 +1250,7 @@ defaultLabelOptions = {
|
|
1298
1250
|
|
1299
1251
|
defaultOptions = {
|
1300
1252
|
colors: ['#7cb5ec', '#434348', '#90ed7d', '#f7a35c',
|
1301
|
-
'#8085e9', '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1'],
|
1253
|
+
'#8085e9', '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1'],
|
1302
1254
|
symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
|
1303
1255
|
lang: {
|
1304
1256
|
loading: 'Loading...',
|
@@ -1315,8 +1267,8 @@ defaultOptions = {
|
|
1315
1267
|
global: {
|
1316
1268
|
useUTC: true,
|
1317
1269
|
//timezoneOffset: 0,
|
1318
|
-
canvasToolsURL: 'http://code.highcharts.com/4.0.
|
1319
|
-
VMLRadialGradientURL: 'http://code.highcharts.com/4.0.
|
1270
|
+
canvasToolsURL: 'http://code.highcharts.com/4.0.3/modules/canvas-tools.js',
|
1271
|
+
VMLRadialGradientURL: 'http://code.highcharts.com/4.0.3/gfx/vml-radial-gradient.png'
|
1320
1272
|
},
|
1321
1273
|
chart: {
|
1322
1274
|
//animation: true,
|
@@ -1373,7 +1325,7 @@ defaultOptions = {
|
|
1373
1325
|
// verticalAlign: 'top',
|
1374
1326
|
// y: null,
|
1375
1327
|
style: {
|
1376
|
-
color: '#333333',
|
1328
|
+
color: '#333333',
|
1377
1329
|
fontSize: '18px'
|
1378
1330
|
}
|
1379
1331
|
|
@@ -1386,7 +1338,7 @@ defaultOptions = {
|
|
1386
1338
|
// verticalAlign: 'top',
|
1387
1339
|
// y: null,
|
1388
1340
|
style: {
|
1389
|
-
color: '#555555'
|
1341
|
+
color: '#555555'
|
1390
1342
|
}
|
1391
1343
|
},
|
1392
1344
|
|
@@ -1417,8 +1369,9 @@ defaultOptions = {
|
|
1417
1369
|
//fillColor: null,
|
1418
1370
|
states: { // states for a single point
|
1419
1371
|
hover: {
|
1420
|
-
enabled: true
|
1421
|
-
|
1372
|
+
enabled: true,
|
1373
|
+
lineWidthPlus: 1,
|
1374
|
+
radiusPlus: 2
|
1422
1375
|
},
|
1423
1376
|
select: {
|
1424
1377
|
fillColor: '#FFFFFF',
|
@@ -1454,7 +1407,7 @@ defaultOptions = {
|
|
1454
1407
|
states: { // states for the entire series
|
1455
1408
|
hover: {
|
1456
1409
|
//enabled: false,
|
1457
|
-
|
1410
|
+
lineWidthPlus: 1,
|
1458
1411
|
marker: {
|
1459
1412
|
// lineWidth: base + 1,
|
1460
1413
|
// radius: base + 1
|
@@ -1498,7 +1451,7 @@ defaultOptions = {
|
|
1498
1451
|
},
|
1499
1452
|
//borderWidth: 0,
|
1500
1453
|
borderColor: '#909090',
|
1501
|
-
borderRadius: 0,
|
1454
|
+
borderRadius: 0,
|
1502
1455
|
navigation: {
|
1503
1456
|
// animation: true,
|
1504
1457
|
activeColor: '#274b6d',
|
@@ -1514,9 +1467,9 @@ defaultOptions = {
|
|
1514
1467
|
padding: '5px'
|
1515
1468
|
},*/
|
1516
1469
|
itemStyle: {
|
1517
|
-
color: '#333333',
|
1470
|
+
color: '#333333',
|
1518
1471
|
fontSize: '12px',
|
1519
|
-
fontWeight: 'bold'
|
1472
|
+
fontWeight: 'bold'
|
1520
1473
|
},
|
1521
1474
|
itemHoverStyle: {
|
1522
1475
|
//cursor: 'pointer', removed as of #601
|
@@ -1551,7 +1504,7 @@ defaultOptions = {
|
|
1551
1504
|
labelStyle: {
|
1552
1505
|
fontWeight: 'bold',
|
1553
1506
|
position: RELATIVE,
|
1554
|
-
top: '
|
1507
|
+
top: '45%'
|
1555
1508
|
},
|
1556
1509
|
// showDuration: 0,
|
1557
1510
|
style: {
|
@@ -1581,9 +1534,9 @@ defaultOptions = {
|
|
1581
1534
|
},
|
1582
1535
|
//formatter: defaultFormatter,
|
1583
1536
|
headerFormat: '<span style="font-size: 10px">{point.key}</span><br/>',
|
1584
|
-
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>',
|
1537
|
+
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>',
|
1585
1538
|
shadow: true,
|
1586
|
-
//shape: '
|
1539
|
+
//shape: 'callout',
|
1587
1540
|
//shared: false,
|
1588
1541
|
snap: isTouchDevice ? 25 : 10,
|
1589
1542
|
style: {
|
@@ -1816,6 +1769,13 @@ var Color = function (input) {
|
|
1816
1769
|
function SVGElement() {}
|
1817
1770
|
|
1818
1771
|
SVGElement.prototype = {
|
1772
|
+
|
1773
|
+
// Default base for animation
|
1774
|
+
opacity: 1,
|
1775
|
+
// For labels, these CSS properties are applied to the <text> node directly
|
1776
|
+
textProps: ['fontSize', 'fontWeight', 'fontFamily', 'color',
|
1777
|
+
'lineHeight', 'width', 'textDecoration', 'textShadow', 'HcTextStroke'],
|
1778
|
+
|
1819
1779
|
/**
|
1820
1780
|
* Initialize the SVG renderer
|
1821
1781
|
* @param {Object} renderer
|
@@ -1828,10 +1788,7 @@ SVGElement.prototype = {
|
|
1828
1788
|
doc.createElementNS(SVG_NS, nodeName);
|
1829
1789
|
wrapper.renderer = renderer;
|
1830
1790
|
},
|
1831
|
-
|
1832
|
-
* Default base for animation
|
1833
|
-
*/
|
1834
|
-
opacity: 1,
|
1791
|
+
|
1835
1792
|
/**
|
1836
1793
|
* Animate a given attribute
|
1837
1794
|
* @param {Object} params
|
@@ -1853,6 +1810,7 @@ SVGElement.prototype = {
|
|
1853
1810
|
complete();
|
1854
1811
|
}
|
1855
1812
|
}
|
1813
|
+
return this;
|
1856
1814
|
},
|
1857
1815
|
|
1858
1816
|
/**
|
@@ -2108,7 +2066,7 @@ SVGElement.prototype = {
|
|
2108
2066
|
key,
|
2109
2067
|
attribs = {},
|
2110
2068
|
normalizer,
|
2111
|
-
strokeWidth = rect.strokeWidth || wrapper.strokeWidth ||
|
2069
|
+
strokeWidth = rect.strokeWidth || wrapper.strokeWidth || 0;
|
2112
2070
|
|
2113
2071
|
normalizer = mathRound(strokeWidth) % 2 / 2; // mathRound because strokeWidth can sometimes have roundoff errors
|
2114
2072
|
|
@@ -2624,8 +2582,8 @@ SVGElement.prototype = {
|
|
2624
2582
|
});
|
2625
2583
|
}
|
2626
2584
|
|
2627
|
-
// In case of useHTML, clean up empty containers emulating SVG groups (#1960, #2393).
|
2628
|
-
while (parentToClean && parentToClean.div.childNodes.length === 0) {
|
2585
|
+
// In case of useHTML, clean up empty containers emulating SVG groups (#1960, #2393, #2697).
|
2586
|
+
while (parentToClean && parentToClean.div && parentToClean.div.childNodes.length === 0) {
|
2629
2587
|
grandParent = parentToClean.parentGroup;
|
2630
2588
|
wrapper.safeRemoveChild(parentToClean.div);
|
2631
2589
|
delete parentToClean.div;
|
@@ -2712,7 +2670,7 @@ SVGElement.prototype = {
|
|
2712
2670
|
_defaultGetter: function (key) {
|
2713
2671
|
var ret = pick(this[key], this.element ? this.element.getAttribute(key) : null, 0);
|
2714
2672
|
|
2715
|
-
if (/^[0-9\.]+$/.test(ret)) { // is numerical
|
2673
|
+
if (/^[\-0-9\.]+$/.test(ret)) { // is numerical
|
2716
2674
|
ret = parseFloat(ret);
|
2717
2675
|
}
|
2718
2676
|
return ret;
|
@@ -2743,11 +2701,12 @@ SVGElement.prototype = {
|
|
2743
2701
|
.replace(/dot/g, '1,3,')
|
2744
2702
|
.replace('dash', '4,3,')
|
2745
2703
|
.replace(/,$/, '')
|
2704
|
+
.replace('solid', 1)
|
2746
2705
|
.split(','); // ending comma
|
2747
2706
|
|
2748
2707
|
i = value.length;
|
2749
2708
|
while (i--) {
|
2750
|
-
value[i] = pInt(value[i]) * this
|
2709
|
+
value[i] = pInt(value[i]) * this['stroke-width'];
|
2751
2710
|
}
|
2752
2711
|
value = value.join(',');
|
2753
2712
|
this.element.setAttribute('stroke-dasharray', value);
|
@@ -2760,15 +2719,6 @@ SVGElement.prototype = {
|
|
2760
2719
|
this[key] = value;
|
2761
2720
|
element.setAttribute(key, value);
|
2762
2721
|
},
|
2763
|
-
// In Chrome/Win < 6 as well as Batik and PhantomJS as of 1.9.7, the stroke attribute can't be set when the stroke-
|
2764
|
-
// width is 0. #1369
|
2765
|
-
'stroke-widthSetter': function (value, key, element) {
|
2766
|
-
if (value === 0) {
|
2767
|
-
value = 0.00001;
|
2768
|
-
}
|
2769
|
-
this.strokeWidth = value; // read in symbol paths like 'callout'
|
2770
|
-
element.setAttribute(key, value);
|
2771
|
-
},
|
2772
2722
|
titleSetter: function (value) {
|
2773
2723
|
var titleNode = this.element.getElementsByTagName('title')[0];
|
2774
2724
|
if (!titleNode) {
|
@@ -2789,7 +2739,6 @@ SVGElement.prototype = {
|
|
2789
2739
|
}
|
2790
2740
|
},
|
2791
2741
|
fillSetter: function (value, key, element) {
|
2792
|
-
|
2793
2742
|
if (typeof value === 'string') {
|
2794
2743
|
element.setAttribute(key, value);
|
2795
2744
|
} else if (value) {
|
@@ -2813,24 +2762,22 @@ SVGElement.prototype.translateXSetter = SVGElement.prototype.translateYSetter =
|
|
2813
2762
|
this[key] = value;
|
2814
2763
|
this.doTransform = true;
|
2815
2764
|
};
|
2816
|
-
SVGElement.prototype.strokeSetter = SVGElement.prototype.fillSetter;
|
2817
|
-
|
2818
2765
|
|
2819
|
-
|
2820
|
-
//
|
2821
|
-
|
2822
|
-
/*SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter = function (value, key) {
|
2766
|
+
// WebKit and Batik have problems with a stroke-width of zero, so in this case we remove the
|
2767
|
+
// stroke attribute altogether. #1270, #1369, #3065, #3072.
|
2768
|
+
SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter = function (value, key, element) {
|
2823
2769
|
this[key] = value;
|
2824
2770
|
// Only apply the stroke attribute if the stroke width is defined and larger than 0
|
2825
2771
|
if (this.stroke && this['stroke-width']) {
|
2826
|
-
this.
|
2827
|
-
|
2772
|
+
this.strokeWidth = this['stroke-width'];
|
2773
|
+
SVGElement.prototype.fillSetter.call(this, this.stroke, 'stroke', element); // use prototype as instance may be overridden
|
2774
|
+
element.setAttribute('stroke-width', this['stroke-width']);
|
2828
2775
|
this.hasStroke = true;
|
2829
2776
|
} else if (key === 'stroke-width' && value === 0 && this.hasStroke) {
|
2830
|
-
|
2777
|
+
element.removeAttribute('stroke');
|
2831
2778
|
this.hasStroke = false;
|
2832
2779
|
}
|
2833
|
-
}
|
2780
|
+
};
|
2834
2781
|
|
2835
2782
|
|
2836
2783
|
/**
|
@@ -3002,6 +2949,7 @@ SVGRenderer.prototype = {
|
|
3002
2949
|
textStyles = wrapper.styles,
|
3003
2950
|
width = wrapper.textWidth,
|
3004
2951
|
textLineHeight = textStyles && textStyles.lineHeight,
|
2952
|
+
textStroke = textStyles && textStyles.HcTextStroke,
|
3005
2953
|
i = childNodes.length,
|
3006
2954
|
getLineHeight = function (tspan) {
|
3007
2955
|
return textLineHeight ?
|
@@ -3009,7 +2957,8 @@ SVGRenderer.prototype = {
|
|
3009
2957
|
renderer.fontMetrics(
|
3010
2958
|
/(px|em)$/.test(tspan && tspan.style.fontSize) ?
|
3011
2959
|
tspan.style.fontSize :
|
3012
|
-
((textStyles && textStyles.fontSize) || renderer.style.fontSize || 12)
|
2960
|
+
((textStyles && textStyles.fontSize) || renderer.style.fontSize || 12),
|
2961
|
+
tspan
|
3013
2962
|
).h;
|
3014
2963
|
};
|
3015
2964
|
|
@@ -3018,8 +2967,9 @@ SVGRenderer.prototype = {
|
|
3018
2967
|
textNode.removeChild(childNodes[i]);
|
3019
2968
|
}
|
3020
2969
|
|
3021
|
-
// Skip tspans, add text directly to text node
|
3022
|
-
|
2970
|
+
// Skip tspans, add text directly to text node. The forceTSpan is a hook
|
2971
|
+
// used in text outline hack.
|
2972
|
+
if (!hasMarkup && !textStroke && textStr.indexOf(' ') === -1) {
|
3023
2973
|
textNode.appendChild(doc.createTextNode(textStr));
|
3024
2974
|
return;
|
3025
2975
|
|
@@ -3094,6 +3044,9 @@ SVGRenderer.prototype = {
|
|
3094
3044
|
// add attributes
|
3095
3045
|
attr(tspan, attributes);
|
3096
3046
|
|
3047
|
+
// Append it
|
3048
|
+
textNode.appendChild(tspan);
|
3049
|
+
|
3097
3050
|
// first span on subsequent line, add the line height
|
3098
3051
|
if (!spanNo && lineNo) {
|
3099
3052
|
|
@@ -3107,27 +3060,19 @@ SVGRenderer.prototype = {
|
|
3107
3060
|
attr(
|
3108
3061
|
tspan,
|
3109
3062
|
'dy',
|
3110
|
-
getLineHeight(tspan)
|
3111
|
-
// Safari 6.0.2 - too optimized for its own good (#1539)
|
3112
|
-
// TODO: revisit this with future versions of Safari
|
3113
|
-
isWebKit && tspan.offsetHeight
|
3063
|
+
getLineHeight(tspan)
|
3114
3064
|
);
|
3115
3065
|
}
|
3116
3066
|
|
3117
|
-
// Append it
|
3118
|
-
textNode.appendChild(tspan);
|
3119
|
-
|
3120
|
-
spanNo++;
|
3121
|
-
|
3122
3067
|
// check width and apply soft breaks
|
3123
3068
|
if (width) {
|
3124
3069
|
var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
|
3125
|
-
hasWhiteSpace = words.length > 1 && textStyles.whiteSpace !== 'nowrap',
|
3070
|
+
hasWhiteSpace = spans.length > 1 || (words.length > 1 && textStyles.whiteSpace !== 'nowrap'),
|
3126
3071
|
tooLong,
|
3127
3072
|
actualWidth,
|
3128
|
-
|
3073
|
+
hcHeight = textStyles.HcHeight,
|
3129
3074
|
rest = [],
|
3130
|
-
dy = getLineHeight(),
|
3075
|
+
dy = getLineHeight(tspan),
|
3131
3076
|
softLineNo = 1,
|
3132
3077
|
bBox;
|
3133
3078
|
|
@@ -3147,8 +3092,7 @@ SVGRenderer.prototype = {
|
|
3147
3092
|
rest = [];
|
3148
3093
|
if (words.length) {
|
3149
3094
|
softLineNo++;
|
3150
|
-
|
3151
|
-
if (clipHeight && softLineNo * dy > clipHeight) {
|
3095
|
+
if (hcHeight && softLineNo * dy > hcHeight) {
|
3152
3096
|
words = ['...'];
|
3153
3097
|
wrapper.attr('title', wrapper.textStr);
|
3154
3098
|
} else {
|
@@ -3162,12 +3106,11 @@ SVGRenderer.prototype = {
|
|
3162
3106
|
attr(tspan, 'style', spanStyle);
|
3163
3107
|
}
|
3164
3108
|
textNode.appendChild(tspan);
|
3165
|
-
|
3166
|
-
if (actualWidth > width) { // a single word is pressing it out
|
3167
|
-
width = actualWidth;
|
3168
|
-
}
|
3169
3109
|
}
|
3170
3110
|
}
|
3111
|
+
if (actualWidth > width) { // a single word is pressing it out
|
3112
|
+
width = actualWidth;
|
3113
|
+
}
|
3171
3114
|
} else { // append to existing line tspan
|
3172
3115
|
tspan.removeChild(tspan.firstChild);
|
3173
3116
|
rest.unshift(words.pop());
|
@@ -3177,6 +3120,8 @@ SVGRenderer.prototype = {
|
|
3177
3120
|
}
|
3178
3121
|
}
|
3179
3122
|
}
|
3123
|
+
|
3124
|
+
spanNo++;
|
3180
3125
|
}
|
3181
3126
|
}
|
3182
3127
|
});
|
@@ -3503,8 +3448,7 @@ SVGRenderer.prototype = {
|
|
3503
3448
|
// could be exporting in IE
|
3504
3449
|
// using href throws "not supported" in ie7 and under, requries regex shim to fix later
|
3505
3450
|
elemWrapper.element.setAttribute('hc-svg-href', src);
|
3506
|
-
|
3507
|
-
|
3451
|
+
}
|
3508
3452
|
return elemWrapper;
|
3509
3453
|
},
|
3510
3454
|
|
@@ -3823,14 +3767,15 @@ SVGRenderer.prototype = {
|
|
3823
3767
|
|
3824
3768
|
if (!useHTML) {
|
3825
3769
|
wrapper.xSetter = function (value, key, element) {
|
3826
|
-
var
|
3827
|
-
|
3770
|
+
var tspans = element.getElementsByTagName('tspan'),
|
3771
|
+
tspan,
|
3772
|
+
parentVal = element.getAttribute(key),
|
3828
3773
|
i;
|
3829
|
-
for (i =
|
3830
|
-
|
3831
|
-
//
|
3832
|
-
if (
|
3833
|
-
|
3774
|
+
for (i = 0; i < tspans.length; i++) {
|
3775
|
+
tspan = tspans[i];
|
3776
|
+
// If the x values are equal, the tspan represents a linebreak
|
3777
|
+
if (tspan.getAttribute(key) === parentVal) {
|
3778
|
+
tspan.setAttribute(key, value);
|
3834
3779
|
}
|
3835
3780
|
}
|
3836
3781
|
element.setAttribute(key, value);
|
@@ -3843,8 +3788,12 @@ SVGRenderer.prototype = {
|
|
3843
3788
|
/**
|
3844
3789
|
* Utility to return the baseline offset and total line height from the font size
|
3845
3790
|
*/
|
3846
|
-
fontMetrics: function (fontSize) {
|
3791
|
+
fontMetrics: function (fontSize, elem) {
|
3847
3792
|
fontSize = fontSize || this.style.fontSize;
|
3793
|
+
if (elem && win.getComputedStyle) {
|
3794
|
+
elem = elem.element || elem; // SVGElement
|
3795
|
+
fontSize = win.getComputedStyle(elem, "").fontSize;
|
3796
|
+
}
|
3848
3797
|
fontSize = /px/.test(fontSize) ? pInt(fontSize) : /em/.test(fontSize) ? parseFloat(fontSize) * 12 : 12;
|
3849
3798
|
|
3850
3799
|
// Empirical values found by comparing font size and bounding box height.
|
@@ -3854,7 +3803,8 @@ SVGRenderer.prototype = {
|
|
3854
3803
|
|
3855
3804
|
return {
|
3856
3805
|
h: lineHeight,
|
3857
|
-
b: baseline
|
3806
|
+
b: baseline,
|
3807
|
+
f: fontSize
|
3858
3808
|
};
|
3859
3809
|
},
|
3860
3810
|
|
@@ -3911,7 +3861,7 @@ SVGRenderer.prototype = {
|
|
3911
3861
|
wrapper.height = (height || bBox.height || 0) + 2 * padding;
|
3912
3862
|
|
3913
3863
|
// update the label-scoped y offset
|
3914
|
-
baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b;
|
3864
|
+
baselineOffset = padding + renderer.fontMetrics(style && style.fontSize, text).b;
|
3915
3865
|
|
3916
3866
|
|
3917
3867
|
if (needsBox) {
|
@@ -4087,7 +4037,7 @@ SVGRenderer.prototype = {
|
|
4087
4037
|
if (styles) {
|
4088
4038
|
var textStyles = {};
|
4089
4039
|
styles = merge(styles); // create a copy to avoid altering the original object (#537)
|
4090
|
-
each(
|
4040
|
+
each(wrapper.textProps, function (prop) {
|
4091
4041
|
if (styles[prop] !== UNDEFINED) {
|
4092
4042
|
textStyles[prop] = styles[prop];
|
4093
4043
|
delete styles[prop];
|
@@ -4460,7 +4410,7 @@ if (!hasSVG && !useCanVG) {
|
|
4460
4410
|
/**
|
4461
4411
|
* The VML element wrapper.
|
4462
4412
|
*/
|
4463
|
-
|
4413
|
+
VMLElement = {
|
4464
4414
|
|
4465
4415
|
/**
|
4466
4416
|
* Initialize a new VML element wrapper. It builds the markup as a string
|
@@ -4825,7 +4775,7 @@ Highcharts.VMLElement = VMLElement = {
|
|
4825
4775
|
var i,
|
4826
4776
|
shadows = this.shadows;
|
4827
4777
|
value = value || [];
|
4828
|
-
this.d = value.join(' '); // used in getter for animation
|
4778
|
+
this.d = value.join && value.join(' '); // used in getter for animation
|
4829
4779
|
|
4830
4780
|
element.path = value = this.pathToVML(value);
|
4831
4781
|
|
@@ -4923,7 +4873,7 @@ Highcharts.VMLElement = VMLElement = {
|
|
4923
4873
|
element.style[key] = value;
|
4924
4874
|
}
|
4925
4875
|
};
|
4926
|
-
VMLElement = extendClass(SVGElement, VMLElement);
|
4876
|
+
Highcharts.VMLElement = VMLElement = extendClass(SVGElement, VMLElement);
|
4927
4877
|
|
4928
4878
|
// Some shared setters
|
4929
4879
|
VMLElement.prototype.ySetter =
|
@@ -5605,6 +5555,7 @@ Tick.prototype = {
|
|
5605
5555
|
names = axis.names,
|
5606
5556
|
pos = tick.pos,
|
5607
5557
|
labelOptions = options.labels,
|
5558
|
+
rotation = labelOptions.rotation,
|
5608
5559
|
str,
|
5609
5560
|
tickPositions = axis.tickPositions,
|
5610
5561
|
width = (horiz && categories &&
|
@@ -5651,14 +5602,14 @@ Tick.prototype = {
|
|
5651
5602
|
attr = {
|
5652
5603
|
align: axis.labelAlign
|
5653
5604
|
};
|
5654
|
-
if (isNumber(
|
5655
|
-
attr.rotation =
|
5605
|
+
if (isNumber(rotation)) {
|
5606
|
+
attr.rotation = rotation;
|
5656
5607
|
}
|
5657
5608
|
if (width && labelOptions.ellipsis) {
|
5658
|
-
|
5609
|
+
css.HcHeight = axis.len / tickPositions.length;
|
5659
5610
|
}
|
5660
5611
|
|
5661
|
-
tick.label =
|
5612
|
+
tick.label = label =
|
5662
5613
|
defined(str) && labelOptions.enabled ?
|
5663
5614
|
chart.renderer.text(
|
5664
5615
|
str,
|
@@ -5672,6 +5623,13 @@ Tick.prototype = {
|
|
5672
5623
|
.add(axis.labelGroup) :
|
5673
5624
|
null;
|
5674
5625
|
|
5626
|
+
// Set the tick baseline and correct for rotation (#1764)
|
5627
|
+
axis.tickBaseline = chart.renderer.fontMetrics(labelOptions.style.fontSize, label).b;
|
5628
|
+
if (rotation && axis.side === 2) {
|
5629
|
+
axis.tickBaseline *= mathCos(rotation * deg2rad);
|
5630
|
+
}
|
5631
|
+
|
5632
|
+
|
5675
5633
|
// update
|
5676
5634
|
} else if (label) {
|
5677
5635
|
label.attr({
|
@@ -5679,6 +5637,7 @@ Tick.prototype = {
|
|
5679
5637
|
})
|
5680
5638
|
.css(css);
|
5681
5639
|
}
|
5640
|
+
tick.yOffset = label ? pick(labelOptions.y, axis.tickBaseline + (axis.side === 2 ? 8 : -(label.getBBox().height / 2))) : 0;
|
5682
5641
|
},
|
5683
5642
|
|
5684
5643
|
/**
|
@@ -5755,7 +5714,7 @@ Tick.prototype = {
|
|
5755
5714
|
do {
|
5756
5715
|
index += (isFirst ? 1 : -1);
|
5757
5716
|
neighbour = axis.ticks[tickPositions[index]];
|
5758
|
-
} while (tickPositions[index] && (!neighbour || neighbour.label.line !== line));
|
5717
|
+
} while (tickPositions[index] && (!neighbour || !neighbour.label || neighbour.label.line !== line)); // #3044
|
5759
5718
|
|
5760
5719
|
neighbourEdge = neighbour && neighbour.label.xy && neighbour.label.xy.x + neighbour.getLabelSides()[isFirst ? 0 : 1];
|
5761
5720
|
|
@@ -5820,25 +5779,13 @@ Tick.prototype = {
|
|
5820
5779
|
var axis = this.axis,
|
5821
5780
|
transA = axis.transA,
|
5822
5781
|
reversed = axis.reversed,
|
5823
|
-
staggerLines = axis.staggerLines
|
5824
|
-
baseline = axis.chart.renderer.fontMetrics(labelOptions.style.fontSize).b,
|
5825
|
-
rotation = labelOptions.rotation;
|
5782
|
+
staggerLines = axis.staggerLines;
|
5826
5783
|
|
5827
5784
|
x = x + labelOptions.x - (tickmarkOffset && horiz ?
|
5828
5785
|
tickmarkOffset * transA * (reversed ? -1 : 1) : 0);
|
5829
|
-
y = y +
|
5786
|
+
y = y + this.yOffset - (tickmarkOffset && !horiz ?
|
5830
5787
|
tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
|
5831
5788
|
|
5832
|
-
// Correct for rotation (#1764)
|
5833
|
-
if (rotation && axis.side === 2) {
|
5834
|
-
y -= baseline - baseline * mathCos(rotation * deg2rad);
|
5835
|
-
}
|
5836
|
-
|
5837
|
-
// Vertically centered
|
5838
|
-
if (!defined(labelOptions.y) && !rotation) { // #1951
|
5839
|
-
y += baseline - label.getBBox().height / 2;
|
5840
|
-
}
|
5841
|
-
|
5842
5789
|
// Correct for staggered labels
|
5843
5790
|
if (staggerLines) {
|
5844
5791
|
label.line = (index / (step || 1) % staggerLines);
|
@@ -5904,6 +5851,7 @@ Tick.prototype = {
|
|
5904
5851
|
y = xy.y,
|
5905
5852
|
reverseCrisp = ((horiz && x === axis.pos + axis.len) || (!horiz && y === axis.pos)) ? -1 : 1; // #1480, #1687
|
5906
5853
|
|
5854
|
+
opacity = pick(opacity, 1);
|
5907
5855
|
this.isActive = true;
|
5908
5856
|
|
5909
5857
|
// create the grid line
|
@@ -6159,8 +6107,9 @@ Highcharts.PlotLineOrBand.prototype = {
|
|
6159
6107
|
}
|
6160
6108
|
|
6161
6109
|
// get the bounding box and align the label
|
6162
|
-
|
6163
|
-
|
6110
|
+
// #3000 changed to better handle choice between plotband or plotline
|
6111
|
+
xs = [path[1], path[4], (isBand ? path[6] : path[1])];
|
6112
|
+
ys = [path[2], path[5], (isBand ? path[7] : path[2])];
|
6164
6113
|
x = arrayMin(xs);
|
6165
6114
|
y = arrayMin(ys);
|
6166
6115
|
|
@@ -6220,11 +6169,11 @@ AxisPlotLineOrBandExtension = {
|
|
6220
6169
|
},
|
6221
6170
|
|
6222
6171
|
addPlotBand: function (options) {
|
6223
|
-
this.addPlotBandOrLine(options, 'plotBands');
|
6172
|
+
return this.addPlotBandOrLine(options, 'plotBands');
|
6224
6173
|
},
|
6225
6174
|
|
6226
6175
|
addPlotLine: function (options) {
|
6227
|
-
|
6176
|
+
return this.addPlotBandOrLine(options, 'plotLines');
|
6228
6177
|
},
|
6229
6178
|
|
6230
6179
|
/**
|
@@ -6433,7 +6382,7 @@ Axis.prototype = {
|
|
6433
6382
|
defaultBottomAxisOptions: {
|
6434
6383
|
labels: {
|
6435
6384
|
x: 0,
|
6436
|
-
y:
|
6385
|
+
y: null // based on font size
|
6437
6386
|
// overflow: undefined,
|
6438
6387
|
// staggerLines: null
|
6439
6388
|
},
|
@@ -7121,6 +7070,8 @@ Axis.prototype = {
|
|
7121
7070
|
var axis = this,
|
7122
7071
|
chart = axis.chart,
|
7123
7072
|
options = axis.options,
|
7073
|
+
startOnTick = options.startOnTick,
|
7074
|
+
endOnTick = options.endOnTick,
|
7124
7075
|
isLog = axis.isLog,
|
7125
7076
|
isDatetimeAxis = axis.isDatetimeAxis,
|
7126
7077
|
isXAxis = axis.isXAxis,
|
@@ -7213,7 +7164,7 @@ Axis.prototype = {
|
|
7213
7164
|
);
|
7214
7165
|
// For squished axes, set only two ticks
|
7215
7166
|
if (!defined(tickIntervalOption) && axis.len < tickPixelIntervalOption && !this.isRadial &&
|
7216
|
-
!this.isLog && !categories &&
|
7167
|
+
!this.isLog && !categories && startOnTick && endOnTick) {
|
7217
7168
|
keepTwoTicksOnly = true;
|
7218
7169
|
axis.tickInterval /= 4; // tick extremes closer to the real values
|
7219
7170
|
}
|
@@ -7303,13 +7254,18 @@ Axis.prototype = {
|
|
7303
7254
|
minPointOffset = axis.minPointOffset || 0,
|
7304
7255
|
singlePad;
|
7305
7256
|
|
7306
|
-
|
7257
|
+
// Prevent all ticks from being removed (#3195)
|
7258
|
+
if (!startOnTick && !endOnTick && !categories && tickPositions.length === 2) {
|
7259
|
+
tickPositions.splice(1, 0, (roundedMax + roundedMin) / 2);
|
7260
|
+
}
|
7261
|
+
|
7262
|
+
if (startOnTick) {
|
7307
7263
|
axis.min = roundedMin;
|
7308
7264
|
} else if (axis.min - minPointOffset > roundedMin) {
|
7309
7265
|
tickPositions.shift();
|
7310
7266
|
}
|
7311
7267
|
|
7312
|
-
if (
|
7268
|
+
if (endOnTick) {
|
7313
7269
|
axis.max = roundedMax;
|
7314
7270
|
} else if (axis.max + minPointOffset < roundedMax) {
|
7315
7271
|
tickPositions.pop();
|
@@ -7539,7 +7495,7 @@ Axis.prototype = {
|
|
7539
7495
|
height = pick(options.height, chart.plotHeight),
|
7540
7496
|
top = pick(options.top, chart.plotTop),
|
7541
7497
|
left = pick(options.left, chart.plotLeft + offsetLeft),
|
7542
|
-
percentRegex = /%$/;
|
7498
|
+
percentRegex = /%$/;
|
7543
7499
|
|
7544
7500
|
// Check for percentage based input values
|
7545
7501
|
if (percentRegex.test(height)) {
|
@@ -7638,6 +7594,7 @@ Axis.prototype = {
|
|
7638
7594
|
axisTitleOptions = options.title,
|
7639
7595
|
labelOptions = options.labels,
|
7640
7596
|
labelOffset = 0, // reset
|
7597
|
+
labelOffsetPadded,
|
7641
7598
|
axisOffset = chart.axisOffset,
|
7642
7599
|
clipOffset = chart.clipOffset,
|
7643
7600
|
directionFactor = [-1, 1, 1, -1][side],
|
@@ -7653,7 +7610,7 @@ Axis.prototype = {
|
|
7653
7610
|
x,
|
7654
7611
|
w,
|
7655
7612
|
lineNo,
|
7656
|
-
lineHeightCorrection
|
7613
|
+
lineHeightCorrection;
|
7657
7614
|
|
7658
7615
|
// For reuse in Axis.render
|
7659
7616
|
axis.hasData = hasData = (axis.hasVisibleSeries || (defined(axis.min) && defined(axis.max) && !!tickPositions));
|
@@ -7734,8 +7691,8 @@ Axis.prototype = {
|
|
7734
7691
|
labelOffset
|
7735
7692
|
);
|
7736
7693
|
}
|
7737
|
-
|
7738
7694
|
});
|
7695
|
+
|
7739
7696
|
if (axis.staggerLines) {
|
7740
7697
|
labelOffset *= axis.staggerLines;
|
7741
7698
|
axis.labelOffset = labelOffset;
|
@@ -7772,8 +7729,8 @@ Axis.prototype = {
|
|
7772
7729
|
|
7773
7730
|
if (showAxis) {
|
7774
7731
|
titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];
|
7775
|
-
titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10);
|
7776
7732
|
titleOffsetOption = axisTitleOptions.offset;
|
7733
|
+
titleMargin = defined(titleOffsetOption) ? 0 : pick(axisTitleOptions.margin, horiz ? 5 : 10);
|
7777
7734
|
}
|
7778
7735
|
|
7779
7736
|
// hide or show the title depending on whether showEmpty is set
|
@@ -7783,15 +7740,15 @@ Axis.prototype = {
|
|
7783
7740
|
// handle automatic or user set offset
|
7784
7741
|
axis.offset = directionFactor * pick(options.offset, axisOffset[side]);
|
7785
7742
|
|
7786
|
-
axis.
|
7787
|
-
|
7788
|
-
|
7789
|
-
|
7790
|
-
);
|
7743
|
+
lineHeightCorrection = side === 2 ? axis.tickBaseline : 0;
|
7744
|
+
labelOffsetPadded = labelOffset + titleMargin +
|
7745
|
+
(labelOffset && (directionFactor * (horiz ? pick(labelOptions.y, axis.tickBaseline + 8) : labelOptions.x) - lineHeightCorrection));
|
7746
|
+
axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded);
|
7791
7747
|
|
7792
7748
|
axisOffset[side] = mathMax(
|
7793
7749
|
axisOffset[side],
|
7794
|
-
axis.axisTitleMargin + titleOffset + directionFactor * axis.offset
|
7750
|
+
axis.axisTitleMargin + titleOffset + directionFactor * axis.offset,
|
7751
|
+
labelOffsetPadded // #3027
|
7795
7752
|
);
|
7796
7753
|
clipOffset[invertedSide] = mathMax(clipOffset[invertedSide], mathFloor(options.lineWidth / 2) * 2);
|
7797
7754
|
},
|
@@ -7961,7 +7918,7 @@ Axis.prototype = {
|
|
7961
7918
|
ticks[pos].render(i, true, 0.1);
|
7962
7919
|
}
|
7963
7920
|
|
7964
|
-
ticks[pos].render(i
|
7921
|
+
ticks[pos].render(i);
|
7965
7922
|
}
|
7966
7923
|
|
7967
7924
|
});
|
@@ -8085,25 +8042,17 @@ Axis.prototype = {
|
|
8085
8042
|
* Redraw the axis to reflect changes in the data or axis extremes
|
8086
8043
|
*/
|
8087
8044
|
redraw: function () {
|
8088
|
-
|
8089
|
-
chart = axis.chart,
|
8090
|
-
pointer = chart.pointer;
|
8091
|
-
|
8092
|
-
// hide tooltip and hover states
|
8093
|
-
if (pointer) {
|
8094
|
-
pointer.reset(true);
|
8095
|
-
}
|
8096
|
-
|
8045
|
+
|
8097
8046
|
// render the axis
|
8098
|
-
|
8047
|
+
this.render();
|
8099
8048
|
|
8100
8049
|
// move plot lines and bands
|
8101
|
-
each(
|
8050
|
+
each(this.plotLinesAndBands, function (plotLine) {
|
8102
8051
|
plotLine.render();
|
8103
8052
|
});
|
8104
8053
|
|
8105
8054
|
// mark associated series as dirty and ready for redraw
|
8106
|
-
each(
|
8055
|
+
each(this.series, function (series) {
|
8107
8056
|
series.isDirty = true;
|
8108
8057
|
});
|
8109
8058
|
|
@@ -8240,40 +8189,40 @@ Axis.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWee
|
|
8240
8189
|
count = normalizedInterval.count;
|
8241
8190
|
|
8242
8191
|
if (defined(min)) { // #1300
|
8243
|
-
if (interval >= timeUnits
|
8192
|
+
if (interval >= timeUnits.second) { // second
|
8244
8193
|
minDate.setMilliseconds(0);
|
8245
|
-
minDate.setSeconds(interval >= timeUnits
|
8194
|
+
minDate.setSeconds(interval >= timeUnits.minute ? 0 :
|
8246
8195
|
count * mathFloor(minDate.getSeconds() / count));
|
8247
8196
|
}
|
8248
8197
|
|
8249
|
-
if (interval >= timeUnits
|
8250
|
-
minDate[setMinutes](interval >= timeUnits
|
8198
|
+
if (interval >= timeUnits.minute) { // minute
|
8199
|
+
minDate[setMinutes](interval >= timeUnits.hour ? 0 :
|
8251
8200
|
count * mathFloor(minDate[getMinutes]() / count));
|
8252
8201
|
}
|
8253
8202
|
|
8254
|
-
if (interval >= timeUnits
|
8255
|
-
minDate[setHours](interval >= timeUnits
|
8203
|
+
if (interval >= timeUnits.hour) { // hour
|
8204
|
+
minDate[setHours](interval >= timeUnits.day ? 0 :
|
8256
8205
|
count * mathFloor(minDate[getHours]() / count));
|
8257
8206
|
}
|
8258
8207
|
|
8259
|
-
if (interval >= timeUnits
|
8260
|
-
minDate[setDate](interval >= timeUnits
|
8208
|
+
if (interval >= timeUnits.day) { // day
|
8209
|
+
minDate[setDate](interval >= timeUnits.month ? 1 :
|
8261
8210
|
count * mathFloor(minDate[getDate]() / count));
|
8262
8211
|
}
|
8263
8212
|
|
8264
|
-
if (interval >= timeUnits
|
8265
|
-
minDate[setMonth](interval >= timeUnits
|
8213
|
+
if (interval >= timeUnits.month) { // month
|
8214
|
+
minDate[setMonth](interval >= timeUnits.year ? 0 :
|
8266
8215
|
count * mathFloor(minDate[getMonth]() / count));
|
8267
8216
|
minYear = minDate[getFullYear]();
|
8268
8217
|
}
|
8269
8218
|
|
8270
|
-
if (interval >= timeUnits
|
8219
|
+
if (interval >= timeUnits.year) { // year
|
8271
8220
|
minYear -= minYear % count;
|
8272
8221
|
minDate[setFullYear](minYear);
|
8273
8222
|
}
|
8274
8223
|
|
8275
8224
|
// week is a special case that runs outside the hierarchy
|
8276
|
-
if (interval === timeUnits
|
8225
|
+
if (interval === timeUnits.week) {
|
8277
8226
|
// get start of current week, independent of count
|
8278
8227
|
minDate[setDate](minDate[getDate]() - minDate[getDay]() +
|
8279
8228
|
pick(startOfWeek, 1));
|
@@ -8298,18 +8247,18 @@ Axis.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWee
|
|
8298
8247
|
tickPositions.push(time);
|
8299
8248
|
|
8300
8249
|
// if the interval is years, use Date.UTC to increase years
|
8301
|
-
if (interval === timeUnits
|
8250
|
+
if (interval === timeUnits.year) {
|
8302
8251
|
time = makeTime(minYear + i * count, 0);
|
8303
8252
|
|
8304
8253
|
// if the interval is months, use Date.UTC to increase months
|
8305
|
-
} else if (interval === timeUnits
|
8254
|
+
} else if (interval === timeUnits.month) {
|
8306
8255
|
time = makeTime(minYear, minMonth + i * count);
|
8307
8256
|
|
8308
8257
|
// if we're using global time, the interval is not fixed as it jumps
|
8309
8258
|
// one hour at the DST crossover
|
8310
|
-
} else if (!useUTC && (interval === timeUnits
|
8259
|
+
} else if (!useUTC && (interval === timeUnits.day || interval === timeUnits.week)) {
|
8311
8260
|
time = makeTime(minYear, minMonth, minDateDate +
|
8312
|
-
i * count * (interval === timeUnits
|
8261
|
+
i * count * (interval === timeUnits.day ? 1 : 7));
|
8313
8262
|
|
8314
8263
|
// else, the interval is fixed and we use simple addition
|
8315
8264
|
} else {
|
@@ -8325,9 +8274,9 @@ Axis.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWee
|
|
8325
8274
|
|
8326
8275
|
// mark new days if the time is dividible by day (#1649, #1760)
|
8327
8276
|
each(grep(tickPositions, function (time) {
|
8328
|
-
return interval <= timeUnits
|
8277
|
+
return interval <= timeUnits.hour && time % timeUnits.day === localTimezoneOffset;
|
8329
8278
|
}), function (time) {
|
8330
|
-
higherRanks[time] =
|
8279
|
+
higherRanks[time] = 'day';
|
8331
8280
|
});
|
8332
8281
|
}
|
8333
8282
|
|
@@ -8351,28 +8300,28 @@ Axis.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWee
|
|
8351
8300
|
*/
|
8352
8301
|
Axis.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) {
|
8353
8302
|
var units = unitsOption || [[
|
8354
|
-
|
8303
|
+
'millisecond', // unit name
|
8355
8304
|
[1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples
|
8356
8305
|
], [
|
8357
|
-
|
8306
|
+
'second',
|
8358
8307
|
[1, 2, 5, 10, 15, 30]
|
8359
8308
|
], [
|
8360
|
-
|
8309
|
+
'minute',
|
8361
8310
|
[1, 2, 5, 10, 15, 30]
|
8362
8311
|
], [
|
8363
|
-
|
8312
|
+
'hour',
|
8364
8313
|
[1, 2, 3, 4, 6, 8, 12]
|
8365
8314
|
], [
|
8366
|
-
|
8315
|
+
'day',
|
8367
8316
|
[1, 2]
|
8368
8317
|
], [
|
8369
|
-
|
8318
|
+
'week',
|
8370
8319
|
[1, 2]
|
8371
8320
|
], [
|
8372
|
-
|
8321
|
+
'month',
|
8373
8322
|
[1, 2, 3, 4, 6]
|
8374
8323
|
], [
|
8375
|
-
|
8324
|
+
'year',
|
8376
8325
|
null
|
8377
8326
|
]],
|
8378
8327
|
unit = units[units.length - 1], // default unit is years
|
@@ -8401,7 +8350,7 @@ Axis.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption)
|
|
8401
8350
|
}
|
8402
8351
|
|
8403
8352
|
// prevent 2.5 years intervals, though 25, 250 etc. are allowed
|
8404
|
-
if (interval === timeUnits
|
8353
|
+
if (interval === timeUnits.year && tickInterval < 5 * interval) {
|
8405
8354
|
multiples = [1, 2, 5];
|
8406
8355
|
}
|
8407
8356
|
|
@@ -8409,7 +8358,7 @@ Axis.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption)
|
|
8409
8358
|
count = normalizeTickInterval(
|
8410
8359
|
tickInterval / interval,
|
8411
8360
|
multiples,
|
8412
|
-
unit[0] ===
|
8361
|
+
unit[0] === 'year' ? mathMax(getMagnitude(tickInterval / interval), 1) : 1 // #1913, #2360
|
8413
8362
|
);
|
8414
8363
|
|
8415
8364
|
return {
|
@@ -8466,8 +8415,7 @@ Axis.prototype.getLogTickPositions = function (interval, min, max, minor) {
|
|
8466
8415
|
len = intermediate.length;
|
8467
8416
|
for (j = 0; j < len && !break2; j++) {
|
8468
8417
|
pos = log2lin(lin2log(i) * intermediate[j]);
|
8469
|
-
|
8470
|
-
if (pos > min && (!minor || lastPos <= max)) { // #1670
|
8418
|
+
if (pos > min && (!minor || lastPos <= max) && lastPos !== UNDEFINED) { // #1670, lastPos is #3113
|
8471
8419
|
positions.push(lastPos);
|
8472
8420
|
}
|
8473
8421
|
|
@@ -8597,10 +8545,12 @@ Tooltip.prototype = {
|
|
8597
8545
|
move: function (x, y, anchorX, anchorY) {
|
8598
8546
|
var tooltip = this,
|
8599
8547
|
now = tooltip.now,
|
8600
|
-
animate = tooltip.options.animation !== false && !tooltip.isHidden
|
8548
|
+
animate = tooltip.options.animation !== false && !tooltip.isHidden &&
|
8549
|
+
// When we get close to the target position, abort animation and land on the right place (#3056)
|
8550
|
+
(mathAbs(x - now.x) > 1 || mathAbs(y - now.y) > 1),
|
8601
8551
|
skipAnchor = tooltip.followPointer || tooltip.len > 1;
|
8602
8552
|
|
8603
|
-
//
|
8553
|
+
// Get intermediate values for animation
|
8604
8554
|
extend(now, {
|
8605
8555
|
x: animate ? (2 * now.x + x) / 3 : x,
|
8606
8556
|
y: animate ? (now.y + y) / 2 : y,
|
@@ -8608,17 +8558,17 @@ Tooltip.prototype = {
|
|
8608
8558
|
anchorY: skipAnchor ? UNDEFINED : animate ? (now.anchorY + anchorY) / 2 : anchorY
|
8609
8559
|
});
|
8610
8560
|
|
8611
|
-
//
|
8561
|
+
// Move to the intermediate value
|
8612
8562
|
tooltip.label.attr(now);
|
8613
8563
|
|
8614
8564
|
|
8615
|
-
//
|
8616
|
-
if (animate
|
8565
|
+
// Run on next tick of the mouse tracker
|
8566
|
+
if (animate) {
|
8617
8567
|
|
8618
|
-
//
|
8568
|
+
// Never allow two timeouts
|
8619
8569
|
clearTimeout(this.tooltipTimeout);
|
8620
8570
|
|
8621
|
-
//
|
8571
|
+
// Set the fixed interval ticking for the smooth tooltip
|
8622
8572
|
this.tooltipTimeout = setTimeout(function () {
|
8623
8573
|
// The interval function may still be running during destroy, so check that the chart is really there before calling.
|
8624
8574
|
if (tooltip) {
|
@@ -8967,7 +8917,7 @@ Tooltip.prototype = {
|
|
8967
8917
|
// If the point is placed every day at 23:59, we need to show
|
8968
8918
|
// the minutes as well. This logic only works for time units less than
|
8969
8919
|
// a day, since all higher time units are dividable by those. #2637.
|
8970
|
-
(timeUnits[n] <= timeUnits
|
8920
|
+
(timeUnits[n] <= timeUnits.day && point.key % timeUnits[n] > 0)) {
|
8971
8921
|
xDateFormat = dateTimeLabelFormats[n];
|
8972
8922
|
break;
|
8973
8923
|
}
|
@@ -9326,7 +9276,8 @@ Pointer.prototype = {
|
|
9326
9276
|
clickedInside,
|
9327
9277
|
size,
|
9328
9278
|
mouseDownX = this.mouseDownX,
|
9329
|
-
mouseDownY = this.mouseDownY
|
9279
|
+
mouseDownY = this.mouseDownY,
|
9280
|
+
panKey = chartOptions.panKey && e[chartOptions.panKey + 'Key'];
|
9330
9281
|
|
9331
9282
|
// If the mouse is outside the plot area, adjust to cooordinates
|
9332
9283
|
// inside to prevent the selection marker from going outside
|
@@ -9352,7 +9303,7 @@ Pointer.prototype = {
|
|
9352
9303
|
clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop);
|
9353
9304
|
|
9354
9305
|
// make a selection
|
9355
|
-
if (chart.hasCartesianSeries && (this.zoomX || this.zoomY) && clickedInside) {
|
9306
|
+
if (chart.hasCartesianSeries && (this.zoomX || this.zoomY) && clickedInside && !panKey) {
|
9356
9307
|
if (!this.selectionMarker) {
|
9357
9308
|
this.selectionMarker = chart.renderer.rect(
|
9358
9309
|
plotLeft,
|
@@ -9420,8 +9371,9 @@ Pointer.prototype = {
|
|
9420
9371
|
each(chart.axes, function (axis) {
|
9421
9372
|
if (axis.zoomEnabled) {
|
9422
9373
|
var horiz = axis.horiz,
|
9423
|
-
|
9424
|
-
|
9374
|
+
minPixelPadding = e.type === 'touchend' ? axis.minPixelPadding: 0, // #1207, #3075
|
9375
|
+
selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) + minPixelPadding),
|
9376
|
+
selectionMax = axis.toValue((horiz ? selectionLeft + selectionWidth : selectionTop + selectionHeight) - minPixelPadding);
|
9425
9377
|
|
9426
9378
|
if (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859
|
9427
9379
|
selectionData[axis.coll].push({
|
@@ -9513,8 +9465,8 @@ Pointer.prototype = {
|
|
9513
9465
|
|
9514
9466
|
hoverChartIndex = chart.index;
|
9515
9467
|
|
9516
|
-
// normalize
|
9517
9468
|
e = this.normalize(e);
|
9469
|
+
e.returnValue = false; // #2251, #3224
|
9518
9470
|
|
9519
9471
|
if (chart.mouseIsDown === 'mousedown') {
|
9520
9472
|
this.drag(e);
|
@@ -9790,8 +9742,8 @@ extend(Highcharts.Pointer.prototype, {
|
|
9790
9742
|
if (axis.zoomEnabled) {
|
9791
9743
|
var bounds = chart.bounds[axis.horiz ? 'h' : 'v'],
|
9792
9744
|
minPixelPadding = axis.minPixelPadding,
|
9793
|
-
min = axis.toPixels(axis.dataMin),
|
9794
|
-
max = axis.toPixels(axis.dataMax),
|
9745
|
+
min = axis.toPixels(pick(axis.options.min, axis.dataMin)),
|
9746
|
+
max = axis.toPixels(pick(axis.options.max, axis.dataMax)),
|
9795
9747
|
absMin = mathMin(min, max),
|
9796
9748
|
absMax = mathMax(min, max);
|
9797
9749
|
|
@@ -9981,7 +9933,6 @@ Legend.prototype = {
|
|
9981
9933
|
return;
|
9982
9934
|
}
|
9983
9935
|
|
9984
|
-
legend.baseline = pInt(itemStyle.fontSize) + 3 + itemMarginTop; // used in Series prototype
|
9985
9936
|
legend.itemStyle = itemStyle;
|
9986
9937
|
legend.itemHiddenStyle = merge(itemStyle, options.itemHiddenStyle);
|
9987
9938
|
legend.itemMarginTop = itemMarginTop;
|
@@ -10179,7 +10130,7 @@ Legend.prototype = {
|
|
10179
10130
|
itemStyle = legend.itemStyle,
|
10180
10131
|
itemHiddenStyle = legend.itemHiddenStyle,
|
10181
10132
|
padding = legend.padding,
|
10182
|
-
itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
|
10133
|
+
itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
|
10183
10134
|
ltr = !options.rtl,
|
10184
10135
|
itemHeight,
|
10185
10136
|
widthOption = options.width,
|
@@ -10202,14 +10153,11 @@ Legend.prototype = {
|
|
10202
10153
|
.attr({ zIndex: 1 })
|
10203
10154
|
.add(legend.scrollGroup);
|
10204
10155
|
|
10205
|
-
// Draw the legend symbol inside the group box
|
10206
|
-
series.drawLegendSymbol(legend, item);
|
10207
|
-
|
10208
10156
|
// Generate the list item text and add it to the group
|
10209
10157
|
item.legendItem = li = renderer.text(
|
10210
10158
|
options.labelFormat ? format(options.labelFormat, item) : options.labelFormatter.call(item),
|
10211
10159
|
ltr ? symbolWidth + symbolPadding : -symbolPadding,
|
10212
|
-
legend.baseline,
|
10160
|
+
legend.baseline || 0,
|
10213
10161
|
useHTML
|
10214
10162
|
)
|
10215
10163
|
.css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)
|
@@ -10219,6 +10167,15 @@ Legend.prototype = {
|
|
10219
10167
|
})
|
10220
10168
|
.add(item.legendGroup);
|
10221
10169
|
|
10170
|
+
// Get the baseline for the first item - the font size is equal for all
|
10171
|
+
if (!legend.baseline) {
|
10172
|
+
legend.baseline = renderer.fontMetrics(itemStyle.fontSize, li).f + 3 + itemMarginTop;
|
10173
|
+
li.attr('y', legend.baseline);
|
10174
|
+
}
|
10175
|
+
|
10176
|
+
// Draw the legend symbol inside the group box
|
10177
|
+
series.drawLegendSymbol(legend, item);
|
10178
|
+
|
10222
10179
|
if (legend.setItemEvents) {
|
10223
10180
|
legend.setItemEvents(item, li, useHTML, itemStyle, itemHiddenStyle);
|
10224
10181
|
}
|
@@ -10471,7 +10428,7 @@ Legend.prototype = {
|
|
10471
10428
|
pages.length = 0;
|
10472
10429
|
if (legendHeight > spaceHeight && !options.useHTML) {
|
10473
10430
|
|
10474
|
-
this.clipHeight = clipHeight = spaceHeight - 20 - this.titleHeight - this.padding;
|
10431
|
+
this.clipHeight = clipHeight = mathMax(spaceHeight - 20 - this.titleHeight - this.padding, 0);
|
10475
10432
|
this.currentPage = pick(this.currentPage, 1);
|
10476
10433
|
this.fullHeight = legendHeight;
|
10477
10434
|
|
@@ -10648,9 +10605,9 @@ var LegendSymbolMixin = Highcharts.LegendSymbolMixin = {
|
|
10648
10605
|
symbolWidth = legend.symbolWidth,
|
10649
10606
|
renderer = this.chart.renderer,
|
10650
10607
|
legendItemGroup = this.legendGroup,
|
10651
|
-
verticalCenter = legend.baseline - mathRound(renderer.fontMetrics(legendOptions.itemStyle.fontSize).b * 0.3),
|
10608
|
+
verticalCenter = legend.baseline - mathRound(renderer.fontMetrics(legendOptions.itemStyle.fontSize, this.legendItem).b * 0.3),
|
10652
10609
|
attr;
|
10653
|
-
|
10610
|
+
|
10654
10611
|
// Draw the line
|
10655
10612
|
if (options.lineWidth) {
|
10656
10613
|
attr = {
|
@@ -10808,8 +10765,7 @@ Chart.prototype = {
|
|
10808
10765
|
|
10809
10766
|
// Expose methods and variables
|
10810
10767
|
chart.animation = useCanVG ? false : pick(optionsChart.animation, true);
|
10811
|
-
chart.pointCount = 0;
|
10812
|
-
chart.counters = new ChartCounters();
|
10768
|
+
chart.pointCount = chart.colorCounter = chart.symbolCounter = 0;
|
10813
10769
|
|
10814
10770
|
chart.firstRender();
|
10815
10771
|
},
|
@@ -10878,6 +10834,7 @@ Chart.prototype = {
|
|
10878
10834
|
redrawLegend = chart.isDirtyLegend,
|
10879
10835
|
hasStackedSeries,
|
10880
10836
|
hasDirtyStacks,
|
10837
|
+
hasCartesianSeries = chart.hasCartesianSeries,
|
10881
10838
|
isDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed?
|
10882
10839
|
seriesLength = series.length,
|
10883
10840
|
i = seriesLength,
|
@@ -10941,7 +10898,7 @@ Chart.prototype = {
|
|
10941
10898
|
}
|
10942
10899
|
|
10943
10900
|
|
10944
|
-
if (
|
10901
|
+
if (hasCartesianSeries) {
|
10945
10902
|
if (!chart.isResizing) {
|
10946
10903
|
|
10947
10904
|
// reset maxTicks
|
@@ -10954,8 +10911,11 @@ Chart.prototype = {
|
|
10954
10911
|
}
|
10955
10912
|
|
10956
10913
|
chart.adjustTickAmounts();
|
10957
|
-
|
10914
|
+
}
|
10915
|
+
|
10916
|
+
chart.getMargins(); // #3098
|
10958
10917
|
|
10918
|
+
if (hasCartesianSeries) {
|
10959
10919
|
// If one axis is dirty, all axes must be redrawn (#792, #2169)
|
10960
10920
|
each(axes, function (axis) {
|
10961
10921
|
if (axis.isDirty) {
|
@@ -10979,9 +10939,8 @@ Chart.prototype = {
|
|
10979
10939
|
axis.redraw();
|
10980
10940
|
}
|
10981
10941
|
});
|
10982
|
-
|
10983
|
-
|
10984
10942
|
}
|
10943
|
+
|
10985
10944
|
// the plot areas size has changed
|
10986
10945
|
if (isDirtyBox) {
|
10987
10946
|
chart.drawChartBox();
|
@@ -11190,12 +11149,15 @@ Chart.prototype = {
|
|
11190
11149
|
titleOptions = options.title,
|
11191
11150
|
subtitleOptions = options.subtitle,
|
11192
11151
|
requiresDirtyBox,
|
11152
|
+
renderer = this.renderer,
|
11193
11153
|
autoWidth = this.spacingBox.width - 44; // 44 makes room for default context button
|
11194
11154
|
|
11195
11155
|
if (title) {
|
11196
11156
|
title
|
11197
11157
|
.css({ width: (titleOptions.width || autoWidth) + PX })
|
11198
|
-
.align(extend({
|
11158
|
+
.align(extend({
|
11159
|
+
y: renderer.fontMetrics(titleOptions.style.fontSize, title).b - 3
|
11160
|
+
}, titleOptions), false, 'spacingBox');
|
11199
11161
|
|
11200
11162
|
if (!titleOptions.floating && !titleOptions.verticalAlign) {
|
11201
11163
|
titleOffset = title.getBBox().height;
|
@@ -11204,7 +11166,9 @@ Chart.prototype = {
|
|
11204
11166
|
if (subtitle) {
|
11205
11167
|
subtitle
|
11206
11168
|
.css({ width: (subtitleOptions.width || autoWidth) + PX })
|
11207
|
-
.align(extend({
|
11169
|
+
.align(extend({
|
11170
|
+
y: titleOffset + (titleOptions.margin - 13) + renderer.fontMetrics(titleOptions.style.fontSize, subtitle).b
|
11171
|
+
}, subtitleOptions), false, 'spacingBox');
|
11208
11172
|
|
11209
11173
|
if (!subtitleOptions.floating && !subtitleOptions.verticalAlign) {
|
11210
11174
|
titleOffset = mathCeil(titleOffset + subtitle.getBBox().height);
|
@@ -11647,7 +11611,7 @@ Chart.prototype = {
|
|
11647
11611
|
x: clipX,
|
11648
11612
|
y: clipY,
|
11649
11613
|
width: mathFloor(chart.plotSizeX - mathMax(plotBorderWidth, clipOffset[1]) / 2 - clipX),
|
11650
|
-
height: mathFloor(chart.plotSizeY - mathMax(plotBorderWidth, clipOffset[2]) / 2 - clipY)
|
11614
|
+
height: mathMax(0, mathFloor(chart.plotSizeY - mathMax(plotBorderWidth, clipOffset[2]) / 2 - clipY))
|
11651
11615
|
};
|
11652
11616
|
|
11653
11617
|
if (!skipAxes) {
|
@@ -11867,6 +11831,35 @@ Chart.prototype = {
|
|
11867
11831
|
serie.render();
|
11868
11832
|
});
|
11869
11833
|
},
|
11834
|
+
|
11835
|
+
/**
|
11836
|
+
* Render labels for the chart
|
11837
|
+
*/
|
11838
|
+
renderLabels: function () {
|
11839
|
+
var chart = this,
|
11840
|
+
labels = chart.options.labels;
|
11841
|
+
if (labels.items) {
|
11842
|
+
each(labels.items, function (label) {
|
11843
|
+
var style = extend(labels.style, label.style),
|
11844
|
+
x = pInt(style.left) + chart.plotLeft,
|
11845
|
+
y = pInt(style.top) + chart.plotTop + 12;
|
11846
|
+
|
11847
|
+
// delete to prevent rewriting in IE
|
11848
|
+
delete style.left;
|
11849
|
+
delete style.top;
|
11850
|
+
|
11851
|
+
chart.renderer.text(
|
11852
|
+
label.html,
|
11853
|
+
x,
|
11854
|
+
y
|
11855
|
+
)
|
11856
|
+
.attr({ zIndex: 2 })
|
11857
|
+
.css(style)
|
11858
|
+
.add();
|
11859
|
+
|
11860
|
+
});
|
11861
|
+
}
|
11862
|
+
},
|
11870
11863
|
|
11871
11864
|
/**
|
11872
11865
|
* Render all graphics for the chart
|
@@ -11877,10 +11870,6 @@ Chart.prototype = {
|
|
11877
11870
|
renderer = chart.renderer,
|
11878
11871
|
options = chart.options;
|
11879
11872
|
|
11880
|
-
var labels = options.labels,
|
11881
|
-
credits = options.credits,
|
11882
|
-
creditsHref;
|
11883
|
-
|
11884
11873
|
// Title
|
11885
11874
|
chart.setTitle();
|
11886
11875
|
|
@@ -11927,39 +11916,29 @@ Chart.prototype = {
|
|
11927
11916
|
chart.renderSeries();
|
11928
11917
|
|
11929
11918
|
// Labels
|
11930
|
-
|
11931
|
-
each(labels.items, function (label) {
|
11932
|
-
var style = extend(labels.style, label.style),
|
11933
|
-
x = pInt(style.left) + chart.plotLeft,
|
11934
|
-
y = pInt(style.top) + chart.plotTop + 12;
|
11919
|
+
chart.renderLabels();
|
11935
11920
|
|
11936
|
-
|
11937
|
-
|
11938
|
-
delete style.top;
|
11921
|
+
// Credits
|
11922
|
+
chart.showCredits(options.credits);
|
11939
11923
|
|
11940
|
-
|
11941
|
-
|
11942
|
-
x,
|
11943
|
-
y
|
11944
|
-
)
|
11945
|
-
.attr({ zIndex: 2 })
|
11946
|
-
.css(style)
|
11947
|
-
.add();
|
11924
|
+
// Set flag
|
11925
|
+
chart.hasRendered = true;
|
11948
11926
|
|
11949
|
-
|
11950
|
-
}
|
11927
|
+
},
|
11951
11928
|
|
11952
|
-
|
11953
|
-
|
11954
|
-
|
11955
|
-
|
11929
|
+
/**
|
11930
|
+
* Show chart credits based on config options
|
11931
|
+
*/
|
11932
|
+
showCredits: function (credits) {
|
11933
|
+
if (credits.enabled && !this.credits) {
|
11934
|
+
this.credits = this.renderer.text(
|
11956
11935
|
credits.text,
|
11957
11936
|
0,
|
11958
11937
|
0
|
11959
11938
|
)
|
11960
11939
|
.on('click', function () {
|
11961
|
-
if (
|
11962
|
-
location.href =
|
11940
|
+
if (credits.href) {
|
11941
|
+
location.href = credits.href;
|
11963
11942
|
}
|
11964
11943
|
})
|
11965
11944
|
.attr({
|
@@ -11970,10 +11949,6 @@ Chart.prototype = {
|
|
11970
11949
|
.add()
|
11971
11950
|
.align(credits.position);
|
11972
11951
|
}
|
11973
|
-
|
11974
|
-
// Set flag
|
11975
|
-
chart.hasRendered = true;
|
11976
|
-
|
11977
11952
|
},
|
11978
11953
|
|
11979
11954
|
/**
|
@@ -12223,7 +12198,7 @@ Point.prototype = {
|
|
12223
12198
|
applyOptions: function (options, x) {
|
12224
12199
|
var point = this,
|
12225
12200
|
series = point.series,
|
12226
|
-
pointValKey = series.pointValKey;
|
12201
|
+
pointValKey = series.options.pointValKey || series.pointValKey;
|
12227
12202
|
|
12228
12203
|
options = Point.prototype.optionsToObject.call(this, options);
|
12229
12204
|
|
@@ -12694,60 +12669,45 @@ Series.prototype = {
|
|
12694
12669
|
return options;
|
12695
12670
|
|
12696
12671
|
},
|
12697
|
-
/**
|
12698
|
-
* Get the series' color
|
12699
|
-
*/
|
12700
|
-
getColor: function () {
|
12701
|
-
var options = this.options,
|
12702
|
-
userOptions = this.userOptions,
|
12703
|
-
defaultColors = this.chart.options.colors,
|
12704
|
-
counters = this.chart.counters,
|
12705
|
-
color,
|
12706
|
-
colorIndex;
|
12707
12672
|
|
12708
|
-
|
12673
|
+
getCyclic: function (prop, value, defaults) {
|
12674
|
+
var i,
|
12675
|
+
userOptions = this.userOptions,
|
12676
|
+
indexName = '_' + prop + 'Index',
|
12677
|
+
counterName = prop + 'Counter';
|
12709
12678
|
|
12710
|
-
if (!
|
12711
|
-
if (defined(userOptions
|
12712
|
-
|
12679
|
+
if (!value) {
|
12680
|
+
if (defined(userOptions[indexName])) { // after Series.update()
|
12681
|
+
i = userOptions[indexName];
|
12713
12682
|
} else {
|
12714
|
-
userOptions
|
12715
|
-
|
12683
|
+
userOptions[indexName] = i = this.chart[counterName] % defaults.length;
|
12684
|
+
this.chart[counterName] += 1;
|
12716
12685
|
}
|
12717
|
-
|
12686
|
+
value = defaults[i];
|
12718
12687
|
}
|
12688
|
+
this[prop] = value;
|
12689
|
+
},
|
12719
12690
|
|
12720
|
-
|
12721
|
-
|
12691
|
+
/**
|
12692
|
+
* Get the series' color
|
12693
|
+
*/
|
12694
|
+
getColor: function () {
|
12695
|
+
if (!this.options.colorByPoint) {
|
12696
|
+
this.getCyclic('color', this.options.color || defaultPlotOptions[this.type].color, this.chart.options.colors);
|
12697
|
+
}
|
12722
12698
|
},
|
12723
12699
|
/**
|
12724
12700
|
* Get the series' symbol
|
12725
12701
|
*/
|
12726
12702
|
getSymbol: function () {
|
12727
|
-
var
|
12728
|
-
|
12729
|
-
|
12730
|
-
chart = series.chart,
|
12731
|
-
defaultSymbols = chart.options.symbols,
|
12732
|
-
counters = chart.counters,
|
12733
|
-
symbolIndex;
|
12734
|
-
|
12735
|
-
series.symbol = seriesMarkerOption.symbol;
|
12736
|
-
if (!series.symbol) {
|
12737
|
-
if (defined(userOptions._symbolIndex)) { // after Series.update()
|
12738
|
-
symbolIndex = userOptions._symbolIndex;
|
12739
|
-
} else {
|
12740
|
-
userOptions._symbolIndex = counters.symbol;
|
12741
|
-
symbolIndex = counters.symbol++;
|
12742
|
-
}
|
12743
|
-
series.symbol = defaultSymbols[symbolIndex];
|
12744
|
-
}
|
12703
|
+
var seriesMarkerOption = this.options.marker;
|
12704
|
+
|
12705
|
+
this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols);
|
12745
12706
|
|
12746
12707
|
// don't substract radius in image symbols (#604)
|
12747
|
-
if (/^url/.test(
|
12708
|
+
if (/^url/.test(this.symbol)) {
|
12748
12709
|
seriesMarkerOption.radius = 0;
|
12749
12710
|
}
|
12750
|
-
counters.wrapSymbol(defaultSymbols.length);
|
12751
12711
|
},
|
12752
12712
|
|
12753
12713
|
drawLegendSymbol: LegendSymbolMixin.drawLineMarker,
|
@@ -12909,6 +12869,7 @@ Series.prototype = {
|
|
12909
12869
|
cropThreshold = options.cropThreshold,
|
12910
12870
|
activePointCount = 0,
|
12911
12871
|
isCartesian = series.isCartesian,
|
12872
|
+
xExtremes,
|
12912
12873
|
min,
|
12913
12874
|
max;
|
12914
12875
|
|
@@ -12922,8 +12883,9 @@ Series.prototype = {
|
|
12922
12883
|
// optionally filter out points outside the plot area
|
12923
12884
|
if (isCartesian && series.sorted && (!cropThreshold || dataLength > cropThreshold || series.forceCrop)) {
|
12924
12885
|
|
12925
|
-
|
12926
|
-
|
12886
|
+
xExtremes = xAxis.getExtremes(); // corrected for log axis (#3053)
|
12887
|
+
min = xExtremes.min;
|
12888
|
+
max = xExtremes.max;
|
12927
12889
|
|
12928
12890
|
// it's outside current extremes
|
12929
12891
|
if (processedXData[dataLength - 1] < min || processedXData[0] > max) {
|
@@ -13453,8 +13415,8 @@ Series.prototype = {
|
|
13453
13415
|
if (seriesOptions.marker) { // line, spline, area, areaspline, scatter
|
13454
13416
|
|
13455
13417
|
// if no hover radius is given, default to normal radius + 2
|
13456
|
-
stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius +
|
13457
|
-
stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth +
|
13418
|
+
stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + stateOptionsHover.radiusPlus;
|
13419
|
+
stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + stateOptionsHover.lineWidthPlus;
|
13458
13420
|
|
13459
13421
|
} else { // column, bar, pie
|
13460
13422
|
|
@@ -14432,9 +14394,18 @@ extend(Chart.prototype, {
|
|
14432
14394
|
showLoading: function (str) {
|
14433
14395
|
var chart = this,
|
14434
14396
|
options = chart.options,
|
14435
|
-
loadingDiv = chart.loadingDiv
|
14436
|
-
|
14437
|
-
|
14397
|
+
loadingDiv = chart.loadingDiv,
|
14398
|
+
loadingOptions = options.loading,
|
14399
|
+
setLoadingSize = function () {
|
14400
|
+
if (loadingDiv) {
|
14401
|
+
css(loadingDiv, {
|
14402
|
+
left: chart.plotLeft + PX,
|
14403
|
+
top: chart.plotTop + PX,
|
14404
|
+
width: chart.plotWidth + PX,
|
14405
|
+
height: chart.plotHeight + PX
|
14406
|
+
});
|
14407
|
+
}
|
14408
|
+
};
|
14438
14409
|
|
14439
14410
|
// create the layer at the first call
|
14440
14411
|
if (!loadingDiv) {
|
@@ -14451,7 +14422,7 @@ extend(Chart.prototype, {
|
|
14451
14422
|
loadingOptions.labelStyle,
|
14452
14423
|
loadingDiv
|
14453
14424
|
);
|
14454
|
-
|
14425
|
+
addEvent(chart, 'redraw', setLoadingSize); // #1080
|
14455
14426
|
}
|
14456
14427
|
|
14457
14428
|
// update text
|
@@ -14461,11 +14432,7 @@ extend(Chart.prototype, {
|
|
14461
14432
|
if (!chart.loadingShown) {
|
14462
14433
|
css(loadingDiv, {
|
14463
14434
|
opacity: 0,
|
14464
|
-
display: ''
|
14465
|
-
left: chart.plotLeft + PX,
|
14466
|
-
top: chart.plotTop + PX,
|
14467
|
-
width: chart.plotWidth + PX,
|
14468
|
-
height: chart.plotHeight + PX
|
14435
|
+
display: ''
|
14469
14436
|
});
|
14470
14437
|
animate(loadingDiv, {
|
14471
14438
|
opacity: loadingOptions.style.opacity
|
@@ -14474,6 +14441,7 @@ extend(Chart.prototype, {
|
|
14474
14441
|
});
|
14475
14442
|
chart.loadingShown = true;
|
14476
14443
|
}
|
14444
|
+
setLoadingSize();
|
14477
14445
|
},
|
14478
14446
|
|
14479
14447
|
/**
|
@@ -14742,14 +14710,22 @@ extend(Series.prototype, {
|
|
14742
14710
|
* Update the series with a new set of options
|
14743
14711
|
*/
|
14744
14712
|
update: function (newOptions, redraw) {
|
14745
|
-
var
|
14713
|
+
var series = this,
|
14714
|
+
chart = this.chart,
|
14746
14715
|
// must use user options when changing type because this.options is merged
|
14747
14716
|
// in with type specific plotOptions
|
14748
14717
|
oldOptions = this.userOptions,
|
14749
14718
|
oldType = this.type,
|
14750
14719
|
proto = seriesTypes[oldType].prototype,
|
14720
|
+
preserve = ['group', 'markerGroup', 'dataLabelsGroup'],
|
14751
14721
|
n;
|
14752
14722
|
|
14723
|
+
// Make sure groups are not destroyed (#3094)
|
14724
|
+
each(preserve, function (prop) {
|
14725
|
+
preserve[prop] = series[prop];
|
14726
|
+
delete series[prop];
|
14727
|
+
});
|
14728
|
+
|
14753
14729
|
// Do the merge, with some forced options
|
14754
14730
|
newOptions = merge(oldOptions, {
|
14755
14731
|
animation: false,
|
@@ -14766,8 +14742,14 @@ extend(Series.prototype, {
|
|
14766
14742
|
}
|
14767
14743
|
extend(this, seriesTypes[newOptions.type || oldType].prototype);
|
14768
14744
|
|
14745
|
+
// Re-register groups (#3094)
|
14746
|
+
each(preserve, function (prop) {
|
14747
|
+
series[prop] = preserve[prop];
|
14748
|
+
});
|
14749
|
+
|
14769
14750
|
|
14770
14751
|
this.init(chart, newOptions);
|
14752
|
+
chart.linkSeries(); // Links are lost in this.remove (#3028)
|
14771
14753
|
if (pick(redraw, true)) {
|
14772
14754
|
chart.redraw(false);
|
14773
14755
|
}
|
@@ -14874,7 +14856,8 @@ var AreaSeries = extendClass(Series, {
|
|
14874
14856
|
* in the stack.
|
14875
14857
|
*/
|
14876
14858
|
getSegments: function () {
|
14877
|
-
var
|
14859
|
+
var series = this,
|
14860
|
+
segments = [],
|
14878
14861
|
segment = [],
|
14879
14862
|
keys = [],
|
14880
14863
|
xAxis = this.xAxis,
|
@@ -14885,7 +14868,6 @@ var AreaSeries = extendClass(Series, {
|
|
14885
14868
|
plotY,
|
14886
14869
|
points = this.points,
|
14887
14870
|
connectNulls = this.options.connectNulls,
|
14888
|
-
val,
|
14889
14871
|
i,
|
14890
14872
|
x;
|
14891
14873
|
|
@@ -14906,6 +14888,9 @@ var AreaSeries = extendClass(Series, {
|
|
14906
14888
|
});
|
14907
14889
|
|
14908
14890
|
each(keys, function (x) {
|
14891
|
+
var y = 0,
|
14892
|
+
stackPoint;
|
14893
|
+
|
14909
14894
|
if (connectNulls && (!pointMap[x] || pointMap[x].y === null)) { // #1836
|
14910
14895
|
return;
|
14911
14896
|
|
@@ -14917,9 +14902,19 @@ var AreaSeries = extendClass(Series, {
|
|
14917
14902
|
// insert a dummy point in order for the areas to be drawn
|
14918
14903
|
// correctly.
|
14919
14904
|
} else {
|
14905
|
+
|
14906
|
+
// Loop down the stack to find the series below this one that has
|
14907
|
+
// a value (#1991)
|
14908
|
+
for (i = series.index; i <= yAxis.series.length; i++) {
|
14909
|
+
stackPoint = stack[x].points[i + ',' + x];
|
14910
|
+
if (stackPoint) {
|
14911
|
+
y = stackPoint[1];
|
14912
|
+
break;
|
14913
|
+
}
|
14914
|
+
}
|
14915
|
+
|
14920
14916
|
plotX = xAxis.translate(x);
|
14921
|
-
|
14922
|
-
plotY = yAxis.toPixels(val, true);
|
14917
|
+
plotY = yAxis.toPixels(y, true);
|
14923
14918
|
segment.push({
|
14924
14919
|
y: null,
|
14925
14920
|
plotX: plotX,
|
@@ -15355,7 +15350,7 @@ var ColumnSeries = extendClass(Series, {
|
|
15355
15350
|
minPointLength = pick(options.minPointLength, 5),
|
15356
15351
|
metrics = series.getColumnMetrics(),
|
15357
15352
|
pointWidth = metrics.width,
|
15358
|
-
seriesBarW = series.barW =
|
15353
|
+
seriesBarW = series.barW = mathMax(pointWidth, 1 + 2 * borderWidth), // postprocessed for border width
|
15359
15354
|
pointXOffset = series.pointXOffset = metrics.offset,
|
15360
15355
|
xCrisp = -(borderWidth % 2 ? 0.5 : 0),
|
15361
15356
|
yCrisp = borderWidth % 2 ? 0.5 : 1;
|
@@ -15364,9 +15359,16 @@ var ColumnSeries = extendClass(Series, {
|
|
15364
15359
|
yCrisp += 1;
|
15365
15360
|
}
|
15366
15361
|
|
15362
|
+
// When the pointPadding is 0, we want the columns to be packed tightly, so we allow individual
|
15363
|
+
// columns to have individual sizes. When pointPadding is greater, we strive for equal-width
|
15364
|
+
// columns (#2694).
|
15365
|
+
if (options.pointPadding) {
|
15366
|
+
seriesBarW = mathCeil(seriesBarW);
|
15367
|
+
}
|
15368
|
+
|
15367
15369
|
Series.prototype.translate.apply(series);
|
15368
15370
|
|
15369
|
-
//
|
15371
|
+
// Record the new values
|
15370
15372
|
each(series.points, function (point) {
|
15371
15373
|
var yBottom = pick(point.yBottom, translatedThreshold),
|
15372
15374
|
plotY = mathMin(mathMax(-999 - yBottom, point.plotY), yAxis.len + 999 + yBottom), // Don't draw too far outside plot area (#1303, #2241)
|
@@ -15376,7 +15378,6 @@ var ColumnSeries = extendClass(Series, {
|
|
15376
15378
|
right,
|
15377
15379
|
bottom,
|
15378
15380
|
fromTop,
|
15379
|
-
fromLeft,
|
15380
15381
|
barH = mathMax(plotY, yBottom) - barY;
|
15381
15382
|
|
15382
15383
|
// Handle options.minPointLength
|
@@ -15397,8 +15398,7 @@ var ColumnSeries = extendClass(Series, {
|
|
15397
15398
|
// Fix the tooltip on center of grouped columns (#1216)
|
15398
15399
|
point.tooltipPos = chart.inverted ? [yAxis.len - plotY, series.xAxis.len - barX - barW / 2] : [barX + barW / 2, plotY];
|
15399
15400
|
|
15400
|
-
// Round off to obtain crisp edges
|
15401
|
-
fromLeft = mathAbs(barX) < 0.5;
|
15401
|
+
// Round off to obtain crisp edges and avoid overlapping with neighbours (#2694)
|
15402
15402
|
right = mathRound(barX + barW) + xCrisp;
|
15403
15403
|
barX = mathRound(barX) + xCrisp;
|
15404
15404
|
barW = right - barX;
|
@@ -15408,11 +15408,7 @@ var ColumnSeries = extendClass(Series, {
|
|
15408
15408
|
barY = mathRound(barY) + yCrisp;
|
15409
15409
|
barH = bottom - barY;
|
15410
15410
|
|
15411
|
-
// Top
|
15412
|
-
if (fromLeft) {
|
15413
|
-
barX += 1;
|
15414
|
-
barW -= 1;
|
15415
|
-
}
|
15411
|
+
// Top edges are exceptions
|
15416
15412
|
if (fromTop) {
|
15417
15413
|
barY -= 1;
|
15418
15414
|
barH += 1;
|
@@ -15426,6 +15422,7 @@ var ColumnSeries = extendClass(Series, {
|
|
15426
15422
|
width: barW,
|
15427
15423
|
height: barH
|
15428
15424
|
};
|
15425
|
+
|
15429
15426
|
});
|
15430
15427
|
|
15431
15428
|
},
|
@@ -15455,20 +15452,23 @@ var ColumnSeries = extendClass(Series, {
|
|
15455
15452
|
renderer = chart.renderer,
|
15456
15453
|
animationLimit = options.animationLimit || 250,
|
15457
15454
|
shapeArgs,
|
15458
|
-
pointAttr
|
15459
|
-
borderAttr;
|
15455
|
+
pointAttr;
|
15460
15456
|
|
15461
15457
|
// draw the columns
|
15462
15458
|
each(series.points, function (point) {
|
15463
15459
|
var plotY = point.plotY,
|
15464
|
-
graphic = point.graphic
|
15460
|
+
graphic = point.graphic,
|
15461
|
+
borderAttr;
|
15465
15462
|
|
15466
15463
|
if (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {
|
15467
15464
|
shapeArgs = point.shapeArgs;
|
15465
|
+
|
15468
15466
|
borderAttr = defined(series.borderWidth) ? {
|
15469
15467
|
'stroke-width': series.borderWidth
|
15470
15468
|
} : {};
|
15469
|
+
|
15471
15470
|
pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE] || series.pointAttr[NORMAL_STATE];
|
15471
|
+
|
15472
15472
|
if (graphic) { // update
|
15473
15473
|
stop(graphic);
|
15474
15474
|
graphic.attr(borderAttr)[chart.pointCount < animationLimit ? 'animate' : 'attr'](merge(shapeArgs));
|
@@ -15562,7 +15562,7 @@ seriesTypes.bar = BarSeries;
|
|
15562
15562
|
defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
|
15563
15563
|
lineWidth: 0,
|
15564
15564
|
tooltip: {
|
15565
|
-
headerFormat: '<span style="color:{series.color}">\u25CF</span> <span style="font-size: 10px;"> {series.name}</span><br/>',
|
15565
|
+
headerFormat: '<span style="color:{series.color}">\u25CF</span> <span style="font-size: 10px;"> {series.name}</span><br/>',
|
15566
15566
|
pointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>'
|
15567
15567
|
},
|
15568
15568
|
stickyTracking: false
|
@@ -15576,7 +15576,7 @@ var ScatterSeries = extendClass(Series, {
|
|
15576
15576
|
sorted: false,
|
15577
15577
|
requireSorting: false,
|
15578
15578
|
noSharedTooltip: true,
|
15579
|
-
trackerGroups: ['markerGroup'],
|
15579
|
+
trackerGroups: ['markerGroup', 'dataLabelsGroup'],
|
15580
15580
|
takeOrdinalPosition: false, // #2342
|
15581
15581
|
singularTooltips: true,
|
15582
15582
|
drawGraph: function () {
|
@@ -15604,7 +15604,7 @@ defaultPlotOptions.pie = merge(defaultSeriesOptions, {
|
|
15604
15604
|
// connectorPadding: 5,
|
15605
15605
|
distance: 30,
|
15606
15606
|
enabled: true,
|
15607
|
-
formatter: function () {
|
15607
|
+
formatter: function () { // #2945
|
15608
15608
|
return this.point.name;
|
15609
15609
|
}
|
15610
15610
|
// softConnector: true,
|
@@ -15733,7 +15733,7 @@ var PiePoint = extendClass(Point, {
|
|
15733
15733
|
var shapeArgs = this.shapeArgs,
|
15734
15734
|
chart = this.series.chart;
|
15735
15735
|
|
15736
|
-
return this.series.chart.renderer.symbols.arc(chart.plotLeft + shapeArgs.x, chart.plotTop + shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
|
15736
|
+
return this.sliced || !this.visible ? [] : this.series.chart.renderer.symbols.arc(chart.plotLeft + shapeArgs.x, chart.plotTop + shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
|
15737
15737
|
innerR: this.shapeArgs.r,
|
15738
15738
|
start: shapeArgs.start,
|
15739
15739
|
end: shapeArgs.end
|
@@ -16082,14 +16082,17 @@ Series.prototype.drawDataLabels = function () {
|
|
16082
16082
|
dataLabelsGroup = series.plotGroup(
|
16083
16083
|
'dataLabelsGroup',
|
16084
16084
|
'data-labels',
|
16085
|
-
HIDDEN,
|
16085
|
+
options.defer ? HIDDEN : VISIBLE,
|
16086
16086
|
options.zIndex || 6
|
16087
16087
|
);
|
16088
16088
|
|
16089
16089
|
if (!series.hasRendered && pick(options.defer, true)) {
|
16090
16090
|
dataLabelsGroup.attr({ opacity: 0 });
|
16091
16091
|
addEvent(series, 'afterAnimate', function () {
|
16092
|
-
series.
|
16092
|
+
if (series.visible) { // #3023, #3024
|
16093
|
+
dataLabelsGroup.show();
|
16094
|
+
}
|
16095
|
+
dataLabelsGroup[seriesOptions.animation ? 'animate' : 'attr']({ opacity: 1 }, { duration: 200 });
|
16093
16096
|
});
|
16094
16097
|
}
|
16095
16098
|
|
@@ -16228,12 +16231,13 @@ Series.prototype.alignDataLabel = function (point, dataLabel, options, alignTo,
|
|
16228
16231
|
|
16229
16232
|
// Allow a hook for changing alignment in the last moment, then do the alignment
|
16230
16233
|
if (options.rotation) { // Fancy box alignment isn't supported for rotated text
|
16231
|
-
|
16232
|
-
|
16233
|
-
|
16234
|
-
|
16235
|
-
|
16236
|
-
|
16234
|
+
dataLabel[isNew ? 'attr' : 'animate']({
|
16235
|
+
x: alignTo.x + options.x + alignTo.width / 2,
|
16236
|
+
y: alignTo.y + options.y + alignTo.height / 2
|
16237
|
+
})
|
16238
|
+
.attr({ // #3003
|
16239
|
+
align: options.align
|
16240
|
+
});
|
16237
16241
|
} else {
|
16238
16242
|
dataLabel.align(options, null, alignTo);
|
16239
16243
|
alignAttr = dataLabel.alignAttr;
|
@@ -16375,13 +16379,6 @@ if (seriesTypes.pie) {
|
|
16375
16379
|
}
|
16376
16380
|
});
|
16377
16381
|
|
16378
|
-
// assume equal label heights
|
16379
|
-
i = 0;
|
16380
|
-
while (!labelHeight && data[i]) { // #1569
|
16381
|
-
labelHeight = data[i] && data[i].dataLabel && (data[i].dataLabel.getBBox().height || 21); // 21 is for #968
|
16382
|
-
i++;
|
16383
|
-
}
|
16384
|
-
|
16385
16382
|
/* Loop over the points in each half, starting from the top and bottom
|
16386
16383
|
* of the pie to detect overlapping labels.
|
16387
16384
|
*/
|
@@ -16393,38 +16390,65 @@ if (seriesTypes.pie) {
|
|
16393
16390
|
usedSlots = [],
|
16394
16391
|
points = halves[i],
|
16395
16392
|
pos,
|
16393
|
+
bottom,
|
16396
16394
|
length = points.length,
|
16397
16395
|
slotIndex;
|
16398
16396
|
|
16397
|
+
if (!length) {
|
16398
|
+
continue;
|
16399
|
+
}
|
16400
|
+
|
16399
16401
|
// Sort by angle
|
16400
16402
|
series.sortByAngle(points, i - 0.5);
|
16401
16403
|
|
16404
|
+
// Assume equal label heights on either hemisphere (#2630)
|
16405
|
+
j = labelHeight = 0;
|
16406
|
+
while (!labelHeight && points[j]) { // #1569
|
16407
|
+
labelHeight = points[j] && points[j].dataLabel && (points[j].dataLabel.getBBox().height || 21); // 21 is for #968
|
16408
|
+
j++;
|
16409
|
+
}
|
16410
|
+
|
16402
16411
|
// Only do anti-collision when we are outside the pie and have connectors (#856)
|
16403
16412
|
if (distanceOption > 0) {
|
16404
16413
|
|
16405
|
-
//
|
16406
|
-
|
16414
|
+
// Build the slots
|
16415
|
+
bottom = mathMin(centerY + radius + distanceOption, chart.plotHeight);
|
16416
|
+
for (pos = mathMax(0, centerY - radius - distanceOption); pos <= bottom; pos += labelHeight) {
|
16407
16417
|
slots.push(pos);
|
16418
|
+
}
|
16419
|
+
slotsLength = slots.length;
|
16420
|
+
|
16408
16421
|
|
16409
|
-
|
16410
|
-
|
16422
|
+
/* Visualize the slots
|
16423
|
+
if (!series.slotElements) {
|
16424
|
+
series.slotElements = [];
|
16425
|
+
}
|
16426
|
+
if (i === 1) {
|
16427
|
+
series.slotElements.forEach(function (elem) {
|
16428
|
+
elem.destroy();
|
16429
|
+
});
|
16430
|
+
series.slotElements.length = 0;
|
16431
|
+
}
|
16432
|
+
|
16433
|
+
slots.forEach(function (pos, no) {
|
16411
16434
|
var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0),
|
16412
16435
|
slotY = pos + chart.plotTop;
|
16436
|
+
|
16413
16437
|
if (!isNaN(slotX)) {
|
16414
|
-
chart.renderer.rect(slotX, slotY - 7, 100, labelHeight, 1)
|
16438
|
+
series.slotElements.push(chart.renderer.rect(slotX, slotY - 7, 100, labelHeight, 1)
|
16415
16439
|
.attr({
|
16416
16440
|
'stroke-width': 1,
|
16417
|
-
stroke: 'silver'
|
16441
|
+
stroke: 'silver',
|
16442
|
+
fill: 'rgba(0,0,255,0.1)'
|
16418
16443
|
})
|
16419
|
-
.add();
|
16420
|
-
chart.renderer.text('Slot '+
|
16444
|
+
.add());
|
16445
|
+
series.slotElements.push(chart.renderer.text('Slot '+ no, slotX, slotY + 4)
|
16421
16446
|
.attr({
|
16422
16447
|
fill: 'silver'
|
16423
|
-
}).add();
|
16448
|
+
}).add());
|
16424
16449
|
}
|
16425
|
-
|
16426
|
-
|
16427
|
-
slotsLength = slots.length;
|
16450
|
+
});
|
16451
|
+
// */
|
16428
16452
|
|
16429
16453
|
// if there are more values than available slots, remove lowest values
|
16430
16454
|
if (length > slotsLength) {
|
@@ -16508,7 +16532,7 @@ if (seriesTypes.pie) {
|
|
16508
16532
|
y = slot.y;
|
16509
16533
|
if ((naturalY > y && slots[slotIndex + 1] !== null) ||
|
16510
16534
|
(naturalY < y && slots[slotIndex - 1] !== null)) {
|
16511
|
-
y = naturalY;
|
16535
|
+
y = mathMin(mathMax(0, naturalY), chart.plotHeight);
|
16512
16536
|
}
|
16513
16537
|
|
16514
16538
|
} else {
|
@@ -16519,7 +16543,7 @@ if (seriesTypes.pie) {
|
|
16519
16543
|
// and botton slice connectors from touching each other on either side
|
16520
16544
|
x = options.justify ?
|
16521
16545
|
seriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) :
|
16522
|
-
series.getX(
|
16546
|
+
series.getX(y === centerY - radius - distanceOption || y === centerY + radius + distanceOption ? naturalY : y, i);
|
16523
16547
|
|
16524
16548
|
|
16525
16549
|
// Record the placement and visibility
|
@@ -17192,9 +17216,9 @@ extend(Point.prototype, {
|
|
17192
17216
|
var chart = this.series.chart,
|
17193
17217
|
hoverPoints = chart.hoverPoints;
|
17194
17218
|
|
17195
|
-
|
17196
|
-
this.firePointEvent('mouseOut');
|
17219
|
+
this.firePointEvent('mouseOut');
|
17197
17220
|
|
17221
|
+
if (!hoverPoints || inArray(this, hoverPoints) === -1) { // #887, #2240
|
17198
17222
|
this.setState();
|
17199
17223
|
chart.hoverPoint = null;
|
17200
17224
|
}
|
@@ -17439,7 +17463,7 @@ extend(Series.prototype, {
|
|
17439
17463
|
}
|
17440
17464
|
|
17441
17465
|
if (state) {
|
17442
|
-
lineWidth = stateOptions[state].lineWidth || lineWidth +
|
17466
|
+
lineWidth = stateOptions[state].lineWidth || lineWidth + (stateOptions[state].lineWidthPlus || 0);
|
17443
17467
|
}
|
17444
17468
|
|
17445
17469
|
if (graph && !graph.dashstyle) { // hover is turned off for dashed lines in VML
|