highcharts-js-rails 0.1.11 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/README.md +9 -8
- data/highcharts-js-rails.gemspec +1 -1
- data/lib/highcharts.rb +3 -1
- data/vendor/assets/javascripts/highcharts-more.js +1581 -35
- 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/modules/canvas-tools.js +1 -1
- data/vendor/assets/javascripts/highcharts/modules/data.js +248 -13
- data/vendor/assets/javascripts/highcharts/modules/exporting.js +75 -59
- metadata +4 -4
@@ -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
|
}());
|