highcharts-rails 2.3.3.1 → 2.3.5
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/CHANGELOG.markdown +4 -0
- data/lib/highcharts/version.rb +1 -1
- data/vendor/assets/javascripts/highcharts.js +677 -507
- data/vendor/assets/javascripts/highcharts/adapters/mootools.js +15 -14
- data/vendor/assets/javascripts/highcharts/adapters/prototype.js +1 -1
- data/vendor/assets/javascripts/highcharts/highcharts-more.js +1581 -35
- data/vendor/assets/javascripts/highcharts/modules/canvas-tools.js +2792 -2792
- data/vendor/assets/javascripts/highcharts/modules/data.js +248 -13
- data/vendor/assets/javascripts/highcharts/modules/exporting.js +75 -59
- metadata +2 -2
data/CHANGELOG.markdown
CHANGED
data/lib/highcharts/version.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
// @compilation_level SIMPLE_OPTIMIZATIONS
|
3
3
|
|
4
4
|
/**
|
5
|
-
* @license Highcharts JS v2.3.
|
5
|
+
* @license Highcharts JS v2.3.5 (2012-12-19)
|
6
6
|
*
|
7
|
-
* (c) 2009-
|
7
|
+
* (c) 2009-2012 Torstein Hønsi
|
8
8
|
*
|
9
9
|
* License: www.highcharts.com/license
|
10
10
|
*/
|
@@ -37,6 +37,7 @@ var UNDEFINED,
|
|
37
37
|
docMode8 = doc.documentMode === 8,
|
38
38
|
isWebKit = /AppleWebKit/.test(userAgent),
|
39
39
|
isFirefox = /Firefox/.test(userAgent),
|
40
|
+
isTouchDevice = /(Mobile|Android|Windows Phone)/.test(userAgent),
|
40
41
|
SVG_NS = 'http://www.w3.org/2000/svg',
|
41
42
|
hasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg').createSVGRect,
|
42
43
|
hasBidiBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4, // issue #38
|
@@ -52,6 +53,7 @@ var UNDEFINED,
|
|
52
53
|
pathAnim,
|
53
54
|
timeUnits,
|
54
55
|
noop = function () {},
|
56
|
+
charts = [],
|
55
57
|
|
56
58
|
// some constants for frequently used strings
|
57
59
|
DIV = 'div',
|
@@ -70,12 +72,13 @@ var UNDEFINED,
|
|
70
72
|
* IE7: 0.002
|
71
73
|
* IE8: 0.002
|
72
74
|
* IE9: 0.00000000001 (unlimited)
|
75
|
+
* IE10: 0.0001 (exporting only)
|
73
76
|
* FF: 0.00000000001 (unlimited)
|
74
77
|
* Chrome: 0.000001
|
75
78
|
* Safari: 0.000001
|
76
79
|
* Opera: 0.00000000001 (unlimited)
|
77
80
|
*/
|
78
|
-
TRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.
|
81
|
+
TRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.0001 : 0.002) + ')', // invisible but clickable
|
79
82
|
//TRACKER_FILL = 'rgba(192,192,192,0.5)',
|
80
83
|
NORMAL_STATE = '',
|
81
84
|
HOVER_STATE = 'hover',
|
@@ -461,7 +464,9 @@ dateFormat = function (format, timestamp, capitalize) {
|
|
461
464
|
|
462
465
|
// do the replaces
|
463
466
|
for (key in replacements) {
|
464
|
-
|
467
|
+
while (format.indexOf('%' + key) !== -1) { // regex would do it in one line, but this is faster
|
468
|
+
format = format.replace('%' + key, replacements[key]);
|
469
|
+
}
|
465
470
|
}
|
466
471
|
|
467
472
|
// Optionally capitalize the string and return
|
@@ -610,91 +615,91 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
|
|
610
615
|
interval = normalizedInterval.unitRange,
|
611
616
|
count = normalizedInterval.count;
|
612
617
|
|
618
|
+
if (defined(min)) { // #1300
|
619
|
+
if (interval >= timeUnits[SECOND]) { // second
|
620
|
+
minDate.setMilliseconds(0);
|
621
|
+
minDate.setSeconds(interval >= timeUnits[MINUTE] ? 0 :
|
622
|
+
count * mathFloor(minDate.getSeconds() / count));
|
623
|
+
}
|
613
624
|
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
625
|
+
if (interval >= timeUnits[MINUTE]) { // minute
|
626
|
+
minDate[setMinutes](interval >= timeUnits[HOUR] ? 0 :
|
627
|
+
count * mathFloor(minDate[getMinutes]() / count));
|
628
|
+
}
|
629
|
+
|
630
|
+
if (interval >= timeUnits[HOUR]) { // hour
|
631
|
+
minDate[setHours](interval >= timeUnits[DAY] ? 0 :
|
632
|
+
count * mathFloor(minDate[getHours]() / count));
|
633
|
+
}
|
634
|
+
|
635
|
+
if (interval >= timeUnits[DAY]) { // day
|
636
|
+
minDate[setDate](interval >= timeUnits[MONTH] ? 1 :
|
637
|
+
count * mathFloor(minDate[getDate]() / count));
|
638
|
+
}
|
639
|
+
|
640
|
+
if (interval >= timeUnits[MONTH]) { // month
|
641
|
+
minDate[setMonth](interval >= timeUnits[YEAR] ? 0 :
|
642
|
+
count * mathFloor(minDate[getMonth]() / count));
|
643
|
+
minYear = minDate[getFullYear]();
|
644
|
+
}
|
645
|
+
|
646
|
+
if (interval >= timeUnits[YEAR]) { // year
|
647
|
+
minYear -= minYear % count;
|
648
|
+
minDate[setFullYear](minYear);
|
649
|
+
}
|
650
|
+
|
651
|
+
// week is a special case that runs outside the hierarchy
|
652
|
+
if (interval === timeUnits[WEEK]) {
|
653
|
+
// get start of current week, independent of count
|
654
|
+
minDate[setDate](minDate[getDate]() - minDate[getDay]() +
|
655
|
+
pick(startOfWeek, 1));
|
656
|
+
}
|
657
|
+
|
658
|
+
|
659
|
+
// get tick positions
|
660
|
+
i = 1;
|
639
661
|
minYear = minDate[getFullYear]();
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
// if the interval is months, use Date.UTC to increase months
|
674
|
-
} else if (interval === timeUnits[MONTH]) {
|
675
|
-
time = makeTime(minYear, minMonth + i * count);
|
676
|
-
|
677
|
-
// if we're using global time, the interval is not fixed as it jumps
|
678
|
-
// one hour at the DST crossover
|
679
|
-
} else if (!useUTC && (interval === timeUnits[DAY] || interval === timeUnits[WEEK])) {
|
680
|
-
time = makeTime(minYear, minMonth, minDateDate +
|
681
|
-
i * count * (interval === timeUnits[DAY] ? 1 : 7));
|
682
|
-
|
683
|
-
// else, the interval is fixed and we use simple addition
|
684
|
-
} else {
|
685
|
-
time += interval * count;
|
686
|
-
|
687
|
-
// mark new days if the time is dividable by day
|
688
|
-
if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset) {
|
689
|
-
higherRanks[time] = DAY;
|
662
|
+
var time = minDate.getTime(),
|
663
|
+
minMonth = minDate[getMonth](),
|
664
|
+
minDateDate = minDate[getDate](),
|
665
|
+
timezoneOffset = useUTC ?
|
666
|
+
0 :
|
667
|
+
(24 * 3600 * 1000 + minDate.getTimezoneOffset() * 60 * 1000) % (24 * 3600 * 1000); // #950
|
668
|
+
|
669
|
+
// iterate and add tick positions at appropriate values
|
670
|
+
while (time < max) {
|
671
|
+
tickPositions.push(time);
|
672
|
+
|
673
|
+
// if the interval is years, use Date.UTC to increase years
|
674
|
+
if (interval === timeUnits[YEAR]) {
|
675
|
+
time = makeTime(minYear + i * count, 0);
|
676
|
+
|
677
|
+
// if the interval is months, use Date.UTC to increase months
|
678
|
+
} else if (interval === timeUnits[MONTH]) {
|
679
|
+
time = makeTime(minYear, minMonth + i * count);
|
680
|
+
|
681
|
+
// if we're using global time, the interval is not fixed as it jumps
|
682
|
+
// one hour at the DST crossover
|
683
|
+
} else if (!useUTC && (interval === timeUnits[DAY] || interval === timeUnits[WEEK])) {
|
684
|
+
time = makeTime(minYear, minMonth, minDateDate +
|
685
|
+
i * count * (interval === timeUnits[DAY] ? 1 : 7));
|
686
|
+
|
687
|
+
// else, the interval is fixed and we use simple addition
|
688
|
+
} else {
|
689
|
+
time += interval * count;
|
690
|
+
|
691
|
+
// mark new days if the time is dividable by day
|
692
|
+
if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset) {
|
693
|
+
higherRanks[time] = DAY;
|
694
|
+
}
|
690
695
|
}
|
696
|
+
|
697
|
+
i++;
|
691
698
|
}
|
692
|
-
|
693
|
-
i++;
|
694
|
-
}
|
695
699
|
|
696
|
-
|
697
|
-
|
700
|
+
// push the last time
|
701
|
+
tickPositions.push(time);
|
702
|
+
}
|
698
703
|
|
699
704
|
// record information on the chosen unit - for dynamic label formatter
|
700
705
|
tickPositions.info = extend(normalizedInterval, {
|
@@ -875,7 +880,7 @@ timeUnits = hash(
|
|
875
880
|
HOUR, 3600000,
|
876
881
|
DAY, 24 * 3600000,
|
877
882
|
WEEK, 7 * 24 * 3600000,
|
878
|
-
MONTH,
|
883
|
+
MONTH, 31 * 24 * 3600000,
|
879
884
|
YEAR, 31556952000
|
880
885
|
);
|
881
886
|
/*jslint white: false*/
|
@@ -1362,8 +1367,8 @@ defaultOptions = {
|
|
1362
1367
|
},
|
1363
1368
|
global: {
|
1364
1369
|
useUTC: true,
|
1365
|
-
canvasToolsURL: 'http://code.highcharts.com/2.3.
|
1366
|
-
VMLRadialGradientURL: 'http://code.highcharts.com/2.3.
|
1370
|
+
canvasToolsURL: 'http://code.highcharts.com/2.3.5/modules/canvas-tools.js',
|
1371
|
+
VMLRadialGradientURL: 'http://code.highcharts.com/2.3.5/gfx/vml-radial-gradient.png'
|
1367
1372
|
},
|
1368
1373
|
chart: {
|
1369
1374
|
//animation: true,
|
@@ -1615,7 +1620,7 @@ defaultOptions = {
|
|
1615
1620
|
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>',
|
1616
1621
|
shadow: true,
|
1617
1622
|
shared: useCanVG,
|
1618
|
-
snap:
|
1623
|
+
snap: isTouchDevice ? 25 : 10,
|
1619
1624
|
style: {
|
1620
1625
|
color: '#333333',
|
1621
1626
|
fontSize: '12px',
|
@@ -2021,8 +2026,8 @@ SVGElement.prototype = {
|
|
2021
2026
|
key = 'stroke-width';
|
2022
2027
|
}
|
2023
2028
|
|
2024
|
-
// Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461)
|
2025
|
-
if (
|
2029
|
+
// Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461), #1369
|
2030
|
+
if (key === 'stroke-width' && value === 0 && (isWebKit || renderer.forExport)) {
|
2026
2031
|
value = 0.000001;
|
2027
2032
|
}
|
2028
2033
|
|
@@ -2213,17 +2218,15 @@ SVGElement.prototype = {
|
|
2213
2218
|
* @param {Function} handler
|
2214
2219
|
*/
|
2215
2220
|
on: function (eventType, handler) {
|
2216
|
-
var fn = handler;
|
2217
2221
|
// touch
|
2218
2222
|
if (hasTouch && eventType === 'click') {
|
2219
|
-
|
2220
|
-
fn = function (e) {
|
2223
|
+
this.element.ontouchstart = function (e) {
|
2221
2224
|
e.preventDefault();
|
2222
2225
|
handler();
|
2223
2226
|
};
|
2224
2227
|
}
|
2225
2228
|
// simplest possible event model for internal use
|
2226
|
-
this.element['on' + eventType] =
|
2229
|
+
this.element['on' + eventType] = handler;
|
2227
2230
|
return this;
|
2228
2231
|
},
|
2229
2232
|
|
@@ -2404,7 +2407,7 @@ SVGElement.prototype = {
|
|
2404
2407
|
height = pick(wrapper.elemHeight, elem.offsetHeight);
|
2405
2408
|
|
2406
2409
|
// update textWidth
|
2407
|
-
if (width > textWidth && /[ \-]/.test(elem.innerText)) { // #983
|
2410
|
+
if (width > textWidth && /[ \-]/.test(elem.textContent || elem.innerText)) { // #983, #1254
|
2408
2411
|
css(elem, {
|
2409
2412
|
width: textWidth + PX,
|
2410
2413
|
display: 'block',
|
@@ -2444,6 +2447,11 @@ SVGElement.prototype = {
|
|
2444
2447
|
left: (x + xCorr) + PX,
|
2445
2448
|
top: (y + yCorr) + PX
|
2446
2449
|
});
|
2450
|
+
|
2451
|
+
// force reflow in webkit to apply the left and top on useHTML element (#1249)
|
2452
|
+
if (isWebKit) {
|
2453
|
+
height = elem.offsetHeight; // assigned to height for JSLint purpose
|
2454
|
+
}
|
2447
2455
|
|
2448
2456
|
// record current text transform
|
2449
2457
|
wrapper.cTT = currentTextTransform;
|
@@ -2563,7 +2571,7 @@ SVGElement.prototype = {
|
|
2563
2571
|
element = wrapper.element,
|
2564
2572
|
styles = wrapper.styles,
|
2565
2573
|
rad = rotation * deg2rad;
|
2566
|
-
|
2574
|
+
|
2567
2575
|
if (!bBox) {
|
2568
2576
|
// SVG elements
|
2569
2577
|
if (element.namespaceURI === SVG_NS || renderer.forExport) {
|
@@ -2599,7 +2607,12 @@ SVGElement.prototype = {
|
|
2599
2607
|
if (renderer.isSVG) {
|
2600
2608
|
width = bBox.width;
|
2601
2609
|
height = bBox.height;
|
2602
|
-
|
2610
|
+
|
2611
|
+
// Workaround for wrong bounding box in IE9 and IE10 (#1101)
|
2612
|
+
if (isIE && styles && styles.fontSize === '11px' && height === 22.700000762939453) {
|
2613
|
+
bBox.height = height = 14;
|
2614
|
+
}
|
2615
|
+
|
2603
2616
|
// Adjust for rotated text
|
2604
2617
|
if (rotation) {
|
2605
2618
|
bBox.width = mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad));
|
@@ -2607,11 +2620,6 @@ SVGElement.prototype = {
|
|
2607
2620
|
}
|
2608
2621
|
}
|
2609
2622
|
|
2610
|
-
// Workaround for wrong bounding box in IE9 and IE10 (#1101)
|
2611
|
-
if (isIE && styles && styles.fontSize === '11px' && height === 22.700000762939453) {
|
2612
|
-
bBox.height = 14;
|
2613
|
-
}
|
2614
|
-
|
2615
2623
|
wrapper.bBox = bBox;
|
2616
2624
|
}
|
2617
2625
|
return bBox;
|
@@ -3430,6 +3438,7 @@ SVGRenderer.prototype = {
|
|
3430
3438
|
options
|
3431
3439
|
),
|
3432
3440
|
|
3441
|
+
imageElement,
|
3433
3442
|
imageRegex = /^url\((.*?)\)$/,
|
3434
3443
|
imageSrc,
|
3435
3444
|
imageSize,
|
@@ -3456,23 +3465,25 @@ SVGRenderer.prototype = {
|
|
3456
3465
|
|
3457
3466
|
// On image load, set the size and position
|
3458
3467
|
centerImage = function (img, size) {
|
3459
|
-
img.
|
3460
|
-
|
3461
|
-
|
3462
|
-
|
3468
|
+
if (img.element) { // it may be destroyed in the meantime (#1390)
|
3469
|
+
img.attr({
|
3470
|
+
width: size[0],
|
3471
|
+
height: size[1]
|
3472
|
+
});
|
3463
3473
|
|
3464
|
-
|
3465
|
-
|
3466
|
-
|
3467
|
-
|
3468
|
-
|
3474
|
+
if (!img.alignByTranslate) { // #185
|
3475
|
+
img.translate(
|
3476
|
+
mathRound((width - size[0]) / 2), // #1378
|
3477
|
+
mathRound((height - size[1]) / 2)
|
3478
|
+
);
|
3479
|
+
}
|
3469
3480
|
}
|
3470
3481
|
};
|
3471
3482
|
|
3472
3483
|
imageSrc = symbol.match(imageRegex)[1];
|
3473
3484
|
imageSize = symbolSizes[imageSrc];
|
3474
3485
|
|
3475
|
-
//
|
3486
|
+
// Ireate the image synchronously, add attribs async
|
3476
3487
|
obj = this.image(imageSrc)
|
3477
3488
|
.attr({
|
3478
3489
|
x: x,
|
@@ -3482,15 +3493,15 @@ SVGRenderer.prototype = {
|
|
3482
3493
|
if (imageSize) {
|
3483
3494
|
centerImage(obj, imageSize);
|
3484
3495
|
} else {
|
3485
|
-
//
|
3496
|
+
// Initialize image to be 0 size so export will still function if there's no cached sizes.
|
3497
|
+
//
|
3486
3498
|
obj.attr({ width: 0, height: 0 });
|
3487
3499
|
|
3488
|
-
//
|
3489
|
-
|
3500
|
+
// Create a dummy JavaScript image to get the width and height. Due to a bug in IE < 8,
|
3501
|
+
// the created element must be assigned to a variable in order to load (#292).
|
3502
|
+
imageElement = createElement('img', {
|
3490
3503
|
onload: function () {
|
3491
|
-
|
3492
|
-
|
3493
|
-
centerImage(obj, symbolSizes[imageSrc] = [img.width, img.height]);
|
3504
|
+
centerImage(obj, symbolSizes[imageSrc] = [this.width, this.height]);
|
3494
3505
|
},
|
3495
3506
|
src: imageSrc
|
3496
3507
|
});
|
@@ -3629,7 +3640,17 @@ SVGRenderer.prototype = {
|
|
3629
3640
|
var renderer = this,
|
3630
3641
|
colorObject,
|
3631
3642
|
regexRgba = /^rgba/,
|
3632
|
-
gradName
|
3643
|
+
gradName,
|
3644
|
+
gradAttr,
|
3645
|
+
gradients,
|
3646
|
+
gradientObject,
|
3647
|
+
stops,
|
3648
|
+
stopColor,
|
3649
|
+
stopOpacity,
|
3650
|
+
radialReference,
|
3651
|
+
n,
|
3652
|
+
id,
|
3653
|
+
key = [];
|
3633
3654
|
|
3634
3655
|
// Apply linear or radial gradients
|
3635
3656
|
if (color && color.linearGradient) {
|
@@ -3639,47 +3660,59 @@ SVGRenderer.prototype = {
|
|
3639
3660
|
}
|
3640
3661
|
|
3641
3662
|
if (gradName) {
|
3642
|
-
|
3643
|
-
|
3644
|
-
|
3645
|
-
|
3646
|
-
stopOpacity,
|
3647
|
-
radialReference = elem.radialReference;
|
3663
|
+
gradAttr = color[gradName];
|
3664
|
+
gradients = renderer.gradients;
|
3665
|
+
stops = color.stops;
|
3666
|
+
radialReference = elem.radialReference;
|
3648
3667
|
|
3649
|
-
//
|
3650
|
-
if (
|
3651
|
-
|
3652
|
-
|
3653
|
-
|
3654
|
-
|
3655
|
-
|
3656
|
-
|
3657
|
-
|
3658
|
-
|
3659
|
-
|
3660
|
-
|
3668
|
+
// Keep < 2.2 kompatibility
|
3669
|
+
if (isArray(gradAttr)) {
|
3670
|
+
color[gradName] = gradAttr = {
|
3671
|
+
x1: gradAttr[0],
|
3672
|
+
y1: gradAttr[1],
|
3673
|
+
x2: gradAttr[2],
|
3674
|
+
y2: gradAttr[3],
|
3675
|
+
gradientUnits: 'userSpaceOnUse'
|
3676
|
+
};
|
3677
|
+
}
|
3678
|
+
|
3679
|
+
// Correct the radial gradient for the radial reference system
|
3680
|
+
if (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) {
|
3681
|
+
extend(gradAttr, {
|
3682
|
+
cx: (radialReference[0] - radialReference[2] / 2) + gradAttr.cx * radialReference[2],
|
3683
|
+
cy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2],
|
3684
|
+
r: gradAttr.r * radialReference[2],
|
3685
|
+
gradientUnits: 'userSpaceOnUse'
|
3686
|
+
});
|
3687
|
+
}
|
3688
|
+
|
3689
|
+
// Build the unique key to detect whether we need to create a new element (#1282)
|
3690
|
+
for (n in gradAttr) {
|
3691
|
+
if (n !== 'id') {
|
3692
|
+
key.push(n, gradAttr[n]);
|
3661
3693
|
}
|
3694
|
+
}
|
3695
|
+
for (n in stops) {
|
3696
|
+
key.push(stops[n]);
|
3697
|
+
}
|
3698
|
+
key = key.join(',');
|
3699
|
+
|
3700
|
+
// Check if a gradient object with the same config object is created within this renderer
|
3701
|
+
if (gradients[key]) {
|
3702
|
+
id = gradients[key].id;
|
3662
3703
|
|
3663
|
-
|
3664
|
-
if (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) {
|
3665
|
-
extend(gradAttr, {
|
3666
|
-
cx: (radialReference[0] - radialReference[2] / 2) + gradAttr.cx * radialReference[2],
|
3667
|
-
cy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2],
|
3668
|
-
r: gradAttr.r * radialReference[2],
|
3669
|
-
gradientUnits: 'userSpaceOnUse'
|
3670
|
-
});
|
3671
|
-
}
|
3704
|
+
} else {
|
3672
3705
|
|
3673
3706
|
// Set the id and create the element
|
3674
|
-
gradAttr.id = PREFIX + idCounter++;
|
3675
|
-
gradients[
|
3707
|
+
gradAttr.id = id = PREFIX + idCounter++;
|
3708
|
+
gradients[key] = gradientObject = renderer.createElement(gradName)
|
3676
3709
|
.attr(gradAttr)
|
3677
3710
|
.add(renderer.defs);
|
3678
3711
|
|
3679
3712
|
|
3680
3713
|
// The gradient needs to keep a list of stops to be able to destroy them
|
3681
3714
|
gradientObject.stops = [];
|
3682
|
-
each(
|
3715
|
+
each(stops, function (stop) {
|
3683
3716
|
var stopObject;
|
3684
3717
|
if (regexRgba.test(stop[1])) {
|
3685
3718
|
colorObject = Color(stop[1]);
|
@@ -3701,7 +3734,7 @@ SVGRenderer.prototype = {
|
|
3701
3734
|
}
|
3702
3735
|
|
3703
3736
|
// Return the reference to the gradient object
|
3704
|
-
return 'url(' + renderer.url + '#' +
|
3737
|
+
return 'url(' + renderer.url + '#' + id + ')';
|
3705
3738
|
|
3706
3739
|
// Webkit and Batik can't show rgba.
|
3707
3740
|
} else if (regexRgba.test(color)) {
|
@@ -3943,7 +3976,8 @@ SVGRenderer.prototype = {
|
|
3943
3976
|
crispAdjust = 0,
|
3944
3977
|
deferredAttr = {},
|
3945
3978
|
baselineOffset,
|
3946
|
-
attrSetters = wrapper.attrSetters
|
3979
|
+
attrSetters = wrapper.attrSetters,
|
3980
|
+
needsBox;
|
3947
3981
|
|
3948
3982
|
/**
|
3949
3983
|
* This function runs after the label is added to the DOM (when the bounding box is
|
@@ -3961,24 +3995,26 @@ SVGRenderer.prototype = {
|
|
3961
3995
|
|
3962
3996
|
// update the label-scoped y offset
|
3963
3997
|
baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b;
|
3964
|
-
|
3965
|
-
|
3966
|
-
|
3967
|
-
|
3968
|
-
|
3969
|
-
|
3970
|
-
|
3971
|
-
|
3972
|
-
|
3973
|
-
|
3998
|
+
|
3999
|
+
if (needsBox) {
|
4000
|
+
|
4001
|
+
// create the border box if it is not already present
|
4002
|
+
if (!box) {
|
4003
|
+
boxY = baseline ? -baselineOffset : 0;
|
4004
|
+
|
4005
|
+
wrapper.box = box = shape ?
|
4006
|
+
renderer.symbol(shape, -alignFactor * padding, boxY, wrapper.width, wrapper.height) :
|
4007
|
+
renderer.rect(-alignFactor * padding, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);
|
4008
|
+
box.add(wrapper);
|
4009
|
+
}
|
4010
|
+
|
4011
|
+
// apply the box attributes
|
4012
|
+
box.attr(merge({
|
4013
|
+
width: wrapper.width,
|
4014
|
+
height: wrapper.height
|
4015
|
+
}, deferredAttr));
|
4016
|
+
deferredAttr = null;
|
3974
4017
|
}
|
3975
|
-
|
3976
|
-
// apply the box attributes
|
3977
|
-
box.attr(merge({
|
3978
|
-
width: wrapper.width,
|
3979
|
-
height: wrapper.height
|
3980
|
-
}, deferredAttr));
|
3981
|
-
deferredAttr = null;
|
3982
4018
|
}
|
3983
4019
|
|
3984
4020
|
/**
|
@@ -4032,7 +4068,7 @@ SVGRenderer.prototype = {
|
|
4032
4068
|
y: y
|
4033
4069
|
});
|
4034
4070
|
|
4035
|
-
if (defined(anchorX)) {
|
4071
|
+
if (box && defined(anchorX)) {
|
4036
4072
|
wrapper.attr({
|
4037
4073
|
anchorX: anchorX,
|
4038
4074
|
anchorY: anchorY
|
@@ -4084,11 +4120,15 @@ SVGRenderer.prototype = {
|
|
4084
4120
|
|
4085
4121
|
// apply these to the box but not to the text
|
4086
4122
|
attrSetters[STROKE_WIDTH] = function (value, key) {
|
4123
|
+
needsBox = true;
|
4087
4124
|
crispAdjust = value % 2 / 2;
|
4088
4125
|
boxAttr(key, value);
|
4089
4126
|
return false;
|
4090
4127
|
};
|
4091
4128
|
attrSetters.stroke = attrSetters.fill = attrSetters.r = function (value, key) {
|
4129
|
+
if (key === 'fill') {
|
4130
|
+
needsBox = true;
|
4131
|
+
}
|
4092
4132
|
boxAttr(key, value);
|
4093
4133
|
return false;
|
4094
4134
|
};
|
@@ -4142,13 +4182,20 @@ SVGRenderer.prototype = {
|
|
4142
4182
|
* Return the bounding box of the box, not the group
|
4143
4183
|
*/
|
4144
4184
|
getBBox: function () {
|
4145
|
-
return
|
4185
|
+
return {
|
4186
|
+
width: bBox.width + 2 * padding,
|
4187
|
+
height: bBox.height + 2 * padding,
|
4188
|
+
x: bBox.x - padding,
|
4189
|
+
y: bBox.y - padding
|
4190
|
+
};
|
4146
4191
|
},
|
4147
4192
|
/**
|
4148
4193
|
* Apply the shadow to the box
|
4149
4194
|
*/
|
4150
4195
|
shadow: function (b) {
|
4151
|
-
box
|
4196
|
+
if (box) {
|
4197
|
+
box.shadow(b);
|
4198
|
+
}
|
4152
4199
|
return wrapper;
|
4153
4200
|
},
|
4154
4201
|
/**
|
@@ -4169,6 +4216,9 @@ SVGRenderer.prototype = {
|
|
4169
4216
|
}
|
4170
4217
|
// Call base implementation to destroy the rest
|
4171
4218
|
SVGElement.prototype.destroy.call(wrapper);
|
4219
|
+
|
4220
|
+
// Release local pointers (#1298)
|
4221
|
+
wrapper = renderer = updateBoxSize = updateTextPadding = boxAttr = getSizeAfterAdd = null;
|
4172
4222
|
}
|
4173
4223
|
});
|
4174
4224
|
}
|
@@ -4459,7 +4509,7 @@ var VMLElement = {
|
|
4459
4509
|
|
4460
4510
|
if (nodeName === 'SPAN') { // text color
|
4461
4511
|
elemStyle.color = value;
|
4462
|
-
} else {
|
4512
|
+
} else if (nodeName !== 'IMG') { // #1336
|
4463
4513
|
element.filled = value !== NONE ? true : false;
|
4464
4514
|
|
4465
4515
|
value = renderer.color(value, element, key, wrapper);
|
@@ -4516,6 +4566,7 @@ var VMLElement = {
|
|
4516
4566
|
|
4517
4567
|
if (clipRect) {
|
4518
4568
|
clipMembers = clipRect.members;
|
4569
|
+
erase(clipMembers, wrapper); // Ensure unique list of elements (#1258)
|
4519
4570
|
clipMembers.push(wrapper);
|
4520
4571
|
wrapper.destroyClip = function () {
|
4521
4572
|
erase(clipMembers, wrapper);
|
@@ -5722,10 +5773,9 @@ Tick.prototype = {
|
|
5722
5773
|
// Set the new position, and show or hide
|
5723
5774
|
if (show) {
|
5724
5775
|
label[tick.isNew ? 'attr' : 'animate'](xy);
|
5725
|
-
label.show();
|
5726
5776
|
tick.isNew = false;
|
5727
5777
|
} else {
|
5728
|
-
label.
|
5778
|
+
label.attr('y', -9999); // #1338
|
5729
5779
|
}
|
5730
5780
|
}
|
5731
5781
|
},
|
@@ -6543,11 +6593,14 @@ Axis.prototype = {
|
|
6543
6593
|
pointStack = isNegative ? negPointStack : posPointStack;
|
6544
6594
|
key = isNegative ? negKey : stackKey;
|
6545
6595
|
|
6546
|
-
y
|
6547
|
-
|
6548
|
-
|
6549
|
-
|
6596
|
+
// Set the stack value and y for extremes
|
6597
|
+
if (defined(pointStack[x])) { // we're adding to the stack
|
6598
|
+
pointStack[x] = correctFloat(pointStack[x] + y);
|
6599
|
+
y = [y, pointStack[x]]; // consider both the actual value and the stack (#1376)
|
6550
6600
|
|
6601
|
+
} else { // it's the first point in the stack
|
6602
|
+
pointStack[x] = y;
|
6603
|
+
}
|
6551
6604
|
|
6552
6605
|
// add the series
|
6553
6606
|
if (!stacks[key]) {
|
@@ -6559,7 +6612,7 @@ Axis.prototype = {
|
|
6559
6612
|
if (!stacks[key][x]) {
|
6560
6613
|
stacks[key][x] = new StackItem(axis, axis.options.stackLabels, isNegative, x, stackOption, stacking);
|
6561
6614
|
}
|
6562
|
-
stacks[key][x].setTotal(
|
6615
|
+
stacks[key][x].setTotal(pointStack[x]);
|
6563
6616
|
}
|
6564
6617
|
|
6565
6618
|
// Handle non null values
|
@@ -6588,12 +6641,6 @@ Axis.prototype = {
|
|
6588
6641
|
}
|
6589
6642
|
}
|
6590
6643
|
|
6591
|
-
// record the least unit distance
|
6592
|
-
/*if (findPointRange) {
|
6593
|
-
series.pointRange = pointRange || 1;
|
6594
|
-
}
|
6595
|
-
series.closestPointRange = pointRange;*/
|
6596
|
-
|
6597
6644
|
// Get the dataMin and dataMax so far. If percentage is used, the min and max are
|
6598
6645
|
// always 0 and 100. If the length of activeYData is 0, continue with null values.
|
6599
6646
|
if (!axis.usePercentage && activeYData.length) {
|
@@ -6871,6 +6918,7 @@ Axis.prototype = {
|
|
6871
6918
|
*/
|
6872
6919
|
getMinorTickPositions: function () {
|
6873
6920
|
var axis = this,
|
6921
|
+
options = axis.options,
|
6874
6922
|
tickPositions = axis.tickPositions,
|
6875
6923
|
minorTickInterval = axis.minorTickInterval;
|
6876
6924
|
|
@@ -6886,13 +6934,20 @@ Axis.prototype = {
|
|
6886
6934
|
axis.getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true)
|
6887
6935
|
);
|
6888
6936
|
}
|
6889
|
-
|
6937
|
+
} else if (axis.isDatetimeAxis && options.minorTickInterval === 'auto') { // #1314
|
6938
|
+
minorTickPositions = minorTickPositions.concat(
|
6939
|
+
getTimeTicks(
|
6940
|
+
normalizeTimeTickInterval(minorTickInterval),
|
6941
|
+
axis.min,
|
6942
|
+
axis.max,
|
6943
|
+
options.startOfWeek
|
6944
|
+
)
|
6945
|
+
);
|
6890
6946
|
} else {
|
6891
6947
|
for (pos = axis.min + (tickPositions[0] - axis.min) % minorTickInterval; pos <= axis.max; pos += minorTickInterval) {
|
6892
6948
|
minorTickPositions.push(pos);
|
6893
6949
|
}
|
6894
6950
|
}
|
6895
|
-
|
6896
6951
|
return minorTickPositions;
|
6897
6952
|
},
|
6898
6953
|
|
@@ -7036,7 +7091,7 @@ Axis.prototype = {
|
|
7036
7091
|
// is some other value
|
7037
7092
|
axis.closestPointRange = closestPointRange;
|
7038
7093
|
}
|
7039
|
-
|
7094
|
+
|
7040
7095
|
// secondary values
|
7041
7096
|
axis.oldTransA = transA;
|
7042
7097
|
//axis.translationSlope = axis.transA = transA = axis.len / ((range + (2 * minPointOffset)) || 1);
|
@@ -7102,15 +7157,18 @@ Axis.prototype = {
|
|
7102
7157
|
|
7103
7158
|
// adjust min and max for the minimum range
|
7104
7159
|
axis.adjustForMinRange();
|
7105
|
-
|
7106
|
-
//
|
7160
|
+
|
7161
|
+
// Pad the values to get clear of the chart's edges. To avoid tickInterval taking the padding
|
7162
|
+
// into account, we do this after computing tick interval (#1337).
|
7107
7163
|
if (!categories && !axis.usePercentage && !isLinked && defined(axis.min) && defined(axis.max)) {
|
7108
|
-
length =
|
7109
|
-
if (
|
7110
|
-
|
7111
|
-
|
7112
|
-
|
7113
|
-
|
7164
|
+
length = axis.max - axis.min;
|
7165
|
+
if (length) {
|
7166
|
+
if (!defined(options.min) && !defined(axis.userMin) && minPadding && (axis.dataMin < 0 || !axis.ignoreMinPadding)) {
|
7167
|
+
axis.min -= length * minPadding;
|
7168
|
+
}
|
7169
|
+
if (!defined(options.max) && !defined(axis.userMax) && maxPadding && (axis.dataMax > 0 || !axis.ignoreMaxPadding)) {
|
7170
|
+
axis.max += length * maxPadding;
|
7171
|
+
}
|
7114
7172
|
}
|
7115
7173
|
}
|
7116
7174
|
|
@@ -7193,7 +7251,8 @@ Axis.prototype = {
|
|
7193
7251
|
// reset min/max or remove extremes based on start/end on tick
|
7194
7252
|
var roundedMin = tickPositions[0],
|
7195
7253
|
roundedMax = tickPositions[tickPositions.length - 1],
|
7196
|
-
minPointOffset = axis.minPointOffset || 0
|
7254
|
+
minPointOffset = axis.minPointOffset || 0,
|
7255
|
+
singlePad;
|
7197
7256
|
|
7198
7257
|
if (options.startOnTick) {
|
7199
7258
|
axis.min = roundedMin;
|
@@ -7207,6 +7266,14 @@ Axis.prototype = {
|
|
7207
7266
|
tickPositions.pop();
|
7208
7267
|
}
|
7209
7268
|
|
7269
|
+
// When there is only one point, or all points have the same value on this axis, then min
|
7270
|
+
// and max are equal and tickPositions.length is 1. In this case, add some padding
|
7271
|
+
// in order to center the point, but leave it with one tick. #1337.
|
7272
|
+
if (tickPositions.length === 1) {
|
7273
|
+
singlePad = 1e-9; // The lowest possible number to avoid extra padding on columns
|
7274
|
+
axis.min -= singlePad;
|
7275
|
+
axis.max += singlePad;
|
7276
|
+
}
|
7210
7277
|
}
|
7211
7278
|
},
|
7212
7279
|
|
@@ -7694,28 +7761,30 @@ Axis.prototype = {
|
|
7694
7761
|
|
7695
7762
|
// Major ticks. Pull out the first item and render it last so that
|
7696
7763
|
// we can get the position of the neighbour label. #808.
|
7697
|
-
|
7698
|
-
|
7699
|
-
|
7700
|
-
|
7701
|
-
|
7702
|
-
|
7703
|
-
|
7704
|
-
|
7705
|
-
|
7706
|
-
ticks[pos]
|
7707
|
-
|
7708
|
-
|
7709
|
-
|
7710
|
-
|
7711
|
-
ticks[pos].
|
7764
|
+
if (tickPositions.length) { // #1300
|
7765
|
+
each(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) {
|
7766
|
+
|
7767
|
+
// Reorganize the indices
|
7768
|
+
i = (i === tickPositions.length - 1) ? 0 : i + 1;
|
7769
|
+
|
7770
|
+
// linked axes need an extra check to find out if
|
7771
|
+
if (!isLinked || (pos >= axis.min && pos <= axis.max)) {
|
7772
|
+
|
7773
|
+
if (!ticks[pos]) {
|
7774
|
+
ticks[pos] = new Tick(axis, pos);
|
7775
|
+
}
|
7776
|
+
|
7777
|
+
// render new ticks in old position
|
7778
|
+
if (slideInTicks && ticks[pos].isNew) {
|
7779
|
+
ticks[pos].render(i, true);
|
7780
|
+
}
|
7781
|
+
|
7782
|
+
ticks[pos].isActive = true;
|
7783
|
+
ticks[pos].render(i);
|
7712
7784
|
}
|
7713
|
-
|
7714
|
-
|
7715
|
-
|
7716
|
-
}
|
7717
|
-
|
7718
|
-
});
|
7785
|
+
|
7786
|
+
});
|
7787
|
+
}
|
7719
7788
|
|
7720
7789
|
// alternate grid color
|
7721
7790
|
if (alternateGridColor) {
|
@@ -8494,7 +8563,7 @@ MouseTracker.prototype = {
|
|
8494
8563
|
for (j = 0; j < i; j++) {
|
8495
8564
|
if (series[j].visible &&
|
8496
8565
|
series[j].options.enableMouseTracking !== false &&
|
8497
|
-
!series[j].noSharedTooltip && series[j].tooltipPoints.length) {
|
8566
|
+
!series[j].noSharedTooltip && series[j].tooltipPoints && series[j].tooltipPoints.length) {
|
8498
8567
|
point = series[j].tooltipPoints[index];
|
8499
8568
|
point._dist = mathAbs(index - point[series[j].xAxis.tooltipPosName || 'plotX']);
|
8500
8569
|
distance = mathMin(distance, point._dist);
|
@@ -8657,7 +8726,10 @@ MouseTracker.prototype = {
|
|
8657
8726
|
chart.mouseIsDown = hasDragged = false;
|
8658
8727
|
}
|
8659
8728
|
|
8660
|
-
removeEvent(doc,
|
8729
|
+
removeEvent(doc, 'mouseup', drop);
|
8730
|
+
if (hasTouch) {
|
8731
|
+
removeEvent(doc, 'touchend', drop);
|
8732
|
+
}
|
8661
8733
|
}
|
8662
8734
|
|
8663
8735
|
/**
|
@@ -8692,7 +8764,7 @@ MouseTracker.prototype = {
|
|
8692
8764
|
e = mouseTracker.normalizeMouseEvent(e);
|
8693
8765
|
|
8694
8766
|
// issue #295, dragging not always working in Firefox
|
8695
|
-
if (
|
8767
|
+
if (e.type.indexOf('touch') === -1 && e.preventDefault) {
|
8696
8768
|
e.preventDefault();
|
8697
8769
|
}
|
8698
8770
|
|
@@ -8702,11 +8774,15 @@ MouseTracker.prototype = {
|
|
8702
8774
|
chart.mouseDownX = mouseTracker.mouseDownX = e.chartX;
|
8703
8775
|
mouseTracker.mouseDownY = e.chartY;
|
8704
8776
|
|
8705
|
-
addEvent(doc,
|
8777
|
+
addEvent(doc, 'mouseup', drop);
|
8778
|
+
if (hasTouch) {
|
8779
|
+
addEvent(doc, 'touchend', drop);
|
8780
|
+
}
|
8706
8781
|
};
|
8707
8782
|
|
8708
8783
|
// The mousemove, touchmove and touchstart event handler
|
8709
8784
|
var mouseMove = function (e) {
|
8785
|
+
|
8710
8786
|
// let the system handle multitouch operations like two finger scroll
|
8711
8787
|
// and pinching
|
8712
8788
|
if (e && e.touches && e.touches.length > 1) {
|
@@ -8715,16 +8791,19 @@ MouseTracker.prototype = {
|
|
8715
8791
|
|
8716
8792
|
// normalize
|
8717
8793
|
e = mouseTracker.normalizeMouseEvent(e);
|
8718
|
-
if (!hasTouch) { // not for touch devices
|
8719
|
-
e.returnValue = false;
|
8720
|
-
}
|
8721
8794
|
|
8722
|
-
var
|
8795
|
+
var type = e.type,
|
8796
|
+
chartX = e.chartX,
|
8723
8797
|
chartY = e.chartY,
|
8724
8798
|
isOutsidePlot = !chart.isInsidePlot(chartX - chart.plotLeft, chartY - chart.plotTop);
|
8799
|
+
|
8800
|
+
|
8801
|
+
if (type.indexOf('touch') === -1) { // not for touch actions
|
8802
|
+
e.returnValue = false;
|
8803
|
+
}
|
8725
8804
|
|
8726
8805
|
// on touch devices, only trigger click if a handler is defined
|
8727
|
-
if (
|
8806
|
+
if (type === 'touchstart') {
|
8728
8807
|
if (attr(e.target, 'isTracker')) {
|
8729
8808
|
if (!chart.runTrackerClick) {
|
8730
8809
|
e.preventDefault();
|
@@ -8757,7 +8836,7 @@ MouseTracker.prototype = {
|
|
8757
8836
|
}
|
8758
8837
|
}
|
8759
8838
|
|
8760
|
-
if (chart.mouseIsDown &&
|
8839
|
+
if (chart.mouseIsDown && type !== 'touchstart') { // make selection
|
8761
8840
|
|
8762
8841
|
// determine if the mouse has moved more than 10px
|
8763
8842
|
hasDragged = Math.sqrt(
|
@@ -8821,10 +8900,10 @@ MouseTracker.prototype = {
|
|
8821
8900
|
return isOutsidePlot || !chart.hasCartesianSeries;
|
8822
8901
|
};
|
8823
8902
|
|
8824
|
-
|
8825
|
-
|
8826
|
-
|
8827
|
-
|
8903
|
+
// When the mouse enters the container, run mouseMove
|
8904
|
+
if (!/Android 4\.0/.test(userAgent)) { // This hurts. Best effort for #1385.
|
8905
|
+
container.onmousemove = mouseMove;
|
8906
|
+
}
|
8828
8907
|
|
8829
8908
|
/*
|
8830
8909
|
* When the mouse leaves the container, hide the tracking (tooltip).
|
@@ -8834,7 +8913,9 @@ MouseTracker.prototype = {
|
|
8834
8913
|
// issue #149 workaround
|
8835
8914
|
// The mouseleave event above does not always fire. Whenever the mouse is moving
|
8836
8915
|
// outside the plotarea, hide the tooltip
|
8837
|
-
|
8916
|
+
if (!hasTouch) { // #1385
|
8917
|
+
addEvent(doc, 'mousemove', mouseTracker.hideTooltipOnMouseMove);
|
8918
|
+
}
|
8838
8919
|
|
8839
8920
|
container.ontouchstart = function (e) {
|
8840
8921
|
// For touch devices, use touchmove to zoom
|
@@ -9124,19 +9205,27 @@ Legend.prototype = {
|
|
9124
9205
|
/**
|
9125
9206
|
* Position the checkboxes after the width is determined
|
9126
9207
|
*/
|
9127
|
-
positionCheckboxes: function () {
|
9128
|
-
var
|
9208
|
+
positionCheckboxes: function (scrollOffset) {
|
9209
|
+
var alignAttr = this.group.alignAttr,
|
9210
|
+
translateY,
|
9211
|
+
clipHeight = this.clipHeight || this.legendHeight;
|
9129
9212
|
|
9130
|
-
|
9131
|
-
|
9132
|
-
|
9133
|
-
|
9134
|
-
|
9135
|
-
|
9136
|
-
|
9137
|
-
|
9138
|
-
|
9139
|
-
|
9213
|
+
if (alignAttr) {
|
9214
|
+
translateY = alignAttr.translateY;
|
9215
|
+
each(this.allItems, function (item) {
|
9216
|
+
var checkbox = item.checkbox,
|
9217
|
+
top;
|
9218
|
+
|
9219
|
+
if (checkbox) {
|
9220
|
+
top = (translateY + checkbox.y + (scrollOffset || 0) + 3);
|
9221
|
+
css(checkbox, {
|
9222
|
+
left: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 20) + PX,
|
9223
|
+
top: top + PX,
|
9224
|
+
display: top > translateY - 6 && top < translateY + clipHeight - 6 ? '' : NONE
|
9225
|
+
});
|
9226
|
+
}
|
9227
|
+
});
|
9228
|
+
}
|
9140
9229
|
},
|
9141
9230
|
|
9142
9231
|
/**
|
@@ -9165,7 +9254,8 @@ Legend.prototype = {
|
|
9165
9254
|
li = item.legendItem,
|
9166
9255
|
series = item.series || item,
|
9167
9256
|
itemOptions = series.options,
|
9168
|
-
showCheckbox = itemOptions.showCheckbox
|
9257
|
+
showCheckbox = itemOptions.showCheckbox,
|
9258
|
+
useHTML = options.useHTML;
|
9169
9259
|
|
9170
9260
|
if (!li) { // generate it once, later move it
|
9171
9261
|
|
@@ -9183,7 +9273,7 @@ Legend.prototype = {
|
|
9183
9273
|
options.labelFormatter.call(item),
|
9184
9274
|
ltr ? symbolWidth + symbolPadding : -symbolPadding,
|
9185
9275
|
legend.baseline,
|
9186
|
-
|
9276
|
+
useHTML
|
9187
9277
|
)
|
9188
9278
|
.css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)
|
9189
9279
|
.attr({
|
@@ -9192,8 +9282,8 @@ Legend.prototype = {
|
|
9192
9282
|
})
|
9193
9283
|
.add(item.legendGroup);
|
9194
9284
|
|
9195
|
-
// Set the events on the item group
|
9196
|
-
item.legendGroup.on('mouseover', function () {
|
9285
|
+
// Set the events on the item group, or in case of useHTML, the item itself (#1249)
|
9286
|
+
(useHTML ? li : item.legendGroup).on('mouseover', function () {
|
9197
9287
|
item.setState(HOVER_STATE);
|
9198
9288
|
li.css(legend.options.itemHoverStyle);
|
9199
9289
|
})
|
@@ -9512,6 +9602,7 @@ Legend.prototype = {
|
|
9512
9602
|
this.scrollGroup.attr({
|
9513
9603
|
translateY: 1
|
9514
9604
|
});
|
9605
|
+
this.clipHeight = 0; // #1379
|
9515
9606
|
}
|
9516
9607
|
|
9517
9608
|
return legendHeight;
|
@@ -9530,7 +9621,8 @@ Legend.prototype = {
|
|
9530
9621
|
activeColor = navOptions.activeColor,
|
9531
9622
|
inactiveColor = navOptions.inactiveColor,
|
9532
9623
|
pager = this.pager,
|
9533
|
-
padding = this.padding
|
9624
|
+
padding = this.padding,
|
9625
|
+
scrollOffset;
|
9534
9626
|
|
9535
9627
|
// When resizing while looking at the last page
|
9536
9628
|
if (currentPage > pageCount) {
|
@@ -9565,8 +9657,9 @@ Legend.prototype = {
|
|
9565
9657
|
cursor: currentPage === pageCount ? 'default' : 'pointer'
|
9566
9658
|
});
|
9567
9659
|
|
9660
|
+
scrollOffset = -mathMin(clipHeight * (currentPage - 1), this.fullHeight - clipHeight + padding) + 1;
|
9568
9661
|
this.scrollGroup.animate({
|
9569
|
-
translateY:
|
9662
|
+
translateY: scrollOffset
|
9570
9663
|
});
|
9571
9664
|
pager.attr({
|
9572
9665
|
text: currentPage + '/' + pageCount
|
@@ -9574,6 +9667,7 @@ Legend.prototype = {
|
|
9574
9667
|
|
9575
9668
|
|
9576
9669
|
this.currentPage = currentPage;
|
9670
|
+
this.positionCheckboxes(scrollOffset);
|
9577
9671
|
}
|
9578
9672
|
|
9579
9673
|
}
|
@@ -9586,72 +9680,108 @@ Legend.prototype = {
|
|
9586
9680
|
* @param {Object} options
|
9587
9681
|
* @param {Function} callback Function to run when the chart has loaded
|
9588
9682
|
*/
|
9589
|
-
function Chart(
|
9590
|
-
|
9591
|
-
var options,
|
9592
|
-
seriesOptions = userOptions.series; // skip merging data points to increase performance
|
9593
|
-
userOptions.series = null;
|
9594
|
-
options = merge(defaultOptions, userOptions); // do the merge
|
9595
|
-
options.series = userOptions.series = seriesOptions; // set back the series data
|
9596
|
-
|
9597
|
-
var optionsChart = options.chart,
|
9598
|
-
optionsMargin = optionsChart.margin,
|
9599
|
-
margin = isObject(optionsMargin) ?
|
9600
|
-
optionsMargin :
|
9601
|
-
[optionsMargin, optionsMargin, optionsMargin, optionsMargin];
|
9602
|
-
|
9603
|
-
this.optionsMarginTop = pick(optionsChart.marginTop, margin[0]);
|
9604
|
-
this.optionsMarginRight = pick(optionsChart.marginRight, margin[1]);
|
9605
|
-
this.optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]);
|
9606
|
-
this.optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]);
|
9607
|
-
|
9608
|
-
var chartEvents = optionsChart.events;
|
9609
|
-
|
9610
|
-
this.runChartClick = chartEvents && !!chartEvents.click;
|
9611
|
-
this.callback = callback;
|
9612
|
-
this.isResizing = 0;
|
9613
|
-
this.options = options;
|
9614
|
-
//chartTitleOptions = UNDEFINED;
|
9615
|
-
//chartSubtitleOptions = UNDEFINED;
|
9616
|
-
|
9617
|
-
this.axes = [];
|
9618
|
-
this.series = [];
|
9619
|
-
this.hasCartesianSeries = optionsChart.showAxes;
|
9620
|
-
//this.axisOffset = UNDEFINED;
|
9621
|
-
//this.maxTicks = UNDEFINED; // handle the greatest amount of ticks on grouped axes
|
9622
|
-
//this.inverted = UNDEFINED;
|
9623
|
-
//this.loadingShown = UNDEFINED;
|
9624
|
-
//this.container = UNDEFINED;
|
9625
|
-
//this.chartWidth = UNDEFINED;
|
9626
|
-
//this.chartHeight = UNDEFINED;
|
9627
|
-
//this.marginRight = UNDEFINED;
|
9628
|
-
//this.marginBottom = UNDEFINED;
|
9629
|
-
//this.containerWidth = UNDEFINED;
|
9630
|
-
//this.containerHeight = UNDEFINED;
|
9631
|
-
//this.oldChartWidth = UNDEFINED;
|
9632
|
-
//this.oldChartHeight = UNDEFINED;
|
9633
|
-
|
9634
|
-
//this.renderTo = UNDEFINED;
|
9635
|
-
//this.renderToClone = UNDEFINED;
|
9636
|
-
//this.tracker = UNDEFINED;
|
9637
|
-
|
9638
|
-
//this.spacingBox = UNDEFINED
|
9639
|
-
|
9640
|
-
//this.legend = UNDEFINED;
|
9641
|
-
|
9642
|
-
// Elements
|
9643
|
-
//this.chartBackground = UNDEFINED;
|
9644
|
-
//this.plotBackground = UNDEFINED;
|
9645
|
-
//this.plotBGImage = UNDEFINED;
|
9646
|
-
//this.plotBorder = UNDEFINED;
|
9647
|
-
//this.loadingDiv = UNDEFINED;
|
9648
|
-
//this.loadingSpan = UNDEFINED;
|
9649
|
-
|
9650
|
-
this.init(chartEvents);
|
9683
|
+
function Chart() {
|
9684
|
+
this.init.apply(this, arguments);
|
9651
9685
|
}
|
9652
9686
|
|
9653
9687
|
Chart.prototype = {
|
9654
9688
|
|
9689
|
+
/**
|
9690
|
+
* Initialize the chart
|
9691
|
+
*/
|
9692
|
+
init: function (userOptions, callback) {
|
9693
|
+
|
9694
|
+
// Handle regular options
|
9695
|
+
var options,
|
9696
|
+
seriesOptions = userOptions.series; // skip merging data points to increase performance
|
9697
|
+
|
9698
|
+
userOptions.series = null;
|
9699
|
+
options = merge(defaultOptions, userOptions); // do the merge
|
9700
|
+
options.series = userOptions.series = seriesOptions; // set back the series data
|
9701
|
+
|
9702
|
+
var optionsChart = options.chart,
|
9703
|
+
optionsMargin = optionsChart.margin,
|
9704
|
+
margin = isObject(optionsMargin) ?
|
9705
|
+
optionsMargin :
|
9706
|
+
[optionsMargin, optionsMargin, optionsMargin, optionsMargin];
|
9707
|
+
|
9708
|
+
this.optionsMarginTop = pick(optionsChart.marginTop, margin[0]);
|
9709
|
+
this.optionsMarginRight = pick(optionsChart.marginRight, margin[1]);
|
9710
|
+
this.optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]);
|
9711
|
+
this.optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]);
|
9712
|
+
|
9713
|
+
var chartEvents = optionsChart.events;
|
9714
|
+
|
9715
|
+
this.runChartClick = chartEvents && !!chartEvents.click;
|
9716
|
+
this.callback = callback;
|
9717
|
+
this.isResizing = 0;
|
9718
|
+
this.options = options;
|
9719
|
+
//chartTitleOptions = UNDEFINED;
|
9720
|
+
//chartSubtitleOptions = UNDEFINED;
|
9721
|
+
|
9722
|
+
this.axes = [];
|
9723
|
+
this.series = [];
|
9724
|
+
this.hasCartesianSeries = optionsChart.showAxes;
|
9725
|
+
//this.axisOffset = UNDEFINED;
|
9726
|
+
//this.maxTicks = UNDEFINED; // handle the greatest amount of ticks on grouped axes
|
9727
|
+
//this.inverted = UNDEFINED;
|
9728
|
+
//this.loadingShown = UNDEFINED;
|
9729
|
+
//this.container = UNDEFINED;
|
9730
|
+
//this.chartWidth = UNDEFINED;
|
9731
|
+
//this.chartHeight = UNDEFINED;
|
9732
|
+
//this.marginRight = UNDEFINED;
|
9733
|
+
//this.marginBottom = UNDEFINED;
|
9734
|
+
//this.containerWidth = UNDEFINED;
|
9735
|
+
//this.containerHeight = UNDEFINED;
|
9736
|
+
//this.oldChartWidth = UNDEFINED;
|
9737
|
+
//this.oldChartHeight = UNDEFINED;
|
9738
|
+
|
9739
|
+
//this.renderTo = UNDEFINED;
|
9740
|
+
//this.renderToClone = UNDEFINED;
|
9741
|
+
//this.tracker = UNDEFINED;
|
9742
|
+
|
9743
|
+
//this.spacingBox = UNDEFINED
|
9744
|
+
|
9745
|
+
//this.legend = UNDEFINED;
|
9746
|
+
|
9747
|
+
// Elements
|
9748
|
+
//this.chartBackground = UNDEFINED;
|
9749
|
+
//this.plotBackground = UNDEFINED;
|
9750
|
+
//this.plotBGImage = UNDEFINED;
|
9751
|
+
//this.plotBorder = UNDEFINED;
|
9752
|
+
//this.loadingDiv = UNDEFINED;
|
9753
|
+
//this.loadingSpan = UNDEFINED;
|
9754
|
+
|
9755
|
+
var chart = this,
|
9756
|
+
eventType;
|
9757
|
+
|
9758
|
+
// Add the chart to the global lookup
|
9759
|
+
chart.index = charts.length;
|
9760
|
+
charts.push(chart);
|
9761
|
+
|
9762
|
+
// Set up auto resize
|
9763
|
+
if (optionsChart.reflow !== false) {
|
9764
|
+
addEvent(chart, 'load', chart.initReflow);
|
9765
|
+
}
|
9766
|
+
|
9767
|
+
// Chart event handlers
|
9768
|
+
if (chartEvents) {
|
9769
|
+
for (eventType in chartEvents) {
|
9770
|
+
addEvent(chart, eventType, chartEvents[eventType]);
|
9771
|
+
}
|
9772
|
+
}
|
9773
|
+
|
9774
|
+
chart.xAxis = [];
|
9775
|
+
chart.yAxis = [];
|
9776
|
+
|
9777
|
+
// Expose methods and variables
|
9778
|
+
chart.animation = useCanVG ? false : pick(optionsChart.animation, true);
|
9779
|
+
chart.pointCount = 0;
|
9780
|
+
chart.counters = new ChartCounters();
|
9781
|
+
|
9782
|
+
chart.firstRender();
|
9783
|
+
},
|
9784
|
+
|
9655
9785
|
/**
|
9656
9786
|
* Initialize an individual series, called internally before render time
|
9657
9787
|
*/
|
@@ -9822,13 +9952,13 @@ Chart.prototype = {
|
|
9822
9952
|
|
9823
9953
|
|
9824
9954
|
}
|
9825
|
-
|
9826
9955
|
// the plot areas size has changed
|
9827
9956
|
if (isDirtyBox) {
|
9828
9957
|
chart.drawChartBox();
|
9829
9958
|
}
|
9830
9959
|
|
9831
9960
|
|
9961
|
+
|
9832
9962
|
// redraw affected series
|
9833
9963
|
each(series, function (serie) {
|
9834
9964
|
if (serie.isDirty && serie.visible &&
|
@@ -9837,7 +9967,6 @@ Chart.prototype = {
|
|
9837
9967
|
}
|
9838
9968
|
});
|
9839
9969
|
|
9840
|
-
|
9841
9970
|
// move tooltip or reset
|
9842
9971
|
if (tracker && tracker.resetTracker) {
|
9843
9972
|
tracker.resetTracker(true);
|
@@ -10191,10 +10320,10 @@ Chart.prototype = {
|
|
10191
10320
|
chart.containerWidth = adapterRun(renderTo, 'width');
|
10192
10321
|
chart.containerHeight = adapterRun(renderTo, 'height');
|
10193
10322
|
|
10194
|
-
chart.chartWidth = optionsChart.width
|
10195
|
-
chart.chartHeight = optionsChart.height
|
10323
|
+
chart.chartWidth = mathMax(0, pick(optionsChart.width, chart.containerWidth, 600));
|
10324
|
+
chart.chartHeight = mathMax(0, pick(optionsChart.height,
|
10196
10325
|
// the offsetHeight of an empty container is 0 in standard browsers, but 19 in IE7:
|
10197
|
-
|
10326
|
+
chart.containerHeight > 19 ? chart.containerHeight : 400));
|
10198
10327
|
},
|
10199
10328
|
|
10200
10329
|
/**
|
@@ -10242,6 +10371,8 @@ Chart.prototype = {
|
|
10242
10371
|
chartWidth,
|
10243
10372
|
chartHeight,
|
10244
10373
|
renderTo,
|
10374
|
+
indexAttrName = 'data-highcharts-chart',
|
10375
|
+
oldChartIndex,
|
10245
10376
|
containerId;
|
10246
10377
|
|
10247
10378
|
chart.renderTo = renderTo = optionsChart.renderTo;
|
@@ -10255,6 +10386,15 @@ Chart.prototype = {
|
|
10255
10386
|
if (!renderTo) {
|
10256
10387
|
error(13, true);
|
10257
10388
|
}
|
10389
|
+
|
10390
|
+
// If the container already holds a chart, destroy it
|
10391
|
+
oldChartIndex = pInt(attr(renderTo, indexAttrName));
|
10392
|
+
if (!isNaN(oldChartIndex) && charts[oldChartIndex]) {
|
10393
|
+
charts[oldChartIndex].destroy();
|
10394
|
+
}
|
10395
|
+
|
10396
|
+
// Make a reference to the chart from the div
|
10397
|
+
attr(renderTo, indexAttrName, chart.index);
|
10258
10398
|
|
10259
10399
|
// remove previous chart
|
10260
10400
|
renderTo.innerHTML = '';
|
@@ -10427,13 +10567,14 @@ Chart.prototype = {
|
|
10427
10567
|
|
10428
10568
|
// Width and height checks for display:none. Target is doc in IE8 and Opera,
|
10429
10569
|
// win in Firefox, Chrome and IE9.
|
10430
|
-
if (width && height && (target === win || target === doc)) {
|
10570
|
+
if (!chart.hasUserSize && width && height && (target === win || target === doc)) {
|
10431
10571
|
|
10432
10572
|
if (width !== chart.containerWidth || height !== chart.containerHeight) {
|
10433
10573
|
clearTimeout(reflowTimeout);
|
10434
10574
|
chart.reflowTimeout = reflowTimeout = setTimeout(function () {
|
10435
10575
|
if (chart.container) { // It may have been destroyed in the meantime (#1257)
|
10436
|
-
chart.
|
10576
|
+
chart.setSize(width, height, false);
|
10577
|
+
chart.hasUserSize = null;
|
10437
10578
|
}
|
10438
10579
|
}, 100);
|
10439
10580
|
}
|
@@ -10453,8 +10594,7 @@ Chart.prototype = {
|
|
10453
10594
|
* @param {Number} height
|
10454
10595
|
* @param {Object|Boolean} animation
|
10455
10596
|
*/
|
10456
|
-
|
10457
|
-
resize: function (width, height, animation) {
|
10597
|
+
setSize: function (width, height, animation) {
|
10458
10598
|
var chart = this,
|
10459
10599
|
chartWidth,
|
10460
10600
|
chartHeight,
|
@@ -10480,10 +10620,11 @@ Chart.prototype = {
|
|
10480
10620
|
chart.oldChartHeight = chart.chartHeight;
|
10481
10621
|
chart.oldChartWidth = chart.chartWidth;
|
10482
10622
|
if (defined(width)) {
|
10483
|
-
chart.chartWidth = chartWidth = mathRound(width);
|
10623
|
+
chart.chartWidth = chartWidth = mathMax(0, mathRound(width));
|
10624
|
+
chart.hasUserSize = !!chartWidth;
|
10484
10625
|
}
|
10485
10626
|
if (defined(height)) {
|
10486
|
-
chart.chartHeight = chartHeight = mathRound(height);
|
10627
|
+
chart.chartHeight = chartHeight = mathMax(0, mathRound(height));
|
10487
10628
|
}
|
10488
10629
|
|
10489
10630
|
css(chart.container, {
|
@@ -10564,8 +10705,8 @@ Chart.prototype = {
|
|
10564
10705
|
|
10565
10706
|
chart.plotLeft = plotLeft = mathRound(chart.plotLeft);
|
10566
10707
|
chart.plotTop = plotTop = mathRound(chart.plotTop);
|
10567
|
-
chart.plotWidth = plotWidth = mathRound(chartWidth - plotLeft - chart.marginRight);
|
10568
|
-
chart.plotHeight = plotHeight = mathRound(chartHeight - plotTop - chart.marginBottom);
|
10708
|
+
chart.plotWidth = plotWidth = mathMax(0, mathRound(chartWidth - plotLeft - chart.marginRight));
|
10709
|
+
chart.plotHeight = plotHeight = mathMax(0, mathRound(chartHeight - plotTop - chart.marginBottom));
|
10569
10710
|
|
10570
10711
|
chart.plotSizeX = inverted ? plotHeight : plotWidth;
|
10571
10712
|
chart.plotSizeY = inverted ? plotWidth : plotHeight;
|
@@ -10884,9 +11025,13 @@ Chart.prototype = {
|
|
10884
11025
|
container = chart.container,
|
10885
11026
|
i,
|
10886
11027
|
parentNode = container && container.parentNode;
|
10887
|
-
|
11028
|
+
|
10888
11029
|
// fire the chart.destoy event
|
10889
11030
|
fireEvent(chart, 'destroy');
|
11031
|
+
|
11032
|
+
// Delete the chart from charts lookup array
|
11033
|
+
charts[chart.index] = UNDEFINED;
|
11034
|
+
chart.renderTo.removeAttribute('data-highcharts-chart');
|
10890
11035
|
|
10891
11036
|
// remove events
|
10892
11037
|
removeEvent(chart);
|
@@ -10905,7 +11050,9 @@ Chart.prototype = {
|
|
10905
11050
|
}
|
10906
11051
|
|
10907
11052
|
// ==== Destroy chart properties:
|
10908
|
-
each(['title', 'subtitle', 'chartBackground', 'plotBackground', 'plotBGImage',
|
11053
|
+
each(['title', 'subtitle', 'chartBackground', 'plotBackground', 'plotBGImage',
|
11054
|
+
'plotBorder', 'seriesGroup', 'clipRect', 'credits', 'tracker', 'scroller',
|
11055
|
+
'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', 'renderer'], function (name) {
|
10909
11056
|
var prop = chart[name];
|
10910
11057
|
|
10911
11058
|
if (prop && prop.destroy) {
|
@@ -10930,37 +11077,48 @@ Chart.prototype = {
|
|
10930
11077
|
|
10931
11078
|
},
|
10932
11079
|
|
11080
|
+
|
10933
11081
|
/**
|
10934
|
-
*
|
11082
|
+
* VML namespaces can't be added until after complete. Listening
|
11083
|
+
* for Perini's doScroll hack is not enough.
|
10935
11084
|
*/
|
10936
|
-
|
10937
|
-
var chart = this
|
10938
|
-
options = chart.options,
|
10939
|
-
callback = chart.callback;
|
11085
|
+
isReadyToRender: function () {
|
11086
|
+
var chart = this;
|
10940
11087
|
|
10941
|
-
// VML namespaces can't be added until after complete. Listening
|
10942
|
-
// for Perini's doScroll hack is not enough.
|
10943
|
-
var ONREADYSTATECHANGE = 'onreadystatechange',
|
10944
|
-
COMPLETE = 'complete';
|
10945
11088
|
// Note: in spite of JSLint's complaints, win == win.top is required
|
10946
11089
|
/*jslint eqeq: true*/
|
10947
|
-
if ((!hasSVG && (win == win.top && doc.readyState !==
|
11090
|
+
if ((!hasSVG && (win == win.top && doc.readyState !== 'complete')) || (useCanVG && !win.canvg)) {
|
10948
11091
|
/*jslint eqeq: false*/
|
10949
11092
|
if (useCanVG) {
|
10950
11093
|
// Delay rendering until canvg library is downloaded and ready
|
10951
|
-
CanVGController.push(function () { chart.firstRender(); }, options.global.canvasToolsURL);
|
11094
|
+
CanVGController.push(function () { chart.firstRender(); }, chart.options.global.canvasToolsURL);
|
10952
11095
|
} else {
|
10953
|
-
doc.attachEvent(
|
10954
|
-
doc.detachEvent(
|
10955
|
-
if (doc.readyState ===
|
11096
|
+
doc.attachEvent('onreadystatechange', function () {
|
11097
|
+
doc.detachEvent('onreadystatechange', chart.firstRender);
|
11098
|
+
if (doc.readyState === 'complete') {
|
10956
11099
|
chart.firstRender();
|
10957
11100
|
}
|
10958
11101
|
});
|
10959
11102
|
}
|
11103
|
+
return false;
|
11104
|
+
}
|
11105
|
+
return true;
|
11106
|
+
},
|
11107
|
+
|
11108
|
+
/**
|
11109
|
+
* Prepare for first rendering after all data are loaded
|
11110
|
+
*/
|
11111
|
+
firstRender: function () {
|
11112
|
+
var chart = this,
|
11113
|
+
options = chart.options,
|
11114
|
+
callback = chart.callback;
|
11115
|
+
|
11116
|
+
// Check whether the chart is ready to render
|
11117
|
+
if (!chart.isReadyToRender()) {
|
10960
11118
|
return;
|
10961
11119
|
}
|
10962
11120
|
|
10963
|
-
//
|
11121
|
+
// Create the container
|
10964
11122
|
chart.getContainer();
|
10965
11123
|
|
10966
11124
|
// Run an early event after the container and renderer are established
|
@@ -11014,73 +11172,6 @@ Chart.prototype = {
|
|
11014
11172
|
|
11015
11173
|
fireEvent(chart, 'load');
|
11016
11174
|
|
11017
|
-
},
|
11018
|
-
|
11019
|
-
init: function (chartEvents) {
|
11020
|
-
var chart = this,
|
11021
|
-
optionsChart = chart.options.chart,
|
11022
|
-
eventType;
|
11023
|
-
|
11024
|
-
// Run chart
|
11025
|
-
|
11026
|
-
// Set up auto resize
|
11027
|
-
if (optionsChart.reflow !== false) {
|
11028
|
-
addEvent(chart, 'load', chart.initReflow);
|
11029
|
-
}
|
11030
|
-
|
11031
|
-
// Chart event handlers
|
11032
|
-
if (chartEvents) {
|
11033
|
-
for (eventType in chartEvents) {
|
11034
|
-
addEvent(chart, eventType, chartEvents[eventType]);
|
11035
|
-
}
|
11036
|
-
}
|
11037
|
-
|
11038
|
-
chart.xAxis = [];
|
11039
|
-
chart.yAxis = [];
|
11040
|
-
|
11041
|
-
// Expose methods and variables
|
11042
|
-
chart.animation = useCanVG ? false : pick(optionsChart.animation, true);
|
11043
|
-
chart.setSize = chart.resize;
|
11044
|
-
chart.pointCount = 0;
|
11045
|
-
chart.counters = new ChartCounters();
|
11046
|
-
/*
|
11047
|
-
if ($) $(function () {
|
11048
|
-
$container = $('#container');
|
11049
|
-
var origChartWidth,
|
11050
|
-
origChartHeight;
|
11051
|
-
if ($container) {
|
11052
|
-
$('<button>+</button>')
|
11053
|
-
.insertBefore($container)
|
11054
|
-
.click(function () {
|
11055
|
-
if (origChartWidth === UNDEFINED) {
|
11056
|
-
origChartWidth = chartWidth;
|
11057
|
-
origChartHeight = chartHeight;
|
11058
|
-
}
|
11059
|
-
chart.resize(chartWidth *= 1.1, chartHeight *= 1.1);
|
11060
|
-
});
|
11061
|
-
$('<button>-</button>')
|
11062
|
-
.insertBefore($container)
|
11063
|
-
.click(function () {
|
11064
|
-
if (origChartWidth === UNDEFINED) {
|
11065
|
-
origChartWidth = chartWidth;
|
11066
|
-
origChartHeight = chartHeight;
|
11067
|
-
}
|
11068
|
-
chart.resize(chartWidth *= 0.9, chartHeight *= 0.9);
|
11069
|
-
});
|
11070
|
-
$('<button>1:1</button>')
|
11071
|
-
.insertBefore($container)
|
11072
|
-
.click(function () {
|
11073
|
-
if (origChartWidth === UNDEFINED) {
|
11074
|
-
origChartWidth = chartWidth;
|
11075
|
-
origChartHeight = chartHeight;
|
11076
|
-
}
|
11077
|
-
chart.resize(origChartWidth, origChartHeight);
|
11078
|
-
});
|
11079
|
-
}
|
11080
|
-
})
|
11081
|
-
*/
|
11082
|
-
|
11083
|
-
chart.firstRender();
|
11084
11175
|
}
|
11085
11176
|
}; // end Chart
|
11086
11177
|
|
@@ -11108,7 +11199,6 @@ Point.prototype = {
|
|
11108
11199
|
if (series.options.colorByPoint) {
|
11109
11200
|
defaultColors = series.chart.options.colors;
|
11110
11201
|
point.color = point.color || defaultColors[counters.color++];
|
11111
|
-
|
11112
11202
|
// loop back to zero
|
11113
11203
|
counters.wrapColor(defaultColors.length);
|
11114
11204
|
}
|
@@ -11212,7 +11302,7 @@ Point.prototype = {
|
|
11212
11302
|
*/
|
11213
11303
|
destroyElements: function () {
|
11214
11304
|
var point = this,
|
11215
|
-
props = ['graphic', 'tracker', 'dataLabel', 'group', 'connector', 'shadowGroup'],
|
11305
|
+
props = ['graphic', 'tracker', 'dataLabel', 'dataLabelUpper', 'group', 'connector', 'shadowGroup'],
|
11216
11306
|
prop,
|
11217
11307
|
i = 6;
|
11218
11308
|
while (i--) {
|
@@ -11337,7 +11427,7 @@ Point.prototype = {
|
|
11337
11427
|
|
11338
11428
|
// Backwards compatibility to y naming in early Highstock
|
11339
11429
|
seriesTooltipOptions.valuePrefix = seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix;
|
11340
|
-
seriesTooltipOptions.valueDecimals = seriesTooltipOptions.valueDecimals
|
11430
|
+
seriesTooltipOptions.valueDecimals = pick(seriesTooltipOptions.valueDecimals, seriesTooltipOptions.yDecimals); // #1248
|
11341
11431
|
seriesTooltipOptions.valueSuffix = seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix;
|
11342
11432
|
|
11343
11433
|
// loop over the variables defined on the form {series.name}, {point.y} etc
|
@@ -11406,7 +11496,7 @@ Point.prototype = {
|
|
11406
11496
|
for (i = 0; i < dataLength; i++) {
|
11407
11497
|
if (data[i] === point) {
|
11408
11498
|
series.xData[i] = point.x;
|
11409
|
-
series.yData[i] = point.y;
|
11499
|
+
series.yData[i] = point.toYData ? point.toYData() : point.y;
|
11410
11500
|
series.options.data[i] = options;
|
11411
11501
|
break;
|
11412
11502
|
}
|
@@ -11624,6 +11714,7 @@ Series.prototype = {
|
|
11624
11714
|
type: 'line',
|
11625
11715
|
pointClass: Point,
|
11626
11716
|
sorted: true, // requires the data to be sorted
|
11717
|
+
requireSorting: true,
|
11627
11718
|
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
|
11628
11719
|
stroke: 'lineColor',
|
11629
11720
|
'stroke-width': 'lineWidth',
|
@@ -11918,6 +12009,7 @@ Series.prototype = {
|
|
11918
12009
|
*/
|
11919
12010
|
addPoint: function (options, redraw, shift, animation) {
|
11920
12011
|
var series = this,
|
12012
|
+
seriesOptions = series.options,
|
11921
12013
|
data = series.data,
|
11922
12014
|
graph = series.graph,
|
11923
12015
|
area = series.area,
|
@@ -11925,7 +12017,7 @@ Series.prototype = {
|
|
11925
12017
|
xData = series.xData,
|
11926
12018
|
yData = series.yData,
|
11927
12019
|
currentShift = (graph && graph.shift) || 0,
|
11928
|
-
dataOptions =
|
12020
|
+
dataOptions = seriesOptions.data,
|
11929
12021
|
point,
|
11930
12022
|
proto = series.pointClass.prototype;
|
11931
12023
|
|
@@ -11953,6 +12045,10 @@ Series.prototype = {
|
|
11953
12045
|
yData.push(proto.toYData ? proto.toYData.call(point) : point.y);
|
11954
12046
|
dataOptions.push(options);
|
11955
12047
|
|
12048
|
+
// Generate points to be added to the legend (#1329)
|
12049
|
+
if (seriesOptions.legendType === 'point') {
|
12050
|
+
series.generatePoints();
|
12051
|
+
}
|
11956
12052
|
|
11957
12053
|
// Shift the first point off the parallel arrays
|
11958
12054
|
// todo: consider series.removePoint(i) method
|
@@ -12058,6 +12154,12 @@ Series.prototype = {
|
|
12058
12154
|
yData[i] = pointProto.toYData ? pointProto.toYData.call(pt) : pt.y;
|
12059
12155
|
}
|
12060
12156
|
}
|
12157
|
+
|
12158
|
+
// Unsorted data is not supported by the line tooltip as well as data grouping and
|
12159
|
+
// navigation in Stock charts (#725)
|
12160
|
+
if (series.requireSorting && xData.length > 1 && xData[1] < xData[0]) {
|
12161
|
+
error(15);
|
12162
|
+
}
|
12061
12163
|
|
12062
12164
|
// Forgetting to cast strings to numbers is a common caveat when handling CSV or JSON
|
12063
12165
|
if (isString(yData[0])) {
|
@@ -12461,10 +12563,6 @@ Series.prototype = {
|
|
12461
12563
|
chart = series.chart,
|
12462
12564
|
hoverSeries = chart.hoverSeries;
|
12463
12565
|
|
12464
|
-
/*if (!hasTouch && chart.mouseIsDown) {
|
12465
|
-
return;
|
12466
|
-
}*/
|
12467
|
-
|
12468
12566
|
// set normal state to previous series
|
12469
12567
|
if (hoverSeries && hoverSeries !== series) {
|
12470
12568
|
hoverSeries.onMouseOut();
|
@@ -12584,10 +12682,14 @@ Series.prototype = {
|
|
12584
12682
|
afterAnimate: function () {
|
12585
12683
|
var chart = this.chart,
|
12586
12684
|
sharedClipKey = this.sharedClipKey,
|
12587
|
-
group = this.group
|
12685
|
+
group = this.group,
|
12686
|
+
trackerGroup = this.trackerGroup;
|
12588
12687
|
|
12589
12688
|
if (group && this.options.clip !== false) {
|
12590
12689
|
group.clip(chart.clipRect);
|
12690
|
+
if (trackerGroup) {
|
12691
|
+
trackerGroup.clip(chart.clipRect); // #484
|
12692
|
+
}
|
12591
12693
|
this.markerGroup.clip(); // no clip
|
12592
12694
|
}
|
12593
12695
|
|
@@ -12928,7 +13030,7 @@ Series.prototype = {
|
|
12928
13030
|
'dataLabelsGroup',
|
12929
13031
|
'data-labels',
|
12930
13032
|
series.visible ? VISIBLE : HIDDEN,
|
12931
|
-
6
|
13033
|
+
options.zIndex || 6
|
12932
13034
|
);
|
12933
13035
|
|
12934
13036
|
// Make the labels for each point
|
@@ -13061,7 +13163,7 @@ Series.prototype = {
|
|
13061
13163
|
// Show or hide based on the final aligned position
|
13062
13164
|
dataLabel.attr({
|
13063
13165
|
visibility: options.crop === false || chart.isInsidePlot(alignAttr.x, alignAttr.y) || chart.isInsidePlot(plotX, plotY, inverted) ?
|
13064
|
-
(
|
13166
|
+
(chart.renderer.isSVG ? 'inherit' : VISIBLE) :
|
13065
13167
|
HIDDEN
|
13066
13168
|
});
|
13067
13169
|
|
@@ -13072,10 +13174,15 @@ Series.prototype = {
|
|
13072
13174
|
*/
|
13073
13175
|
getSegmentPath: function (segment) {
|
13074
13176
|
var series = this,
|
13075
|
-
segmentPath = []
|
13076
|
-
|
13177
|
+
segmentPath = [],
|
13178
|
+
step = series.options.step;
|
13179
|
+
|
13077
13180
|
// build the segment line
|
13078
13181
|
each(segment, function (point, i) {
|
13182
|
+
|
13183
|
+
var plotX = point.plotX,
|
13184
|
+
plotY = point.plotY,
|
13185
|
+
lastPoint;
|
13079
13186
|
|
13080
13187
|
if (series.getPointSpline) { // generate the spline as defined in the SplineSeries object
|
13081
13188
|
segmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i));
|
@@ -13086,12 +13193,28 @@ Series.prototype = {
|
|
13086
13193
|
segmentPath.push(i ? L : M);
|
13087
13194
|
|
13088
13195
|
// step line?
|
13089
|
-
if (
|
13090
|
-
|
13091
|
-
|
13092
|
-
|
13093
|
-
|
13094
|
-
|
13196
|
+
if (step && i) {
|
13197
|
+
lastPoint = segment[i - 1];
|
13198
|
+
if (step === 'right') {
|
13199
|
+
segmentPath.push(
|
13200
|
+
lastPoint.plotX,
|
13201
|
+
plotY
|
13202
|
+
);
|
13203
|
+
|
13204
|
+
} else if (step === 'center') {
|
13205
|
+
segmentPath.push(
|
13206
|
+
(lastPoint.plotX + plotX) / 2,
|
13207
|
+
lastPoint.plotY,
|
13208
|
+
(lastPoint.plotX + plotX) / 2,
|
13209
|
+
plotY
|
13210
|
+
);
|
13211
|
+
|
13212
|
+
} else {
|
13213
|
+
segmentPath.push(
|
13214
|
+
plotX,
|
13215
|
+
lastPoint.plotY
|
13216
|
+
);
|
13217
|
+
}
|
13095
13218
|
}
|
13096
13219
|
|
13097
13220
|
// normal line to next point
|
@@ -13427,6 +13550,11 @@ Series.prototype = {
|
|
13427
13550
|
}
|
13428
13551
|
}
|
13429
13552
|
}
|
13553
|
+
|
13554
|
+
// hide tooltip (#1361)
|
13555
|
+
if (chart.hoverSeries === series) {
|
13556
|
+
series.onMouseOut();
|
13557
|
+
}
|
13430
13558
|
|
13431
13559
|
|
13432
13560
|
if (dataLabelsGroup) {
|
@@ -13513,7 +13641,17 @@ Series.prototype = {
|
|
13513
13641
|
singlePoints = series.singlePoints,
|
13514
13642
|
trackerGroup = this.isCartesian && this.plotGroup('trackerGroup', null, VISIBLE, options.zIndex || 1, chart.trackerGroup),
|
13515
13643
|
singlePoint,
|
13516
|
-
i
|
13644
|
+
i,
|
13645
|
+
onMouseOver = function () {
|
13646
|
+
if (chart.hoverSeries !== series) {
|
13647
|
+
series.onMouseOver();
|
13648
|
+
}
|
13649
|
+
},
|
13650
|
+
onMouseOut = function () {
|
13651
|
+
if (!options.stickyTracking) {
|
13652
|
+
series.onMouseOut();
|
13653
|
+
}
|
13654
|
+
};
|
13517
13655
|
|
13518
13656
|
// Extend end points. A better way would be to use round linecaps,
|
13519
13657
|
// but those are not clickable in VML.
|
@@ -13544,27 +13682,23 @@ Series.prototype = {
|
|
13544
13682
|
|
13545
13683
|
} else { // create
|
13546
13684
|
|
13547
|
-
series.tracker = renderer.path(trackerPath)
|
13685
|
+
series.tracker = tracker = renderer.path(trackerPath)
|
13548
13686
|
.attr({
|
13549
13687
|
isTracker: true,
|
13550
|
-
'stroke-linejoin': '
|
13688
|
+
'stroke-linejoin': 'round', // #1225
|
13551
13689
|
visibility: series.visible ? VISIBLE : HIDDEN,
|
13552
13690
|
stroke: TRACKER_FILL,
|
13553
13691
|
fill: trackByArea ? TRACKER_FILL : NONE,
|
13554
13692
|
'stroke-width' : options.lineWidth + (trackByArea ? 0 : 2 * snap)
|
13555
13693
|
})
|
13556
|
-
.on(
|
13557
|
-
|
13558
|
-
series.onMouseOver();
|
13559
|
-
}
|
13560
|
-
})
|
13561
|
-
.on('mouseout', function () {
|
13562
|
-
if (!options.stickyTracking) {
|
13563
|
-
series.onMouseOut();
|
13564
|
-
}
|
13565
|
-
})
|
13694
|
+
.on('mouseover', onMouseOver)
|
13695
|
+
.on('mouseout', onMouseOut)
|
13566
13696
|
.css(css)
|
13567
13697
|
.add(trackerGroup);
|
13698
|
+
|
13699
|
+
if (hasTouch) {
|
13700
|
+
tracker.on('touchstart', onMouseOver);
|
13701
|
+
}
|
13568
13702
|
}
|
13569
13703
|
|
13570
13704
|
}
|
@@ -13928,6 +14062,7 @@ var ColumnSeries = extendClass(Series, {
|
|
13928
14062
|
borderWidth = options.borderWidth,
|
13929
14063
|
columnCount = 0,
|
13930
14064
|
xAxis = series.xAxis,
|
14065
|
+
yAxis = series.yAxis,
|
13931
14066
|
reversedXAxis = xAxis.reversed,
|
13932
14067
|
stackGroups = {},
|
13933
14068
|
stackKey,
|
@@ -13940,7 +14075,6 @@ var ColumnSeries = extendClass(Series, {
|
|
13940
14075
|
// chart.orderStacks() function and call it on init, addSeries and removeSeries
|
13941
14076
|
if (options.grouping === false) {
|
13942
14077
|
columnCount = 1;
|
13943
|
-
|
13944
14078
|
} else {
|
13945
14079
|
each(chart.series, function (otherSeries) {
|
13946
14080
|
var otherOptions = otherSeries.options;
|
@@ -13973,23 +14107,24 @@ var ColumnSeries = extendClass(Series, {
|
|
13973
14107
|
pointOffsetWidth * options.pointPadding,
|
13974
14108
|
pointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), // exact point width, used in polar charts
|
13975
14109
|
barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width
|
13976
|
-
colIndex = (reversedXAxis ?
|
13977
|
-
|
14110
|
+
colIndex = (reversedXAxis ?
|
14111
|
+
columnCount - (series.columnIndex || 0) : // #1251
|
14112
|
+
series.columnIndex) || 0,
|
13978
14113
|
pointXOffset = pointPadding + (groupPadding + colIndex *
|
13979
14114
|
pointOffsetWidth - (categoryWidth / 2)) *
|
13980
14115
|
(reversedXAxis ? -1 : 1),
|
13981
14116
|
threshold = options.threshold,
|
13982
|
-
translatedThreshold = series.translatedThreshold =
|
14117
|
+
translatedThreshold = series.translatedThreshold = yAxis.getThreshold(threshold),
|
13983
14118
|
minPointLength = pick(options.minPointLength, 5);
|
13984
14119
|
|
13985
14120
|
// record the new values
|
13986
14121
|
each(points, function (point) {
|
13987
|
-
var plotY = point.plotY,
|
14122
|
+
var plotY = mathMin(mathMax(-999, point.plotY), yAxis.len + 999), // Don't draw too far outside plot area (#1303)
|
13988
14123
|
yBottom = pick(point.yBottom, translatedThreshold),
|
13989
14124
|
barX = point.plotX + pointXOffset,
|
13990
14125
|
barY = mathCeil(mathMin(plotY, yBottom)),
|
13991
14126
|
barH = mathCeil(mathMax(plotY, yBottom) - barY),
|
13992
|
-
stack =
|
14127
|
+
stack = yAxis.stacks[(point.y < 0 ? '-' : '') + series.stackKey],
|
13993
14128
|
shapeArgs;
|
13994
14129
|
|
13995
14130
|
// Record the offset'ed position and width of the bar to be able to align the stacking total correctly
|
@@ -14078,7 +14213,7 @@ var ColumnSeries = extendClass(Series, {
|
|
14078
14213
|
},
|
14079
14214
|
/**
|
14080
14215
|
* Draw the individual tracker elements.
|
14081
|
-
* This method is inherited by
|
14216
|
+
* This method is inherited by pie charts too.
|
14082
14217
|
*/
|
14083
14218
|
drawTracker: function () {
|
14084
14219
|
var series = this,
|
@@ -14093,9 +14228,28 @@ var ColumnSeries = extendClass(Series, {
|
|
14093
14228
|
trackerGroup = series.isCartesian && series.plotGroup('trackerGroup', null, VISIBLE, options.zIndex || 1, chart.trackerGroup),
|
14094
14229
|
rel,
|
14095
14230
|
plotY,
|
14096
|
-
validPlotY
|
14231
|
+
validPlotY,
|
14232
|
+
points = series.points,
|
14233
|
+
point,
|
14234
|
+
i = points.length,
|
14235
|
+
onMouseOver = function (event) {
|
14236
|
+
rel = event.relatedTarget || event.fromElement;
|
14237
|
+
if (chart.hoverSeries !== series && attr(rel, 'isTracker') !== trackerLabel) {
|
14238
|
+
series.onMouseOver();
|
14239
|
+
}
|
14240
|
+
points[event.target._i].onMouseOver();
|
14241
|
+
},
|
14242
|
+
onMouseOut = function (event) {
|
14243
|
+
if (!options.stickyTracking) {
|
14244
|
+
rel = event.relatedTarget || event.toElement;
|
14245
|
+
if (attr(rel, 'isTracker') !== trackerLabel) {
|
14246
|
+
series.onMouseOut();
|
14247
|
+
}
|
14248
|
+
}
|
14249
|
+
};
|
14097
14250
|
|
14098
|
-
|
14251
|
+
while (i--) {
|
14252
|
+
point = points[i];
|
14099
14253
|
tracker = point.tracker;
|
14100
14254
|
shapeArgs = point.trackerArgs || point.shapeArgs;
|
14101
14255
|
plotY = point.plotY;
|
@@ -14106,34 +14260,25 @@ var ColumnSeries = extendClass(Series, {
|
|
14106
14260
|
tracker.attr(shapeArgs);
|
14107
14261
|
|
14108
14262
|
} else {
|
14109
|
-
point.tracker =
|
14263
|
+
point.tracker = tracker =
|
14110
14264
|
renderer[point.shapeType](shapeArgs)
|
14111
14265
|
.attr({
|
14112
14266
|
isTracker: trackerLabel,
|
14113
14267
|
fill: TRACKER_FILL,
|
14114
14268
|
visibility: series.visible ? VISIBLE : HIDDEN
|
14115
14269
|
})
|
14116
|
-
.on(
|
14117
|
-
|
14118
|
-
if (chart.hoverSeries !== series && attr(rel, 'isTracker') !== trackerLabel) {
|
14119
|
-
series.onMouseOver();
|
14120
|
-
}
|
14121
|
-
point.onMouseOver();
|
14122
|
-
|
14123
|
-
})
|
14124
|
-
.on('mouseout', function (event) {
|
14125
|
-
if (!options.stickyTracking) {
|
14126
|
-
rel = event.relatedTarget || event.toElement;
|
14127
|
-
if (attr(rel, 'isTracker') !== trackerLabel) {
|
14128
|
-
series.onMouseOut();
|
14129
|
-
}
|
14130
|
-
}
|
14131
|
-
})
|
14270
|
+
.on('mouseover', onMouseOver)
|
14271
|
+
.on('mouseout', onMouseOut)
|
14132
14272
|
.css(css)
|
14133
14273
|
.add(point.group || trackerGroup); // pies have point group - see issue #118
|
14274
|
+
|
14275
|
+
if (hasTouch) {
|
14276
|
+
tracker.on('touchstart', onMouseOver);
|
14277
|
+
}
|
14134
14278
|
}
|
14279
|
+
tracker.element._i = i;
|
14135
14280
|
}
|
14136
|
-
}
|
14281
|
+
}
|
14137
14282
|
},
|
14138
14283
|
|
14139
14284
|
/**
|
@@ -14142,7 +14287,7 @@ var ColumnSeries = extendClass(Series, {
|
|
14142
14287
|
alignDataLabel: function (point, dataLabel, options, alignTo, isNew) {
|
14143
14288
|
var chart = this.chart,
|
14144
14289
|
inverted = chart.inverted,
|
14145
|
-
below = point.below || (point.plotY > (this.translatedThreshold
|
14290
|
+
below = point.below || (point.plotY > pick(this.translatedThreshold, chart.plotSizeY)),
|
14146
14291
|
inside = (this.options.stacking || options.inside); // draw it inside the box?
|
14147
14292
|
|
14148
14293
|
// Align to the column itself, or the top of it
|
@@ -14232,6 +14377,7 @@ var ColumnSeries = extendClass(Series, {
|
|
14232
14377
|
}
|
14233
14378
|
|
14234
14379
|
},
|
14380
|
+
|
14235
14381
|
/**
|
14236
14382
|
* Remove this series from the chart
|
14237
14383
|
*/
|
@@ -14288,6 +14434,7 @@ defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
|
|
14288
14434
|
var ScatterSeries = extendClass(Series, {
|
14289
14435
|
type: 'scatter',
|
14290
14436
|
sorted: false,
|
14437
|
+
requireSorting: false,
|
14291
14438
|
/**
|
14292
14439
|
* Extend the base Series' translate method by adding shape type and
|
14293
14440
|
* arguments for the point trackers
|
@@ -14317,7 +14464,19 @@ var ScatterSeries = extendClass(Series, {
|
|
14317
14464
|
css = cursor && { cursor: cursor },
|
14318
14465
|
points = series.points,
|
14319
14466
|
i = points.length,
|
14320
|
-
graphic
|
14467
|
+
graphic,
|
14468
|
+
markerGroup = series.markerGroup,
|
14469
|
+
onMouseOver = function (e) {
|
14470
|
+
series.onMouseOver();
|
14471
|
+
if (e.target._i !== UNDEFINED) { // undefined on graph in scatterchart
|
14472
|
+
points[e.target._i].onMouseOver();
|
14473
|
+
}
|
14474
|
+
},
|
14475
|
+
onMouseOut = function () {
|
14476
|
+
if (!series.options.stickyTracking) {
|
14477
|
+
series.onMouseOut();
|
14478
|
+
}
|
14479
|
+
};
|
14321
14480
|
|
14322
14481
|
// Set an expando property for the point index, used below
|
14323
14482
|
while (i--) {
|
@@ -14329,26 +14488,23 @@ var ScatterSeries = extendClass(Series, {
|
|
14329
14488
|
|
14330
14489
|
// Add the event listeners, we need to do this only once
|
14331
14490
|
if (!series._hasTracking) {
|
14332
|
-
|
14491
|
+
markerGroup
|
14333
14492
|
.attr({
|
14334
14493
|
isTracker: true
|
14335
14494
|
})
|
14336
|
-
.on(
|
14337
|
-
|
14338
|
-
if (e.target._i !== UNDEFINED) { // undefined on graph in scatterchart
|
14339
|
-
points[e.target._i].onMouseOver();
|
14340
|
-
}
|
14341
|
-
})
|
14342
|
-
.on('mouseout', function () {
|
14343
|
-
if (!series.options.stickyTracking) {
|
14344
|
-
series.onMouseOut();
|
14345
|
-
}
|
14346
|
-
})
|
14495
|
+
.on('mouseover', onMouseOver)
|
14496
|
+
.on('mouseout', onMouseOut)
|
14347
14497
|
.css(css);
|
14498
|
+
if (hasTouch) {
|
14499
|
+
markerGroup.on('touchstart', onMouseOver);
|
14500
|
+
}
|
14501
|
+
|
14348
14502
|
} else {
|
14349
14503
|
series._hasTracking = true;
|
14350
14504
|
}
|
14351
|
-
}
|
14505
|
+
},
|
14506
|
+
|
14507
|
+
setTooltipPoints: noop
|
14352
14508
|
});
|
14353
14509
|
seriesTypes.scatter = ScatterSeries;
|
14354
14510
|
|
@@ -14500,6 +14656,7 @@ var PieSeries = {
|
|
14500
14656
|
type: 'pie',
|
14501
14657
|
isCartesian: false,
|
14502
14658
|
pointClass: PiePoint,
|
14659
|
+
requireSorting: false,
|
14503
14660
|
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
|
14504
14661
|
stroke: 'borderColor',
|
14505
14662
|
'stroke-width': 'borderWidth',
|
@@ -14519,19 +14676,19 @@ var PieSeries = {
|
|
14519
14676
|
*/
|
14520
14677
|
animate: function () {
|
14521
14678
|
var series = this,
|
14522
|
-
points = series.points
|
14679
|
+
points = series.points,
|
14680
|
+
startAngleRad = series.startAngleRad;
|
14523
14681
|
|
14524
14682
|
each(points, function (point) {
|
14525
14683
|
var graphic = point.graphic,
|
14526
|
-
args = point.shapeArgs
|
14527
|
-
up = -mathPI / 2;
|
14684
|
+
args = point.shapeArgs;
|
14528
14685
|
|
14529
14686
|
if (graphic) {
|
14530
14687
|
// start values
|
14531
14688
|
graphic.attr({
|
14532
|
-
r:
|
14533
|
-
start:
|
14534
|
-
end:
|
14689
|
+
r: series.center[3] / 2, // animate from inner radius (#779)
|
14690
|
+
start: startAngleRad,
|
14691
|
+
end: startAngleRad
|
14535
14692
|
});
|
14536
14693
|
|
14537
14694
|
// animate
|
@@ -14597,7 +14754,7 @@ var PieSeries = {
|
|
14597
14754
|
|
14598
14755
|
var total = 0,
|
14599
14756
|
series = this,
|
14600
|
-
cumulative =
|
14757
|
+
cumulative = 0,
|
14601
14758
|
precision = 1000, // issue #172
|
14602
14759
|
options = series.options,
|
14603
14760
|
slicedOffset = options.slicedOffset,
|
@@ -14607,6 +14764,7 @@ var PieSeries = {
|
|
14607
14764
|
start,
|
14608
14765
|
end,
|
14609
14766
|
angle,
|
14767
|
+
startAngleRad = series.startAngleRad = mathPI / 180 * ((options.startAngle || 0) % 360 - 90),
|
14610
14768
|
points = series.points,
|
14611
14769
|
circ = 2 * mathPI,
|
14612
14770
|
fraction,
|
@@ -14644,11 +14802,11 @@ var PieSeries = {
|
|
14644
14802
|
|
14645
14803
|
// set start and end angle
|
14646
14804
|
fraction = total ? point.y / total : 0;
|
14647
|
-
start = mathRound(cumulative * circ * precision) / precision;
|
14805
|
+
start = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;
|
14648
14806
|
if (!ignoreHiddenPoint || point.visible) {
|
14649
14807
|
cumulative += fraction;
|
14650
14808
|
}
|
14651
|
-
end = mathRound(cumulative * circ * precision) / precision;
|
14809
|
+
end = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;
|
14652
14810
|
|
14653
14811
|
// set the shape
|
14654
14812
|
point.shapeType = 'arc';
|
@@ -14663,6 +14821,9 @@ var PieSeries = {
|
|
14663
14821
|
|
14664
14822
|
// center for the sliced out slice
|
14665
14823
|
angle = (end + start) / 2;
|
14824
|
+
if (angle > 0.75 * circ) {
|
14825
|
+
angle -= 2 * mathPI;
|
14826
|
+
}
|
14666
14827
|
point.slicedTranslation = map([
|
14667
14828
|
mathCos(angle) * slicedOffset + chart.plotLeft,
|
14668
14829
|
mathSin(angle) * slicedOffset + chart.plotTop
|
@@ -14675,6 +14836,9 @@ var PieSeries = {
|
|
14675
14836
|
positions[0] + radiusX * 0.7,
|
14676
14837
|
positions[1] + radiusY * 0.7
|
14677
14838
|
];
|
14839
|
+
|
14840
|
+
point.half = angle < circ / 4 ? 0 : 1;
|
14841
|
+
point.angle = angle;
|
14678
14842
|
|
14679
14843
|
// set the anchor point for data labels
|
14680
14844
|
point.labelPos = [
|
@@ -14686,7 +14850,7 @@ var PieSeries = {
|
|
14686
14850
|
positions[1] + radiusY, // a/a
|
14687
14851
|
labelDistance < 0 ? // alignment
|
14688
14852
|
'center' :
|
14689
|
-
|
14853
|
+
point.half ? 'right' : 'left', // alignment
|
14690
14854
|
angle // center angle
|
14691
14855
|
];
|
14692
14856
|
|
@@ -14823,9 +14987,16 @@ var PieSeries = {
|
|
14823
14987
|
y,
|
14824
14988
|
visibility,
|
14825
14989
|
rankArr,
|
14826
|
-
sort,
|
14827
14990
|
i = 2,
|
14828
|
-
j
|
14991
|
+
j,
|
14992
|
+
sort = function (a, b) {
|
14993
|
+
return b.y - a.y;
|
14994
|
+
},
|
14995
|
+
sortByAngle = function (points, sign) {
|
14996
|
+
points.sort(function (a, b) {
|
14997
|
+
return (b.angle - a.angle) * sign;
|
14998
|
+
});
|
14999
|
+
};
|
14829
15000
|
|
14830
15001
|
// get out if not enabled
|
14831
15002
|
if (!options.enabled && !series._hasPointLabels) {
|
@@ -14838,17 +15009,9 @@ var PieSeries = {
|
|
14838
15009
|
// arrange points for detection collision
|
14839
15010
|
each(data, function (point) {
|
14840
15011
|
if (point.dataLabel) { // it may have been cancelled in the base method (#407)
|
14841
|
-
halves[
|
14842
|
-
point.labelPos[7] < mathPI / 2 ? 0 : 1
|
14843
|
-
].push(point);
|
15012
|
+
halves[point.half].push(point);
|
14844
15013
|
}
|
14845
15014
|
});
|
14846
|
-
halves[1].reverse();
|
14847
|
-
|
14848
|
-
// define the sorting algorithm
|
14849
|
-
sort = function (a, b) {
|
14850
|
-
return b.y - a.y;
|
14851
|
-
};
|
14852
15015
|
|
14853
15016
|
// assume equal label heights
|
14854
15017
|
labelHeight = halves[0][0] && halves[0][0].dataLabel && (halves[0][0].dataLabel.getBBox().height || 21); // 21 is for #968
|
@@ -14865,6 +15028,9 @@ var PieSeries = {
|
|
14865
15028
|
pos,
|
14866
15029
|
length = points.length,
|
14867
15030
|
slotIndex;
|
15031
|
+
|
15032
|
+
// Sort by angle
|
15033
|
+
sortByAngle(points, i - 0.5);
|
14868
15034
|
|
14869
15035
|
// Only do anti-collision when we are outside the pie and have connectors (#856)
|
14870
15036
|
if (distanceOption > 0) {
|
@@ -15081,10 +15247,14 @@ extend(Highcharts, {
|
|
15081
15247
|
VMLRenderer: VMLRenderer,
|
15082
15248
|
|
15083
15249
|
// Various
|
15250
|
+
arrayMin: arrayMin,
|
15251
|
+
arrayMax: arrayMax,
|
15252
|
+
charts: charts,
|
15084
15253
|
dateFormat: dateFormat,
|
15085
15254
|
pathAnim: pathAnim,
|
15086
15255
|
getOptions: getOptions,
|
15087
15256
|
hasBidiBug: hasBidiBug,
|
15257
|
+
isTouchDevice: isTouchDevice,
|
15088
15258
|
numberFormat: numberFormat,
|
15089
15259
|
seriesTypes: seriesTypes,
|
15090
15260
|
setOptions: setOptions,
|
@@ -15106,6 +15276,6 @@ extend(Highcharts, {
|
|
15106
15276
|
canvas: useCanVG,
|
15107
15277
|
vml: !hasSVG && !useCanVG,
|
15108
15278
|
product: 'Highcharts',
|
15109
|
-
version: '2.3.
|
15279
|
+
version: '2.3.5'
|
15110
15280
|
});
|
15111
15281
|
}());
|