highcharts-js-rails 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/highcharts-js-rails.gemspec +1 -1
- data/vendor/assets/javascripts/adapters/mootools.js +10 -1
- data/vendor/assets/javascripts/adapters/prototype.js +7 -3
- data/vendor/assets/javascripts/highcharts.js +581 -484
- data/vendor/assets/javascripts/modules/canvas-tools.js +472 -472
- data/vendor/assets/javascripts/modules/exporting.js +7 -4
- metadata +38 -13
data/CHANGELOG.md
CHANGED
data/highcharts-js-rails.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'highcharts-js-rails'
|
6
|
-
s.version = '0.1.
|
6
|
+
s.version = '0.1.5'
|
7
7
|
s.authors = ['Alex Robbin']
|
8
8
|
s.email = ['agrobbin@gmail.com']
|
9
9
|
s.homepage = 'https://github.com/agrobbin/highcharts-js-rails'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license
|
2
|
+
* @license @product.name@ JS v@product.version@ (@product.date@)
|
3
3
|
* MooTools adapter
|
4
4
|
*
|
5
5
|
* (c) 2010-2011 Torstein Hønsi
|
@@ -285,6 +285,15 @@ win.HighchartsAdapter = {
|
|
285
285
|
}
|
286
286
|
},
|
287
287
|
|
288
|
+
/**
|
289
|
+
* Set back e.pageX and e.pageY that MooTools has abstracted away
|
290
|
+
*/
|
291
|
+
washMouseEvent: function (e) {
|
292
|
+
e.pageX = e.page.x;
|
293
|
+
e.pageY = e.page.y;
|
294
|
+
return e;
|
295
|
+
},
|
296
|
+
|
288
297
|
/**
|
289
298
|
* Stop running animations on the object
|
290
299
|
*/
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license
|
2
|
+
* @license @product.name@ JS v@product.version@ (@product.date@)
|
3
3
|
* Prototype adapter
|
4
4
|
*
|
5
5
|
* @author Michael Nelson, Torstein Hønsi.
|
@@ -84,13 +84,13 @@ return {
|
|
84
84
|
|
85
85
|
if (element.attr) { // SVGElement
|
86
86
|
element.attr(this.options.attribute, position);
|
87
|
-
|
87
|
+
|
88
88
|
} else { // HTML, #409
|
89
89
|
obj = {};
|
90
90
|
obj[this.options.attribute] = position;
|
91
91
|
$(element).setStyle(obj);
|
92
92
|
}
|
93
|
-
|
93
|
+
|
94
94
|
},
|
95
95
|
finish: function () {
|
96
96
|
// Delete the property that holds this animation now that it is finished.
|
@@ -230,6 +230,10 @@ return {
|
|
230
230
|
}
|
231
231
|
},
|
232
232
|
|
233
|
+
washMouseEvent: function (e) {
|
234
|
+
return e;
|
235
|
+
},
|
236
|
+
|
233
237
|
// um, grep
|
234
238
|
grep: function (arr, fn) {
|
235
239
|
return arr.findAll(fn);
|
@@ -2,7 +2,7 @@
|
|
2
2
|
// @compilation_level SIMPLE_OPTIMIZATIONS
|
3
3
|
|
4
4
|
/**
|
5
|
-
* @license Highcharts JS v2.2.
|
5
|
+
* @license Highcharts JS v2.2.2 (2012-04-26)
|
6
6
|
*
|
7
7
|
* (c) 2009-2011 Torstein Hønsi
|
8
8
|
*
|
@@ -124,6 +124,7 @@ var UNDEFINED,
|
|
124
124
|
addEvent = adapter.addEvent,
|
125
125
|
removeEvent = adapter.removeEvent,
|
126
126
|
fireEvent = adapter.fireEvent,
|
127
|
+
washMouseEvent = adapter.washMouseEvent,
|
127
128
|
animate = adapter.animate,
|
128
129
|
stop = adapter.stop,
|
129
130
|
|
@@ -497,10 +498,10 @@ function normalizeTickInterval(interval, multiples, magnitude, options) {
|
|
497
498
|
|
498
499
|
/**
|
499
500
|
* Get a normalized tick interval for dates. Returns a configuration object with
|
500
|
-
* unit range (interval), count and name. Used to prepare data for getTimeTicks.
|
501
|
+
* unit range (interval), count and name. Used to prepare data for getTimeTicks.
|
501
502
|
* Previously this logic was part of getTimeTicks, but as getTimeTicks now runs
|
502
|
-
* of segments in stock charts, the normalizing logic was extracted in order to
|
503
|
-
* prevent it for running over again for each segment having the same interval.
|
503
|
+
* of segments in stock charts, the normalizing logic was extracted in order to
|
504
|
+
* prevent it for running over again for each segment having the same interval.
|
504
505
|
* #662, #697.
|
505
506
|
*/
|
506
507
|
function normalizeTimeTickInterval(tickInterval, unitsOption) {
|
@@ -534,7 +535,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
|
|
534
535
|
multiples = unit[1],
|
535
536
|
count,
|
536
537
|
i;
|
537
|
-
|
538
|
+
|
538
539
|
// loop through the units to find the one that best fits the tickInterval
|
539
540
|
for (i = 0; i < units.length; i++) {
|
540
541
|
unit = units[i];
|
@@ -558,7 +559,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
|
|
558
559
|
if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {
|
559
560
|
multiples = [1, 2, 5];
|
560
561
|
}
|
561
|
-
|
562
|
+
|
562
563
|
// prevent 2.5 years intervals, though 25, 250 etc. are allowed
|
563
564
|
if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {
|
564
565
|
multiples = [1, 2, 5];
|
@@ -566,7 +567,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
|
|
566
567
|
|
567
568
|
// get the count
|
568
569
|
count = normalizeTickInterval(tickInterval / interval, multiples);
|
569
|
-
|
570
|
+
|
570
571
|
return {
|
571
572
|
unitRange: interval,
|
572
573
|
count: count,
|
@@ -595,7 +596,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
|
|
595
596
|
interval = normalizedInterval.unitRange,
|
596
597
|
count = normalizedInterval.count;
|
597
598
|
|
598
|
-
|
599
|
+
|
599
600
|
|
600
601
|
if (interval >= timeUnits[SECOND]) { // second
|
601
602
|
minDate.setMilliseconds(0);
|
@@ -665,7 +666,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
|
|
665
666
|
// else, the interval is fixed and we use simple addition
|
666
667
|
} else {
|
667
668
|
time += interval * count;
|
668
|
-
|
669
|
+
|
669
670
|
// mark new days if the time is dividable by day
|
670
671
|
if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === 0) {
|
671
672
|
higherRanks[time] = DAY;
|
@@ -674,7 +675,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
|
|
674
675
|
|
675
676
|
i++;
|
676
677
|
}
|
677
|
-
|
678
|
+
|
678
679
|
// push the last time
|
679
680
|
tickPositions.push(time);
|
680
681
|
|
@@ -720,7 +721,7 @@ ChartCounters.prototype = {
|
|
720
721
|
* and not covering the point it self.
|
721
722
|
*/
|
722
723
|
function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point, distance, preferRight) {
|
723
|
-
|
724
|
+
|
724
725
|
// keep the box within the chart area
|
725
726
|
var pointX = point.x,
|
726
727
|
pointY = point.y,
|
@@ -749,10 +750,15 @@ function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHei
|
|
749
750
|
if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) {
|
750
751
|
y = pointY + outerTop + distance; // below
|
751
752
|
}
|
752
|
-
}
|
753
|
+
}
|
754
|
+
|
755
|
+
// Now if the tooltip is below the chart, move it up. It's better to cover the
|
756
|
+
// point than to disappear outside the chart. #834.
|
757
|
+
if (y + boxHeight > outerTop + outerHeight) {
|
753
758
|
y = outerTop + outerHeight - boxHeight - distance; // below
|
754
759
|
}
|
755
760
|
|
761
|
+
|
756
762
|
return {x: x, y: y};
|
757
763
|
}
|
758
764
|
|
@@ -853,7 +859,7 @@ function discardElement(element) {
|
|
853
859
|
}
|
854
860
|
|
855
861
|
/**
|
856
|
-
* Provide error messages for debugging, with links to online explanation
|
862
|
+
* Provide error messages for debugging, with links to online explanation
|
857
863
|
*/
|
858
864
|
function error(code, stop) {
|
859
865
|
var msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code;
|
@@ -929,9 +935,10 @@ pathAnim = {
|
|
929
935
|
}
|
930
936
|
|
931
937
|
// if shifting points, prepend a dummy point to the end path
|
932
|
-
if (shift
|
933
|
-
|
934
|
-
|
938
|
+
if (shift <= end.length / numParams) {
|
939
|
+
while (shift--) {
|
940
|
+
end = [].concat(end).splice(0, numParams).concat(end);
|
941
|
+
}
|
935
942
|
}
|
936
943
|
elem.shift = 0; // reset for following animations
|
937
944
|
|
@@ -1145,6 +1152,13 @@ if (!globalAdapter && win.jQuery) {
|
|
1145
1152
|
}
|
1146
1153
|
};
|
1147
1154
|
|
1155
|
+
/**
|
1156
|
+
* Extension method needed for MooTools
|
1157
|
+
*/
|
1158
|
+
washMouseEvent = function (e) {
|
1159
|
+
return e;
|
1160
|
+
};
|
1161
|
+
|
1148
1162
|
/**
|
1149
1163
|
* Animate a HTML element or SVG element wrapper
|
1150
1164
|
* @param {Object} el
|
@@ -1270,7 +1284,7 @@ defaultOptions = {
|
|
1270
1284
|
},
|
1271
1285
|
global: {
|
1272
1286
|
useUTC: true,
|
1273
|
-
canvasToolsURL: 'http://code.highcharts.com/2.2.
|
1287
|
+
canvasToolsURL: 'http://code.highcharts.com/2.2.2/modules/canvas-tools.js'
|
1274
1288
|
},
|
1275
1289
|
chart: {
|
1276
1290
|
//animation: true,
|
@@ -1418,7 +1432,7 @@ defaultOptions = {
|
|
1418
1432
|
//valueDecimals: null,
|
1419
1433
|
//xDateFormat: '%A, %b %e, %Y',
|
1420
1434
|
//valuePrefix: '',
|
1421
|
-
//ySuffix: ''
|
1435
|
+
//ySuffix: ''
|
1422
1436
|
//}
|
1423
1437
|
// turboThreshold: 1000
|
1424
1438
|
// zIndex: null
|
@@ -1673,8 +1687,8 @@ defaultBottomAxisOptions = { // horizontal axis
|
|
1673
1687
|
labels: {
|
1674
1688
|
align: 'center',
|
1675
1689
|
x: 0,
|
1676
|
-
y: 14
|
1677
|
-
overflow:
|
1690
|
+
y: 14
|
1691
|
+
// overflow: undefined // docs - can be 'justify'
|
1678
1692
|
// staggerLines: null
|
1679
1693
|
},
|
1680
1694
|
title: {
|
@@ -1831,15 +1845,15 @@ function setTimeMethods() {
|
|
1831
1845
|
* @param {Object} options The new custom options
|
1832
1846
|
*/
|
1833
1847
|
function setOptions(options) {
|
1834
|
-
|
1835
|
-
// Pull out axis options and apply them to the respective default axis options
|
1848
|
+
|
1849
|
+
// Pull out axis options and apply them to the respective default axis options
|
1836
1850
|
defaultXAxisOptions = merge(defaultXAxisOptions, options.xAxis);
|
1837
1851
|
defaultYAxisOptions = merge(defaultYAxisOptions, options.yAxis);
|
1838
1852
|
options.xAxis = options.yAxis = UNDEFINED;
|
1839
|
-
|
1853
|
+
|
1840
1854
|
// Merge in the default options
|
1841
1855
|
defaultOptions = merge(defaultOptions, options);
|
1842
|
-
|
1856
|
+
|
1843
1857
|
// Apply UTC
|
1844
1858
|
setTimeMethods();
|
1845
1859
|
|
@@ -2008,6 +2022,7 @@ SVGElement.prototype = {
|
|
2008
2022
|
nodeName = element.nodeName,
|
2009
2023
|
renderer = wrapper.renderer,
|
2010
2024
|
skipAttr,
|
2025
|
+
titleNode,
|
2011
2026
|
attrSetters = wrapper.attrSetters,
|
2012
2027
|
shadows = wrapper.shadows,
|
2013
2028
|
hasSetSymbolSize,
|
@@ -2143,9 +2158,12 @@ SVGElement.prototype = {
|
|
2143
2158
|
|
2144
2159
|
// Title requires a subnode, #431
|
2145
2160
|
} else if (key === 'title') {
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2161
|
+
titleNode = element.getElementsByTagName('title')[0];
|
2162
|
+
if (!titleNode) {
|
2163
|
+
titleNode = doc.createElementNS(SVG_NS, 'title');
|
2164
|
+
element.appendChild(titleNode);
|
2165
|
+
}
|
2166
|
+
titleNode.textContent = value;
|
2149
2167
|
}
|
2150
2168
|
|
2151
2169
|
// jQuery animate changes case
|
@@ -2159,7 +2177,7 @@ SVGElement.prototype = {
|
|
2159
2177
|
}
|
2160
2178
|
|
2161
2179
|
// symbols
|
2162
|
-
if (wrapper.symbolName && /^(x|y|r|start|end|innerR|anchorX|anchorY)/.test(key)) {
|
2180
|
+
if (wrapper.symbolName && /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(key)) {
|
2163
2181
|
|
2164
2182
|
|
2165
2183
|
if (!hasSetSymbolSize) {
|
@@ -2200,14 +2218,14 @@ SVGElement.prototype = {
|
|
2200
2218
|
}
|
2201
2219
|
|
2202
2220
|
}
|
2203
|
-
|
2221
|
+
|
2204
2222
|
// Workaround for our #732, WebKit's issue https://bugs.webkit.org/show_bug.cgi?id=78385
|
2205
2223
|
// TODO: If the WebKit team fix this bug before the final release of Chrome 18, remove the workaround.
|
2206
2224
|
if (isWebKit && /Chrome\/(18|19)/.test(userAgent)) {
|
2207
2225
|
if (nodeName === 'text' && (hash.x !== UNDEFINED || hash.y !== UNDEFINED)) {
|
2208
2226
|
var parent = element.parentNode,
|
2209
2227
|
next = element.nextSibling;
|
2210
|
-
|
2228
|
+
|
2211
2229
|
if (parent) {
|
2212
2230
|
parent.removeChild(element);
|
2213
2231
|
if (next) {
|
@@ -2219,7 +2237,7 @@ SVGElement.prototype = {
|
|
2219
2237
|
}
|
2220
2238
|
}
|
2221
2239
|
// End of workaround for #732
|
2222
|
-
|
2240
|
+
|
2223
2241
|
return ret;
|
2224
2242
|
},
|
2225
2243
|
|
@@ -2678,7 +2696,7 @@ SVGElement.prototype = {
|
|
2678
2696
|
// SVG elements
|
2679
2697
|
if (element.namespaceURI === SVG_NS) {
|
2680
2698
|
try { // Fails in Firefox if the container has display: none.
|
2681
|
-
|
2699
|
+
|
2682
2700
|
bBox = element.getBBox ?
|
2683
2701
|
// SVG: use extend because IE9 is not allowed to change width and height in case
|
2684
2702
|
// of rotation (below)
|
@@ -2689,13 +2707,13 @@ SVGElement.prototype = {
|
|
2689
2707
|
height: element.offsetHeight
|
2690
2708
|
};
|
2691
2709
|
} catch (e) {}
|
2692
|
-
|
2710
|
+
|
2693
2711
|
// If the bBox is not set, the try-catch block above failed. The other condition
|
2694
2712
|
// is for Opera that returns a width of -Infinity on hidden elements.
|
2695
2713
|
if (!bBox || bBox.width < 0) {
|
2696
2714
|
bBox = { width: 0, height: 0 };
|
2697
2715
|
}
|
2698
|
-
|
2716
|
+
|
2699
2717
|
width = bBox.width;
|
2700
2718
|
height = bBox.height;
|
2701
2719
|
|
@@ -2951,6 +2969,32 @@ SVGRenderer.prototype = {
|
|
2951
2969
|
renderer.gradients = {}; // Object where gradient SvgElements are stored
|
2952
2970
|
|
2953
2971
|
renderer.setSize(width, height, false);
|
2972
|
+
|
2973
|
+
|
2974
|
+
|
2975
|
+
// Issue 110 workaround:
|
2976
|
+
// In Firefox, if a div is positioned by percentage, its pixel position may land
|
2977
|
+
// between pixels. The container itself doesn't display this, but an SVG element
|
2978
|
+
// inside this container will be drawn at subpixel precision. In order to draw
|
2979
|
+
// sharp lines, this must be compensated for. This doesn't seem to work inside
|
2980
|
+
// iframes though (like in jsFiddle).
|
2981
|
+
var subPixelFix, rect;
|
2982
|
+
if (isFirefox && container.getBoundingClientRect) {
|
2983
|
+
renderer.subPixelFix = subPixelFix = function () {
|
2984
|
+
css(container, { left: 0, top: 0 });
|
2985
|
+
rect = container.getBoundingClientRect();
|
2986
|
+
css(container, {
|
2987
|
+
left: (-(rect.left - pInt(rect.left))) + PX,
|
2988
|
+
top: (-(rect.top - pInt(rect.top))) + PX
|
2989
|
+
});
|
2990
|
+
};
|
2991
|
+
|
2992
|
+
// run the fix now
|
2993
|
+
subPixelFix();
|
2994
|
+
|
2995
|
+
// run it on resize
|
2996
|
+
addEvent(win, 'resize', subPixelFix);
|
2997
|
+
}
|
2954
2998
|
},
|
2955
2999
|
|
2956
3000
|
/**
|
@@ -2972,6 +3016,9 @@ SVGRenderer.prototype = {
|
|
2972
3016
|
renderer.defs = rendererDefs.destroy();
|
2973
3017
|
}
|
2974
3018
|
|
3019
|
+
// Remove sub pixel fix handler
|
3020
|
+
removeEvent(win, 'resize', renderer.subPixelFix);
|
3021
|
+
|
2975
3022
|
renderer.alignedObjects = null;
|
2976
3023
|
|
2977
3024
|
return null;
|
@@ -3014,7 +3061,14 @@ SVGRenderer.prototype = {
|
|
3014
3061
|
textLineHeight = textStyles && textStyles.lineHeight,
|
3015
3062
|
lastLine,
|
3016
3063
|
GET_COMPUTED_STYLE = 'getComputedStyle',
|
3017
|
-
i = childNodes.length
|
3064
|
+
i = childNodes.length,
|
3065
|
+
linePositions = [];
|
3066
|
+
|
3067
|
+
// Needed in IE9 because it doesn't report tspan's offsetHeight (#893)
|
3068
|
+
function getLineHeightByBBox(lineNo) {
|
3069
|
+
linePositions[lineNo] = textNode.getBBox().height;
|
3070
|
+
return mathRound(linePositions[lineNo] - (linePositions[lineNo - 1] || 0));
|
3071
|
+
}
|
3018
3072
|
|
3019
3073
|
// remove old text
|
3020
3074
|
while (i--) {
|
@@ -3092,7 +3146,7 @@ SVGRenderer.prototype = {
|
|
3092
3146
|
pInt(win[GET_COMPUTED_STYLE](lastLine, null).getPropertyValue('line-height'));
|
3093
3147
|
|
3094
3148
|
if (!lineHeight || isNaN(lineHeight)) {
|
3095
|
-
lineHeight = textLineHeight || lastLine.offsetHeight || 18;
|
3149
|
+
lineHeight = textLineHeight || lastLine.offsetHeight || getLineHeightByBBox(lineNo) || 18;
|
3096
3150
|
}
|
3097
3151
|
attr(tspan, 'dy', lineHeight);
|
3098
3152
|
}
|
@@ -3453,7 +3507,8 @@ SVGRenderer.prototype = {
|
|
3453
3507
|
|
3454
3508
|
imageRegex = /^url\((.*?)\)$/,
|
3455
3509
|
imageSrc,
|
3456
|
-
imageSize
|
3510
|
+
imageSize,
|
3511
|
+
centerImage;
|
3457
3512
|
|
3458
3513
|
if (path) {
|
3459
3514
|
|
@@ -3474,14 +3529,19 @@ SVGRenderer.prototype = {
|
|
3474
3529
|
// image symbols
|
3475
3530
|
} else if (imageRegex.test(symbol)) {
|
3476
3531
|
|
3477
|
-
|
3532
|
+
// On image load, set the size and position
|
3533
|
+
centerImage = function (img, size) {
|
3478
3534
|
img.attr({
|
3479
3535
|
width: size[0],
|
3480
3536
|
height: size[1]
|
3481
|
-
})
|
3482
|
-
|
3483
|
-
|
3484
|
-
|
3537
|
+
});
|
3538
|
+
|
3539
|
+
if (!img.alignByTranslate) { // #185
|
3540
|
+
img.translate(
|
3541
|
+
-mathRound(size[0] / 2),
|
3542
|
+
-mathRound(size[1] / 2)
|
3543
|
+
);
|
3544
|
+
}
|
3485
3545
|
};
|
3486
3546
|
|
3487
3547
|
imageSrc = symbol.match(imageRegex)[1];
|
@@ -3865,14 +3925,14 @@ SVGRenderer.prototype = {
|
|
3865
3925
|
*/
|
3866
3926
|
fontMetrics: function (fontSize) {
|
3867
3927
|
fontSize = pInt(fontSize || 11);
|
3868
|
-
|
3928
|
+
|
3869
3929
|
// Empirical values found by comparing font size and bounding box height.
|
3870
3930
|
// Applies to the default font family. http://jsfiddle.net/highcharts/7xvn7/
|
3871
3931
|
var lineHeight = fontSize < 24 ? fontSize + 4 : mathRound(fontSize * 1.2),
|
3872
3932
|
baseline = mathRound(lineHeight * 0.8);
|
3873
|
-
|
3933
|
+
|
3874
3934
|
return {
|
3875
|
-
h: lineHeight,
|
3935
|
+
h: lineHeight,
|
3876
3936
|
b: baseline
|
3877
3937
|
};
|
3878
3938
|
},
|
@@ -3888,12 +3948,13 @@ SVGRenderer.prototype = {
|
|
3888
3948
|
* coordinates it should be pinned to
|
3889
3949
|
* @param {Number} anchorY
|
3890
3950
|
* @param {Boolean} baseline Whether to position the label relative to the text baseline,
|
3891
|
-
* like renderer.text, or to the upper border of the rectangle.
|
3951
|
+
* like renderer.text, or to the upper border of the rectangle.
|
3952
|
+
* @param {String} className Class name for the group
|
3892
3953
|
*/
|
3893
|
-
label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline) {
|
3954
|
+
label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
|
3894
3955
|
|
3895
3956
|
var renderer = this,
|
3896
|
-
wrapper = renderer.g(),
|
3957
|
+
wrapper = renderer.g(className),
|
3897
3958
|
text = renderer.text('', 0, 0, useHTML)
|
3898
3959
|
.attr({
|
3899
3960
|
zIndex: 1
|
@@ -3901,7 +3962,7 @@ SVGRenderer.prototype = {
|
|
3901
3962
|
.add(wrapper),
|
3902
3963
|
box,
|
3903
3964
|
bBox,
|
3904
|
-
|
3965
|
+
alignFactor = 0,
|
3905
3966
|
padding = 3,
|
3906
3967
|
width,
|
3907
3968
|
height,
|
@@ -3920,23 +3981,23 @@ SVGRenderer.prototype = {
|
|
3920
3981
|
function updateBoxSize() {
|
3921
3982
|
var boxY,
|
3922
3983
|
style = text.element.style;
|
3923
|
-
|
3984
|
+
|
3924
3985
|
bBox = (width === undefined || height === undefined || wrapper.styles.textAlign) &&
|
3925
3986
|
text.getBBox(true);
|
3926
|
-
wrapper.width = (width || bBox.width) + 2 * padding;
|
3927
|
-
wrapper.height = (height || bBox.height) + 2 * padding;
|
3928
|
-
|
3987
|
+
wrapper.width = (width || bBox.width || 0) + 2 * padding;
|
3988
|
+
wrapper.height = (height || bBox.height || 0) + 2 * padding;
|
3989
|
+
|
3929
3990
|
// update the label-scoped y offset
|
3930
3991
|
baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b;
|
3931
|
-
|
3932
|
-
|
3992
|
+
|
3993
|
+
|
3933
3994
|
// create the border box if it is not already present
|
3934
3995
|
if (!box) {
|
3935
3996
|
boxY = baseline ? -baselineOffset : 0;
|
3936
|
-
|
3997
|
+
|
3937
3998
|
wrapper.box = box = shape ?
|
3938
|
-
renderer.symbol(shape,
|
3939
|
-
renderer.rect(
|
3999
|
+
renderer.symbol(shape, -alignFactor * padding, boxY, wrapper.width, wrapper.height) :
|
4000
|
+
renderer.rect(-alignFactor * padding, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);
|
3940
4001
|
box.add(wrapper);
|
3941
4002
|
}
|
3942
4003
|
|
@@ -3954,9 +4015,9 @@ SVGRenderer.prototype = {
|
|
3954
4015
|
function updateTextPadding() {
|
3955
4016
|
var styles = wrapper.styles,
|
3956
4017
|
textAlign = styles && styles.textAlign,
|
3957
|
-
x = padding,
|
4018
|
+
x = padding * (1 - alignFactor),
|
3958
4019
|
y;
|
3959
|
-
|
4020
|
+
|
3960
4021
|
// determin y based on the baseline
|
3961
4022
|
y = baseline ? 0 : baselineOffset;
|
3962
4023
|
|
@@ -4031,10 +4092,10 @@ SVGRenderer.prototype = {
|
|
4031
4092
|
|
4032
4093
|
// change local variable and set attribue as well
|
4033
4094
|
attrSetters.align = function (value) {
|
4034
|
-
|
4095
|
+
alignFactor = { left: 0, center: 0.5, right: 1 }[value];
|
4035
4096
|
return false; // prevent setting text-anchor on the group
|
4036
4097
|
};
|
4037
|
-
|
4098
|
+
|
4038
4099
|
// apply these to the box and the text alike
|
4039
4100
|
attrSetters.text = function (value, key) {
|
4040
4101
|
text.attr(key, value);
|
@@ -4063,12 +4124,13 @@ SVGRenderer.prototype = {
|
|
4063
4124
|
boxAttr(key, value - wrapperY);
|
4064
4125
|
return false;
|
4065
4126
|
};
|
4066
|
-
|
4127
|
+
|
4067
4128
|
// rename attributes
|
4068
4129
|
attrSetters.x = function (value) {
|
4069
|
-
|
4070
|
-
|
4071
|
-
|
4130
|
+
wrapper.x = value; // for animation getter
|
4131
|
+
value -= alignFactor * ((width || bBox.width) + padding);
|
4132
|
+
wrapperX = mathRound(value);
|
4133
|
+
|
4072
4134
|
wrapper.attr('translateX', wrapperX);
|
4073
4135
|
return false;
|
4074
4136
|
};
|
@@ -4239,12 +4301,12 @@ var VMLElement = {
|
|
4239
4301
|
toggleChildren: function (element, visibility) {
|
4240
4302
|
var childNodes = element.childNodes,
|
4241
4303
|
i = childNodes.length;
|
4242
|
-
|
4304
|
+
|
4243
4305
|
while (i--) {
|
4244
|
-
|
4306
|
+
|
4245
4307
|
// apply the visibility
|
4246
4308
|
css(childNodes[i], { visibility: visibility });
|
4247
|
-
|
4309
|
+
|
4248
4310
|
// we have a nested group, apply it to its children again
|
4249
4311
|
if (childNodes[i].nodeName === 'DIV') {
|
4250
4312
|
this.toggleChildren(childNodes[i], visibility);
|
@@ -4377,9 +4439,9 @@ var VMLElement = {
|
|
4377
4439
|
|
4378
4440
|
// width and height
|
4379
4441
|
} else if (key === 'width' || key === 'height') {
|
4380
|
-
|
4442
|
+
|
4381
4443
|
value = mathMax(0, value); // don't set width or height below zero (#311)
|
4382
|
-
|
4444
|
+
|
4383
4445
|
this[key] = value; // used in getter
|
4384
4446
|
|
4385
4447
|
// clipping rectangle special
|
@@ -4487,12 +4549,19 @@ var VMLElement = {
|
|
4487
4549
|
*/
|
4488
4550
|
clip: function (clipRect) {
|
4489
4551
|
var wrapper = this,
|
4490
|
-
clipMembers = clipRect.members
|
4552
|
+
clipMembers = clipRect.members,
|
4553
|
+
element = wrapper.element;
|
4491
4554
|
|
4492
4555
|
clipMembers.push(wrapper);
|
4493
4556
|
wrapper.destroyClip = function () {
|
4494
4557
|
erase(clipMembers, wrapper);
|
4495
4558
|
};
|
4559
|
+
|
4560
|
+
// Issue #863 workaround - related to #140, #61, #74
|
4561
|
+
if (element.parentNode.className === 'highcharts-tracker' && !docMode8) {
|
4562
|
+
css(element, { visibility: HIDDEN });
|
4563
|
+
}
|
4564
|
+
|
4496
4565
|
return wrapper.css(clipRect.getCSS(wrapper.inverted));
|
4497
4566
|
},
|
4498
4567
|
|
@@ -4706,6 +4775,7 @@ var VMLRendererExtension = { // inherit SVGRenderer
|
|
4706
4775
|
height: bottom + PX
|
4707
4776
|
});
|
4708
4777
|
}
|
4778
|
+
|
4709
4779
|
return ret;
|
4710
4780
|
},
|
4711
4781
|
|
@@ -4772,15 +4842,15 @@ var VMLRendererExtension = { // inherit SVGRenderer
|
|
4772
4842
|
(y2 - y1) / // y vector
|
4773
4843
|
(x2 - x1) // x vector
|
4774
4844
|
) * 180 / mathPI;
|
4775
|
-
|
4776
|
-
|
4845
|
+
|
4846
|
+
|
4777
4847
|
// when colors attribute is used, the meanings of opacity and o:opacity2
|
4778
4848
|
// are reversed.
|
4779
4849
|
markup = ['<fill colors="0% ', color1, ',100% ', color2, '" angle="', angle,
|
4780
4850
|
'" opacity="', opacity2, '" o:opacity2="', opacity1,
|
4781
4851
|
'" type="gradient" focus="100%" method="sigma" />'];
|
4782
4852
|
createElement(this.prepVML(markup), null, null, elem);
|
4783
|
-
|
4853
|
+
|
4784
4854
|
// Gradients are not supported for VML stroke, return the first color. #722.
|
4785
4855
|
} else {
|
4786
4856
|
return stopColor;
|
@@ -5175,7 +5245,7 @@ function Chart(userOptions, callback) {
|
|
5175
5245
|
userOptions.series = null;
|
5176
5246
|
options = merge(defaultOptions, userOptions); // do the merge
|
5177
5247
|
options.series = userOptions.series = seriesOptions; // set back the series data
|
5178
|
-
|
5248
|
+
|
5179
5249
|
var optionsChart = options.chart,
|
5180
5250
|
optionsMargin = optionsChart.margin,
|
5181
5251
|
margin = isObject(optionsMargin) ?
|
@@ -5451,10 +5521,10 @@ function Chart(userOptions, callback) {
|
|
5451
5521
|
getLabelSize: function () {
|
5452
5522
|
var label = this.label;
|
5453
5523
|
return label ?
|
5454
|
-
((this.labelBBox = label.getBBox()))[horiz ? 'height' : 'width'] :
|
5524
|
+
((this.labelBBox = label.getBBox(true)))[horiz ? 'height' : 'width'] :
|
5455
5525
|
0;
|
5456
5526
|
},
|
5457
|
-
|
5527
|
+
|
5458
5528
|
/**
|
5459
5529
|
* Find how far the labels extend to the right and left of the tick's x position. Used for anti-collision
|
5460
5530
|
* detection with overflow logic.
|
@@ -5464,10 +5534,10 @@ function Chart(userOptions, callback) {
|
|
5464
5534
|
labelOptions = options.labels,
|
5465
5535
|
width = bBox.width,
|
5466
5536
|
leftSide = width * { left: 0, center: 0.5, right: 1 }[labelOptions.align] - labelOptions.x;
|
5467
|
-
|
5468
|
-
return [-leftSide, width - leftSide];
|
5537
|
+
|
5538
|
+
return [-leftSide, width - leftSide];
|
5469
5539
|
},
|
5470
|
-
|
5540
|
+
|
5471
5541
|
/**
|
5472
5542
|
* Handle the label overflow by adjusting the labels to the left and right edge, or
|
5473
5543
|
* hide them if they collide into the neighbour label.
|
@@ -5478,9 +5548,9 @@ function Chart(userOptions, callback) {
|
|
5478
5548
|
isLast = this.isLast,
|
5479
5549
|
label = this.label,
|
5480
5550
|
x = label.x;
|
5481
|
-
|
5551
|
+
|
5482
5552
|
if (isFirst || isLast) {
|
5483
|
-
|
5553
|
+
|
5484
5554
|
var sides = this.getLabelSides(),
|
5485
5555
|
leftSide = sides[0],
|
5486
5556
|
rightSide = sides[1],
|
@@ -5488,41 +5558,41 @@ function Chart(userOptions, callback) {
|
|
5488
5558
|
plotRight = plotLeft + axis.len,
|
5489
5559
|
neighbour = ticks[tickPositions[index + (isFirst ? 1 : -1)]],
|
5490
5560
|
neighbourEdge = neighbour && neighbour.label.x + neighbour.getLabelSides()[isFirst ? 0 : 1];
|
5491
|
-
|
5561
|
+
|
5492
5562
|
if ((isFirst && !reversed) || (isLast && reversed)) {
|
5493
5563
|
// Is the label spilling out to the left of the plot area?
|
5494
5564
|
if (x + leftSide < plotLeft) {
|
5495
|
-
|
5565
|
+
|
5496
5566
|
// Align it to plot left
|
5497
5567
|
x = plotLeft - leftSide;
|
5498
|
-
|
5568
|
+
|
5499
5569
|
// Hide it if it now overlaps the neighbour label
|
5500
5570
|
if (neighbour && x + rightSide > neighbourEdge) {
|
5501
5571
|
show = false;
|
5502
5572
|
}
|
5503
5573
|
}
|
5504
|
-
|
5574
|
+
|
5505
5575
|
} else {
|
5506
5576
|
// Is the label spilling out to the right of the plot area?
|
5507
5577
|
if (x + rightSide > plotRight) {
|
5508
|
-
|
5578
|
+
|
5509
5579
|
// Align it to plot right
|
5510
5580
|
x = plotRight - rightSide;
|
5511
|
-
|
5581
|
+
|
5512
5582
|
// Hide it if it now overlaps the neighbour label
|
5513
5583
|
if (neighbour && x + leftSide < neighbourEdge) {
|
5514
5584
|
show = false;
|
5515
5585
|
}
|
5516
|
-
|
5586
|
+
|
5517
5587
|
}
|
5518
5588
|
}
|
5519
|
-
|
5589
|
+
|
5520
5590
|
// Set the modified x position of the label
|
5521
5591
|
label.x = x;
|
5522
5592
|
}
|
5523
5593
|
return show;
|
5524
5594
|
},
|
5525
|
-
|
5595
|
+
|
5526
5596
|
/**
|
5527
5597
|
* Put everything in place
|
5528
5598
|
*
|
@@ -5589,7 +5659,7 @@ function Chart(userOptions, callback) {
|
|
5589
5659
|
// If the parameter 'old' is set, the current call will be followed
|
5590
5660
|
// by another call, therefore do not do any animations this time
|
5591
5661
|
if (!old && gridLine && gridLinePath) {
|
5592
|
-
gridLine.animate({
|
5662
|
+
gridLine[tick.isNew ? 'attr' : 'animate']({
|
5593
5663
|
d: gridLinePath
|
5594
5664
|
});
|
5595
5665
|
}
|
@@ -5646,7 +5716,7 @@ function Chart(userOptions, callback) {
|
|
5646
5716
|
if (staggerLines) {
|
5647
5717
|
y += (index / (step || 1) % staggerLines) * 16;
|
5648
5718
|
}
|
5649
|
-
|
5719
|
+
|
5650
5720
|
// Cache x and y to be able to read final position before animation
|
5651
5721
|
label.x = x;
|
5652
5722
|
label.y = y;
|
@@ -5655,9 +5725,9 @@ function Chart(userOptions, callback) {
|
|
5655
5725
|
if ((tick.isFirst && !pick(options.showFirstLabel, 1)) ||
|
5656
5726
|
(tick.isLast && !pick(options.showLastLabel, 1))) {
|
5657
5727
|
show = false;
|
5658
|
-
|
5728
|
+
|
5659
5729
|
// Handle label overflow and show or hide accordingly
|
5660
|
-
} else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index)) {
|
5730
|
+
} else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index)) {
|
5661
5731
|
show = false;
|
5662
5732
|
}
|
5663
5733
|
|
@@ -5666,7 +5736,7 @@ function Chart(userOptions, callback) {
|
|
5666
5736
|
// show those indices dividable by step
|
5667
5737
|
show = false;
|
5668
5738
|
}
|
5669
|
-
|
5739
|
+
|
5670
5740
|
// Set the new position, and show or hide
|
5671
5741
|
if (show) {
|
5672
5742
|
label[tick.isNew ? 'attr' : 'animate']({
|
@@ -5680,9 +5750,9 @@ function Chart(userOptions, callback) {
|
|
5680
5750
|
}
|
5681
5751
|
}
|
5682
5752
|
|
5683
|
-
|
5753
|
+
|
5684
5754
|
},
|
5685
|
-
|
5755
|
+
|
5686
5756
|
/**
|
5687
5757
|
* Destructor for the tick prototype
|
5688
5758
|
*/
|
@@ -5997,7 +6067,7 @@ function Chart(userOptions, callback) {
|
|
5997
6067
|
yDataLength,
|
5998
6068
|
activeYData = [],
|
5999
6069
|
activeCounter = 0;
|
6000
|
-
|
6070
|
+
|
6001
6071
|
// Validate threshold in logarithmic axes
|
6002
6072
|
if (isLog && threshold <= 0) {
|
6003
6073
|
threshold = seriesOptions.threshold = null;
|
@@ -6148,7 +6218,7 @@ function Chart(userOptions, callback) {
|
|
6148
6218
|
*
|
6149
6219
|
*/
|
6150
6220
|
translate = function (val, backwards, cvsCoord, old, handleLog) {
|
6151
|
-
|
6221
|
+
|
6152
6222
|
var sign = 1,
|
6153
6223
|
cvsOffset = 0,
|
6154
6224
|
localA = old ? oldTransA : transA,
|
@@ -6263,28 +6333,28 @@ function Chart(userOptions, callback) {
|
|
6263
6333
|
}
|
6264
6334
|
return tickPositions;
|
6265
6335
|
}
|
6266
|
-
|
6336
|
+
|
6267
6337
|
/**
|
6268
6338
|
* Set the tick positions of a logarithmic axis
|
6269
6339
|
*/
|
6270
6340
|
function getLogTickPositions(interval, min, max, minor) {
|
6271
|
-
|
6341
|
+
|
6272
6342
|
// Since we use this method for both major and minor ticks,
|
6273
6343
|
// use a local variable and return the result
|
6274
|
-
var positions = [];
|
6275
|
-
|
6344
|
+
var positions = [];
|
6345
|
+
|
6276
6346
|
// Reset
|
6277
6347
|
if (!minor) {
|
6278
6348
|
axis._minorAutoInterval = null;
|
6279
6349
|
}
|
6280
|
-
|
6350
|
+
|
6281
6351
|
// First case: All ticks fall on whole logarithms: 1, 10, 100 etc.
|
6282
6352
|
if (interval >= 0.5) {
|
6283
6353
|
interval = mathRound(interval);
|
6284
6354
|
positions = getLinearTickPositions(interval, min, max);
|
6285
|
-
|
6286
|
-
// Second case: We need intermediary ticks. For example
|
6287
|
-
// 1, 2, 4, 6, 8, 10, 20, 40 etc.
|
6355
|
+
|
6356
|
+
// Second case: We need intermediary ticks. For example
|
6357
|
+
// 1, 2, 4, 6, 8, 10, 20, 40 etc.
|
6288
6358
|
} else if (interval >= 0.08) {
|
6289
6359
|
var roundedMin = mathFloor(min),
|
6290
6360
|
intermediate,
|
@@ -6294,7 +6364,7 @@ function Chart(userOptions, callback) {
|
|
6294
6364
|
pos,
|
6295
6365
|
lastPos,
|
6296
6366
|
break2;
|
6297
|
-
|
6367
|
+
|
6298
6368
|
if (interval > 0.3) {
|
6299
6369
|
intermediate = [1, 2, 4];
|
6300
6370
|
} else if (interval > 0.15) { // 0.2 equals five minor ticks per 1, 10, 100 etc
|
@@ -6302,23 +6372,23 @@ function Chart(userOptions, callback) {
|
|
6302
6372
|
} else { // 0.1 equals ten minor ticks per 1, 10, 100 etc
|
6303
6373
|
intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
6304
6374
|
}
|
6305
|
-
|
6375
|
+
|
6306
6376
|
for (i = roundedMin; i < max + 1 && !break2; i++) {
|
6307
6377
|
len = intermediate.length;
|
6308
6378
|
for (j = 0; j < len && !break2; j++) {
|
6309
6379
|
pos = log2lin(lin2log(i) * intermediate[j]);
|
6310
|
-
|
6380
|
+
|
6311
6381
|
if (pos > min) {
|
6312
6382
|
positions.push(lastPos);
|
6313
6383
|
}
|
6314
|
-
|
6384
|
+
|
6315
6385
|
if (lastPos > max) {
|
6316
6386
|
break2 = true;
|
6317
6387
|
}
|
6318
6388
|
lastPos = pos;
|
6319
6389
|
}
|
6320
6390
|
}
|
6321
|
-
|
6391
|
+
|
6322
6392
|
// Third case: We are so deep in between whole logarithmic values that
|
6323
6393
|
// we might as well handle the tick positions like a linear axis. For
|
6324
6394
|
// example 1.01, 1.02, 1.03, 1.04.
|
@@ -6329,37 +6399,37 @@ function Chart(userOptions, callback) {
|
|
6329
6399
|
filteredTickIntervalOption = tickIntervalOption === 'auto' ? null : tickIntervalOption,
|
6330
6400
|
tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1),
|
6331
6401
|
totalPixelLength = minor ? axisLength / tickPositions.length : axisLength;
|
6332
|
-
|
6402
|
+
|
6333
6403
|
interval = pick(
|
6334
6404
|
filteredTickIntervalOption,
|
6335
6405
|
axis._minorAutoInterval,
|
6336
6406
|
(realMax - realMin) * tickPixelIntervalOption / (totalPixelLength || 1)
|
6337
6407
|
);
|
6338
|
-
|
6408
|
+
|
6339
6409
|
interval = normalizeTickInterval(
|
6340
|
-
interval,
|
6341
|
-
null,
|
6410
|
+
interval,
|
6411
|
+
null,
|
6342
6412
|
math.pow(10, mathFloor(math.log(interval) / math.LN10))
|
6343
6413
|
);
|
6344
|
-
|
6414
|
+
|
6345
6415
|
positions = map(getLinearTickPositions(
|
6346
|
-
interval,
|
6416
|
+
interval,
|
6347
6417
|
realMin,
|
6348
|
-
realMax
|
6418
|
+
realMax
|
6349
6419
|
), log2lin);
|
6350
|
-
|
6420
|
+
|
6351
6421
|
if (!minor) {
|
6352
6422
|
axis._minorAutoInterval = interval / 5;
|
6353
6423
|
}
|
6354
6424
|
}
|
6355
|
-
|
6356
|
-
// Set the axis-level tickInterval variable
|
6425
|
+
|
6426
|
+
// Set the axis-level tickInterval variable
|
6357
6427
|
if (!minor) {
|
6358
6428
|
tickInterval = interval;
|
6359
6429
|
}
|
6360
6430
|
return positions;
|
6361
6431
|
}
|
6362
|
-
|
6432
|
+
|
6363
6433
|
/**
|
6364
6434
|
* Return the minor tick positions. For logarithmic axes, reuse the same logic
|
6365
6435
|
* as for major ticks.
|
@@ -6369,27 +6439,27 @@ function Chart(userOptions, callback) {
|
|
6369
6439
|
pos,
|
6370
6440
|
i,
|
6371
6441
|
len;
|
6372
|
-
|
6442
|
+
|
6373
6443
|
if (isLog) {
|
6374
6444
|
len = tickPositions.length;
|
6375
6445
|
for (i = 1; i < len; i++) {
|
6376
6446
|
minorTickPositions = minorTickPositions.concat(
|
6377
6447
|
getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true)
|
6378
|
-
);
|
6448
|
+
);
|
6379
6449
|
}
|
6380
|
-
|
6381
|
-
} else {
|
6450
|
+
|
6451
|
+
} else {
|
6382
6452
|
for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) {
|
6383
|
-
minorTickPositions.push(pos);
|
6453
|
+
minorTickPositions.push(pos);
|
6384
6454
|
}
|
6385
6455
|
}
|
6386
|
-
|
6456
|
+
|
6387
6457
|
return minorTickPositions;
|
6388
6458
|
}
|
6389
6459
|
|
6390
6460
|
/**
|
6391
|
-
* Adjust the min and max for the minimum range. Keep in mind that the series data is
|
6392
|
-
* not yet processed, so we don't have information on data cropping and grouping, or
|
6461
|
+
* Adjust the min and max for the minimum range. Keep in mind that the series data is
|
6462
|
+
* not yet processed, so we don't have information on data cropping and grouping, or
|
6393
6463
|
* updated axis.pointRange or series.pointRange. The data can't be processed until
|
6394
6464
|
* we have finally established min and max.
|
6395
6465
|
*/
|
@@ -6403,10 +6473,10 @@ function Chart(userOptions, callback) {
|
|
6403
6473
|
loopLength,
|
6404
6474
|
minArgs,
|
6405
6475
|
maxArgs;
|
6406
|
-
|
6476
|
+
|
6407
6477
|
// Set the automatic minimum range based on the closest point distance
|
6408
6478
|
if (isXAxis && minRange === UNDEFINED && !isLog) {
|
6409
|
-
|
6479
|
+
|
6410
6480
|
if (defined(options.min) || defined(options.max)) {
|
6411
6481
|
minRange = null; // don't do this again
|
6412
6482
|
|
@@ -6426,8 +6496,14 @@ function Chart(userOptions, callback) {
|
|
6426
6496
|
});
|
6427
6497
|
minRange = mathMin(closestDataRange * 5, dataMax - dataMin);
|
6428
6498
|
}
|
6499
|
+
|
6500
|
+
// A hook for resetting the minRange in series.setData (#878)
|
6501
|
+
// TODO: remove this in protofy, where xAxis.minRange can be set directly
|
6502
|
+
axis.setMinRange = function (newMinRange) {
|
6503
|
+
minRange = newMinRange;
|
6504
|
+
};
|
6429
6505
|
}
|
6430
|
-
|
6506
|
+
|
6431
6507
|
// if minRange is exceeded, adjust
|
6432
6508
|
if (max - min < minRange) {
|
6433
6509
|
|
@@ -6444,7 +6520,7 @@ function Chart(userOptions, callback) {
|
|
6444
6520
|
if (spaceAvailable) { // if space is availabe, stay within the data range
|
6445
6521
|
maxArgs[2] = dataMax;
|
6446
6522
|
}
|
6447
|
-
|
6523
|
+
|
6448
6524
|
max = arrayMin(maxArgs);
|
6449
6525
|
|
6450
6526
|
// now if the max is adjusted, adjust the min back
|
@@ -6528,10 +6604,10 @@ function Chart(userOptions, callback) {
|
|
6528
6604
|
}
|
6529
6605
|
|
6530
6606
|
// Now we're finished detecting min and max, crop and group series data. This
|
6531
|
-
// is in turn needed in order to find tick positions in ordinal axes.
|
6607
|
+
// is in turn needed in order to find tick positions in ordinal axes.
|
6532
6608
|
if (isXAxis && !secondPass) {
|
6533
6609
|
each(axis.series, function (series) {
|
6534
|
-
series.processData(min !== oldMin || max !== oldMax);
|
6610
|
+
series.processData(min !== oldMin || max !== oldMax);
|
6535
6611
|
});
|
6536
6612
|
}
|
6537
6613
|
|
@@ -6542,10 +6618,10 @@ function Chart(userOptions, callback) {
|
|
6542
6618
|
if (axis.beforeSetTickPositions) {
|
6543
6619
|
axis.beforeSetTickPositions();
|
6544
6620
|
}
|
6545
|
-
|
6621
|
+
|
6546
6622
|
// hook for extensions, used in Highstock ordinal axes
|
6547
6623
|
if (axis.postProcessTickInterval) {
|
6548
|
-
tickInterval = axis.postProcessTickInterval(tickInterval);
|
6624
|
+
tickInterval = axis.postProcessTickInterval(tickInterval);
|
6549
6625
|
}
|
6550
6626
|
|
6551
6627
|
// for linear axes, get magnitude and normalize the interval
|
@@ -6620,7 +6696,6 @@ function Chart(userOptions, callback) {
|
|
6620
6696
|
* number of ticks in that group
|
6621
6697
|
*/
|
6622
6698
|
function adjustTickAmount() {
|
6623
|
-
|
6624
6699
|
if (maxTicks && maxTicks[xOrY] && !isDatetimeAxis && !categories && !isLinked && options.alignTicks !== false) { // only apply to linear scale
|
6625
6700
|
var oldTickAmount = tickAmount,
|
6626
6701
|
calculatedTickAmount = tickPositions.length;
|
@@ -6655,13 +6730,14 @@ function Chart(userOptions, callback) {
|
|
6655
6730
|
i,
|
6656
6731
|
isDirtyData,
|
6657
6732
|
isDirtyAxisLength;
|
6658
|
-
|
6733
|
+
|
6659
6734
|
oldMin = min;
|
6660
6735
|
oldMax = max;
|
6661
6736
|
oldAxisLength = axisLength;
|
6662
6737
|
|
6663
6738
|
// set the new axisLength
|
6664
|
-
|
6739
|
+
axis.setAxisSize();
|
6740
|
+
//axisLength = horiz ? axisWidth : axisHeight;
|
6665
6741
|
isDirtyAxisLength = axisLength !== oldAxisLength;
|
6666
6742
|
|
6667
6743
|
// is there new data?
|
@@ -6709,13 +6785,13 @@ function Chart(userOptions, callback) {
|
|
6709
6785
|
* @param {Boolean} redraw
|
6710
6786
|
* @param {Boolean|Object} animation Whether to apply animation, and optionally animation
|
6711
6787
|
* configuration
|
6712
|
-
* @param {Object} eventArguments
|
6788
|
+
* @param {Object} eventArguments
|
6713
6789
|
*
|
6714
6790
|
*/
|
6715
6791
|
function setExtremes(newMin, newMax, redraw, animation, eventArguments) {
|
6716
6792
|
|
6717
6793
|
redraw = pick(redraw, true); // defaults to true
|
6718
|
-
|
6794
|
+
|
6719
6795
|
// Extend the arguments with min and max
|
6720
6796
|
eventArguments = extend(eventArguments, {
|
6721
6797
|
min: newMin,
|
@@ -6727,17 +6803,17 @@ function Chart(userOptions, callback) {
|
|
6727
6803
|
|
6728
6804
|
userMin = newMin;
|
6729
6805
|
userMax = newMax;
|
6730
|
-
|
6806
|
+
|
6731
6807
|
// Mark for running afterSetExtremes
|
6732
6808
|
axis.isDirtyExtremes = true;
|
6733
|
-
|
6809
|
+
|
6734
6810
|
// redraw
|
6735
6811
|
if (redraw) {
|
6736
6812
|
chart.redraw(animation);
|
6737
6813
|
}
|
6738
6814
|
});
|
6739
6815
|
}
|
6740
|
-
|
6816
|
+
|
6741
6817
|
/**
|
6742
6818
|
* Update translation information
|
6743
6819
|
*/
|
@@ -6746,7 +6822,7 @@ function Chart(userOptions, callback) {
|
|
6746
6822
|
pointRange = 0,
|
6747
6823
|
closestPointRange,
|
6748
6824
|
seriesClosestPointRange;
|
6749
|
-
|
6825
|
+
|
6750
6826
|
// adjust translation for padding
|
6751
6827
|
if (isXAxis) {
|
6752
6828
|
if (isLinked) {
|
@@ -6762,7 +6838,7 @@ function Chart(userOptions, callback) {
|
|
6762
6838
|
}
|
6763
6839
|
});
|
6764
6840
|
}
|
6765
|
-
|
6841
|
+
|
6766
6842
|
// pointRange means the width reserved for each point, like in a column chart
|
6767
6843
|
axis.pointRange = pointRange;
|
6768
6844
|
|
@@ -6794,7 +6870,7 @@ function Chart(userOptions, callback) {
|
|
6794
6870
|
axisHeight = pick(options.height, plotHeight);
|
6795
6871
|
axisBottom = chartHeight - axisHeight - axisTop;
|
6796
6872
|
axisRight = chartWidth - axisWidth - axisLeft;
|
6797
|
-
axisLength = horiz ? axisWidth : axisHeight;
|
6873
|
+
axisLength = mathMax(horiz ? axisWidth : axisHeight, 0); // mathMax fixes #905
|
6798
6874
|
|
6799
6875
|
// expose to use in Series object and navigator
|
6800
6876
|
axis.left = axisLeft;
|
@@ -6824,7 +6900,7 @@ function Chart(userOptions, callback) {
|
|
6824
6900
|
function getThreshold(threshold) {
|
6825
6901
|
var realMin = isLog ? lin2log(min) : min,
|
6826
6902
|
realMax = isLog ? lin2log(max) : max;
|
6827
|
-
|
6903
|
+
|
6828
6904
|
if (realMin > threshold || threshold === null) {
|
6829
6905
|
threshold = realMin;
|
6830
6906
|
} else if (realMax < threshold) {
|
@@ -6995,10 +7071,10 @@ function Chart(userOptions, callback) {
|
|
6995
7071
|
// Major ticks. Pull out the first item and render it last so that
|
6996
7072
|
// we can get the position of the neighbour label. #808.
|
6997
7073
|
each(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) {
|
6998
|
-
|
7074
|
+
|
6999
7075
|
// Reorganize the indices
|
7000
7076
|
i = (i === tickPositions.length - 1) ? 0 : i + 1;
|
7001
|
-
|
7077
|
+
|
7002
7078
|
// linked axes need an extra check to find out if
|
7003
7079
|
if (!isLinked || (pos >= min && pos <= max)) {
|
7004
7080
|
|
@@ -7149,10 +7225,13 @@ function Chart(userOptions, callback) {
|
|
7149
7225
|
visibility: VISIBLE,
|
7150
7226
|
zIndex: 6
|
7151
7227
|
})
|
7152
|
-
.translate(plotLeft, plotTop)
|
7153
7228
|
.add();
|
7154
7229
|
}
|
7155
7230
|
|
7231
|
+
// plotLeft/Top will change when y axis gets wider so we need to translate the
|
7232
|
+
// stackTotalGroup at every render call. See bug #506 and #516
|
7233
|
+
stackTotalGroup.translate(plotLeft, plotTop);
|
7234
|
+
|
7156
7235
|
// Render each stack total
|
7157
7236
|
for (stackKey in stacks) {
|
7158
7237
|
oneStack = stacks[stackKey];
|
@@ -7178,16 +7257,16 @@ function Chart(userOptions, callback) {
|
|
7178
7257
|
}
|
7179
7258
|
}
|
7180
7259
|
}
|
7181
|
-
|
7260
|
+
|
7182
7261
|
/**
|
7183
7262
|
* Update the axis title by options
|
7184
7263
|
*/
|
7185
7264
|
function setTitle(newTitleOptions, redraw) {
|
7186
7265
|
options.title = merge(options.title, newTitleOptions);
|
7187
|
-
|
7266
|
+
|
7188
7267
|
axisTitle = axisTitle.destroy();
|
7189
7268
|
axis.isDirty = true;
|
7190
|
-
|
7269
|
+
|
7191
7270
|
if (pick(redraw, true)) {
|
7192
7271
|
chart.redraw();
|
7193
7272
|
}
|
@@ -7200,7 +7279,7 @@ function Chart(userOptions, callback) {
|
|
7200
7279
|
|
7201
7280
|
// hide tooltip and hover states
|
7202
7281
|
if (tracker.resetTracker) {
|
7203
|
-
tracker.resetTracker();
|
7282
|
+
tracker.resetTracker(true);
|
7204
7283
|
}
|
7205
7284
|
|
7206
7285
|
// render the axis
|
@@ -7355,7 +7434,7 @@ function Chart(userOptions, callback) {
|
|
7355
7434
|
style.padding = 0;
|
7356
7435
|
|
7357
7436
|
// create the label
|
7358
|
-
var label = renderer.label('', 0, 0, null, null, null, options.useHTML)
|
7437
|
+
var label = renderer.label('', 0, 0, null, null, null, options.useHTML, null, 'tooltip')
|
7359
7438
|
.attr({
|
7360
7439
|
padding: padding,
|
7361
7440
|
fill: options.backgroundColor,
|
@@ -7407,10 +7486,10 @@ function Chart(userOptions, callback) {
|
|
7407
7486
|
s.push((series.tooltipFormatter && series.tooltipFormatter(item)) ||
|
7408
7487
|
item.point.tooltipFormatter(series.tooltipOptions.pointFormat));
|
7409
7488
|
});
|
7410
|
-
|
7489
|
+
|
7411
7490
|
// footer
|
7412
7491
|
s.push(options.footerFormat || '');
|
7413
|
-
|
7492
|
+
|
7414
7493
|
return s.join('');
|
7415
7494
|
}
|
7416
7495
|
|
@@ -7593,7 +7672,7 @@ function Chart(userOptions, callback) {
|
|
7593
7672
|
axis = point.series[i ? 'yAxis' : 'xAxis'];
|
7594
7673
|
if (crosshairsOptions[i] && axis) {
|
7595
7674
|
path = axis.getPlotLinePath(
|
7596
|
-
i ? pick(point.stackY, point.y) : point.x, // #814
|
7675
|
+
i ? pick(point.stackY, point.y) : point.x, // #814
|
7597
7676
|
1
|
7598
7677
|
);
|
7599
7678
|
if (crosshairs[i]) {
|
@@ -7658,8 +7737,6 @@ function Chart(userOptions, callback) {
|
|
7658
7737
|
*/
|
7659
7738
|
function normalizeMouseEvent(e) {
|
7660
7739
|
var ePos,
|
7661
|
-
chartPosLeft,
|
7662
|
-
chartPosTop,
|
7663
7740
|
chartX,
|
7664
7741
|
chartY;
|
7665
7742
|
|
@@ -7684,16 +7761,14 @@ function Chart(userOptions, callback) {
|
|
7684
7761
|
|
7685
7762
|
// get mouse position
|
7686
7763
|
chartPosition = offset(container);
|
7687
|
-
chartPosLeft = chartPosition.left;
|
7688
|
-
chartPosTop = chartPosition.top;
|
7689
7764
|
|
7690
7765
|
// chartX and chartY
|
7691
|
-
if (
|
7766
|
+
if (ePos.pageX === UNDEFINED) { // IE < 9. #886.
|
7692
7767
|
chartX = e.x;
|
7693
7768
|
chartY = e.y;
|
7694
7769
|
} else {
|
7695
|
-
chartX = ePos.pageX -
|
7696
|
-
chartY = ePos.pageY -
|
7770
|
+
chartX = ePos.pageX - chartPosition.left;
|
7771
|
+
chartY = ePos.pageY - chartPosition.top;
|
7697
7772
|
}
|
7698
7773
|
|
7699
7774
|
return extend(e, {
|
@@ -7741,7 +7816,8 @@ function Chart(userOptions, callback) {
|
|
7741
7816
|
i,
|
7742
7817
|
j,
|
7743
7818
|
distance = chartWidth,
|
7744
|
-
index
|
7819
|
+
// the index in the tooltipPoints array, corresponding to pixel position in plot area
|
7820
|
+
index = inverted ? plotHeight + plotTop - e.chartY : e.chartX - plotLeft;
|
7745
7821
|
|
7746
7822
|
// shared tooltip
|
7747
7823
|
if (tooltip && options.shared && !(hoverSeries && hoverSeries.noSharedTooltip)) {
|
@@ -7794,24 +7870,34 @@ function Chart(userOptions, callback) {
|
|
7794
7870
|
/**
|
7795
7871
|
* Reset the tracking by hiding the tooltip, the hover series state and the hover point
|
7796
7872
|
*/
|
7797
|
-
function resetTracker() {
|
7873
|
+
function resetTracker(allowMove) {
|
7798
7874
|
var hoverSeries = chart.hoverSeries,
|
7799
|
-
hoverPoint = chart.hoverPoint
|
7875
|
+
hoverPoint = chart.hoverPoint,
|
7876
|
+
tooltipPoints = chart.hoverPoints || hoverPoint;
|
7800
7877
|
|
7801
|
-
|
7802
|
-
|
7803
|
-
|
7878
|
+
// Just move the tooltip, #349
|
7879
|
+
if (allowMove && tooltip && tooltipPoints) {
|
7880
|
+
tooltip.refresh(tooltipPoints);
|
7804
7881
|
|
7805
|
-
|
7806
|
-
|
7807
|
-
}
|
7882
|
+
// Full reset
|
7883
|
+
} else {
|
7808
7884
|
|
7809
|
-
|
7810
|
-
|
7811
|
-
|
7812
|
-
|
7885
|
+
if (hoverPoint) {
|
7886
|
+
hoverPoint.onMouseOut();
|
7887
|
+
}
|
7888
|
+
|
7889
|
+
if (hoverSeries) {
|
7890
|
+
hoverSeries.onMouseOut();
|
7891
|
+
}
|
7892
|
+
|
7893
|
+
if (tooltip) {
|
7894
|
+
tooltip.hide();
|
7895
|
+
tooltip.hideCrosshairs();
|
7896
|
+
}
|
7813
7897
|
|
7814
|
-
|
7898
|
+
hoverX = null;
|
7899
|
+
|
7900
|
+
}
|
7815
7901
|
}
|
7816
7902
|
|
7817
7903
|
/**
|
@@ -7825,7 +7911,8 @@ function Chart(userOptions, callback) {
|
|
7825
7911
|
},
|
7826
7912
|
selectionBox = selectionMarker.getBBox(),
|
7827
7913
|
selectionLeft = selectionBox.x - plotLeft,
|
7828
|
-
selectionTop = selectionBox.y - plotTop
|
7914
|
+
selectionTop = selectionBox.y - plotTop,
|
7915
|
+
runZoom;
|
7829
7916
|
|
7830
7917
|
|
7831
7918
|
// a selection has been made
|
@@ -7855,23 +7942,30 @@ function Chart(userOptions, callback) {
|
|
7855
7942
|
0,
|
7856
7943
|
1
|
7857
7944
|
);
|
7858
|
-
|
7859
|
-
|
7860
|
-
|
7861
|
-
|
7862
|
-
|
7863
|
-
|
7945
|
+
if (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859
|
7946
|
+
selectionData[isXAxis ? 'xAxis' : 'yAxis'].push({
|
7947
|
+
axis: axis,
|
7948
|
+
min: mathMin(selectionMin, selectionMax), // for reversed axes,
|
7949
|
+
max: mathMax(selectionMin, selectionMax)
|
7950
|
+
});
|
7951
|
+
runZoom = true;
|
7952
|
+
}
|
7864
7953
|
}
|
7865
7954
|
});
|
7866
|
-
|
7955
|
+
if (runZoom) {
|
7956
|
+
fireEvent(chart, 'selection', selectionData, zoom);
|
7957
|
+
}
|
7867
7958
|
|
7868
7959
|
}
|
7869
7960
|
selectionMarker = selectionMarker.destroy();
|
7870
7961
|
}
|
7871
7962
|
|
7872
|
-
|
7963
|
+
if (chart) { // it may be destroyed on mouse up - #877
|
7964
|
+
css(container, { cursor: 'auto' });
|
7965
|
+
chart.cancelClick = hasDragged; // #370
|
7966
|
+
chart.mouseIsDown = mouseIsDown = hasDragged = false;
|
7967
|
+
}
|
7873
7968
|
|
7874
|
-
chart.mouseIsDown = mouseIsDown = hasDragged = false;
|
7875
7969
|
removeEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop);
|
7876
7970
|
|
7877
7971
|
}
|
@@ -7880,12 +7974,14 @@ function Chart(userOptions, callback) {
|
|
7880
7974
|
* Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea.
|
7881
7975
|
*/
|
7882
7976
|
function hideTooltipOnMouseMove(e) {
|
7883
|
-
var pageX = defined(e.pageX) ? e.pageX : e.page.x, // In mootools the event is wrapped and the page x/y position is named e.page.x
|
7884
|
-
pageY = defined(e.pageX) ? e.pageY : e.page.y; // Ref: http://mootools.net/docs/core/Types/DOMEvent
|
7885
7977
|
|
7978
|
+
// Get e.pageX and e.pageY back in MooTools
|
7979
|
+
washMouseEvent(e);
|
7980
|
+
|
7981
|
+
// If we're outside, hide the tooltip
|
7886
7982
|
if (chartPosition &&
|
7887
|
-
!isInsidePlot(pageX - chartPosition.left - plotLeft,
|
7888
|
-
pageY - chartPosition.top - plotTop)) {
|
7983
|
+
!isInsidePlot(e.pageX - chartPosition.left - plotLeft,
|
7984
|
+
e.pageY - chartPosition.top - plotTop)) {
|
7889
7985
|
resetTracker();
|
7890
7986
|
}
|
7891
7987
|
}
|
@@ -7916,6 +8012,7 @@ function Chart(userOptions, callback) {
|
|
7916
8012
|
|
7917
8013
|
// record the start position
|
7918
8014
|
chart.mouseIsDown = mouseIsDown = true;
|
8015
|
+
chart.cancelClick = false;
|
7919
8016
|
chart.mouseDownX = mouseDownX = e.chartX;
|
7920
8017
|
mouseDownY = e.chartY;
|
7921
8018
|
|
@@ -8087,9 +8184,9 @@ function Chart(userOptions, callback) {
|
|
8087
8184
|
e.cancelBubble = true; // IE specific
|
8088
8185
|
|
8089
8186
|
|
8090
|
-
if (!
|
8091
|
-
|
8092
|
-
// Detect clicks on trackers or tracker groups, #783
|
8187
|
+
if (!chart.cancelClick) {
|
8188
|
+
|
8189
|
+
// Detect clicks on trackers or tracker groups, #783
|
8093
8190
|
if (hoverPoint && (attr(e.target, 'isTracker') || attr(e.target.parentNode, 'isTracker'))) {
|
8094
8191
|
var plotX = hoverPoint.plotX,
|
8095
8192
|
plotY = hoverPoint.plotY;
|
@@ -8121,8 +8218,6 @@ function Chart(userOptions, callback) {
|
|
8121
8218
|
|
8122
8219
|
|
8123
8220
|
}
|
8124
|
-
// reset mouseIsDown and hasDragged
|
8125
|
-
hasDragged = false;
|
8126
8221
|
};
|
8127
8222
|
|
8128
8223
|
}
|
@@ -8141,15 +8236,15 @@ function Chart(userOptions, callback) {
|
|
8141
8236
|
container.onclick = container.onmousedown = container.onmousemove = container.ontouchstart = container.ontouchend = container.ontouchmove = null;
|
8142
8237
|
}
|
8143
8238
|
|
8144
|
-
|
8239
|
+
|
8145
8240
|
// Run MouseTracker
|
8146
|
-
|
8241
|
+
|
8147
8242
|
if (!trackerGroup) {
|
8148
8243
|
chart.trackerGroup = trackerGroup = renderer.g('tracker')
|
8149
8244
|
.attr({ zIndex: 9 })
|
8150
8245
|
.add();
|
8151
8246
|
}
|
8152
|
-
|
8247
|
+
|
8153
8248
|
if (options.enabled) {
|
8154
8249
|
chart.tooltip = tooltip = Tooltip(options);
|
8155
8250
|
|
@@ -8258,7 +8353,7 @@ function Chart(userOptions, callback) {
|
|
8258
8353
|
legendSymbol = item.legendSymbol,
|
8259
8354
|
symbolX,
|
8260
8355
|
checkbox = item.checkbox;
|
8261
|
-
|
8356
|
+
|
8262
8357
|
if (legendItem) {
|
8263
8358
|
legendItem.attr({
|
8264
8359
|
x: ltr ? itemX : legendWidth - itemX,
|
@@ -8426,11 +8521,11 @@ function Chart(userOptions, callback) {
|
|
8426
8521
|
//'stroke-width': 0,
|
8427
8522
|
zIndex: 3
|
8428
8523
|
}).add(legendGroup);
|
8429
|
-
|
8524
|
+
|
8430
8525
|
if (!ltr) {
|
8431
8526
|
symbolX += symbolWidth;
|
8432
8527
|
}
|
8433
|
-
|
8528
|
+
|
8434
8529
|
} else if (itemOptions && itemOptions.marker && itemOptions.marker.enabled) { // draw the marker
|
8435
8530
|
radius = itemOptions.marker.radius;
|
8436
8531
|
legendSymbol = renderer.symbol(
|
@@ -8443,14 +8538,14 @@ function Chart(userOptions, callback) {
|
|
8443
8538
|
.attr(item.pointAttr[NORMAL_STATE])
|
8444
8539
|
.attr({ zIndex: 3 })
|
8445
8540
|
.add(legendGroup);
|
8446
|
-
|
8541
|
+
|
8447
8542
|
if (!ltr) {
|
8448
8543
|
symbolX += symbolWidth / 2;
|
8449
8544
|
}
|
8450
8545
|
|
8451
8546
|
}
|
8452
8547
|
if (legendSymbol) {
|
8453
|
-
|
8548
|
+
|
8454
8549
|
legendSymbol.xOff = symbolX + (strokeWidth % 2 / 2);
|
8455
8550
|
legendSymbol.yOff = symbolY + (strokeWidth % 2 / 2);
|
8456
8551
|
}
|
@@ -8496,7 +8591,7 @@ function Chart(userOptions, callback) {
|
|
8496
8591
|
itemX = initialItemX;
|
8497
8592
|
itemY += itemMarginTop + itemHeight + itemMarginBottom;
|
8498
8593
|
}
|
8499
|
-
|
8594
|
+
|
8500
8595
|
// If the item exceeds the height, start a new column
|
8501
8596
|
if (!horizontal && itemY + options.y + itemHeight > chartHeight - spacingTop - spacingBottom) {
|
8502
8597
|
itemY = initialItemY;
|
@@ -8507,7 +8602,7 @@ function Chart(userOptions, callback) {
|
|
8507
8602
|
// Set the edge positions
|
8508
8603
|
maxItemWidth = mathMax(maxItemWidth, itemWidth);
|
8509
8604
|
lastItemY = mathMax(lastItemY, itemY + itemMarginBottom);
|
8510
|
-
|
8605
|
+
|
8511
8606
|
// cache the position of the newly generated or reordered items
|
8512
8607
|
item._legendItemPos = [itemX, itemY];
|
8513
8608
|
|
@@ -8539,10 +8634,10 @@ function Chart(userOptions, callback) {
|
|
8539
8634
|
|
8540
8635
|
if (!legendGroup) {
|
8541
8636
|
legendGroup = renderer.g('legend')
|
8542
|
-
// #414, #759. Trackers will be drawn above the legend, but we have
|
8637
|
+
// #414, #759. Trackers will be drawn above the legend, but we have
|
8543
8638
|
// to sacrifice that because tooltips need to be above the legend
|
8544
8639
|
// and trackers above tooltips
|
8545
|
-
.attr({ zIndex: 7 })
|
8640
|
+
.attr({ zIndex: 7 })
|
8546
8641
|
.add();
|
8547
8642
|
}
|
8548
8643
|
|
@@ -8615,8 +8710,8 @@ function Chart(userOptions, callback) {
|
|
8615
8710
|
// hide the border if no items
|
8616
8711
|
box[allItems.length ? 'show' : 'hide']();
|
8617
8712
|
}
|
8618
|
-
|
8619
|
-
// Now that the legend width and height are extablished, put the items in the
|
8713
|
+
|
8714
|
+
// Now that the legend width and height are extablished, put the items in the
|
8620
8715
|
// final position
|
8621
8716
|
each(allItems, positionItem);
|
8622
8717
|
|
@@ -8825,14 +8920,14 @@ function Chart(userOptions, callback) {
|
|
8825
8920
|
|
8826
8921
|
// redraw axes
|
8827
8922
|
each(axes, function (axis) {
|
8828
|
-
|
8923
|
+
|
8829
8924
|
// Fire 'afterSetExtremes' only if extremes are set
|
8830
8925
|
if (axis.isDirtyExtremes) { // #821
|
8831
8926
|
axis.isDirtyExtremes = false;
|
8832
8927
|
fireEvent(axis, 'afterSetExtremes', axis.getExtremes()); // #747, #751
|
8833
8928
|
}
|
8834
|
-
|
8835
|
-
if (axis.isDirty || isDirtyBox) {
|
8929
|
+
|
8930
|
+
if (axis.isDirty || isDirtyBox || hasStackedSeries) {
|
8836
8931
|
axis.redraw();
|
8837
8932
|
isDirtyBox = true; // #792
|
8838
8933
|
}
|
@@ -8866,9 +8961,9 @@ function Chart(userOptions, callback) {
|
|
8866
8961
|
});
|
8867
8962
|
|
8868
8963
|
|
8869
|
-
//
|
8964
|
+
// move tooltip or reset
|
8870
8965
|
if (tracker && tracker.resetTracker) {
|
8871
|
-
tracker.resetTracker();
|
8966
|
+
tracker.resetTracker(true);
|
8872
8967
|
}
|
8873
8968
|
|
8874
8969
|
// redraw if canvas
|
@@ -9098,7 +9193,7 @@ function Chart(userOptions, callback) {
|
|
9098
9193
|
|
9099
9194
|
// Redraw
|
9100
9195
|
if (hasZoomed) {
|
9101
|
-
redraw(
|
9196
|
+
redraw(
|
9102
9197
|
pick(optionsChart.animation, chart.pointCount < 100) // animation
|
9103
9198
|
);
|
9104
9199
|
}
|
@@ -9204,7 +9299,7 @@ function Chart(userOptions, callback) {
|
|
9204
9299
|
if (isString(renderTo)) {
|
9205
9300
|
renderTo = doc.getElementById(renderTo);
|
9206
9301
|
}
|
9207
|
-
|
9302
|
+
|
9208
9303
|
// Display an error if the renderTo is wrong
|
9209
9304
|
if (!renderTo) {
|
9210
9305
|
error(13, true);
|
@@ -9213,7 +9308,7 @@ function Chart(userOptions, callback) {
|
|
9213
9308
|
// remove previous chart
|
9214
9309
|
renderTo.innerHTML = '';
|
9215
9310
|
|
9216
|
-
// If the container doesn't have an offsetWidth, it
|
9311
|
+
// If the container doesn't have an offsetWidth, it ha s or is a child of a node
|
9217
9312
|
// that has display:none. We need to temporarily move it out to a visible
|
9218
9313
|
// state to determine the size, else the legend and tooltips won't render
|
9219
9314
|
// properly
|
@@ -9222,7 +9317,7 @@ function Chart(userOptions, callback) {
|
|
9222
9317
|
css(renderToClone, {
|
9223
9318
|
position: ABSOLUTE,
|
9224
9319
|
top: '-9999px',
|
9225
|
-
display: ''
|
9320
|
+
display: 'block'
|
9226
9321
|
});
|
9227
9322
|
doc.body.appendChild(renderToClone);
|
9228
9323
|
}
|
@@ -9257,35 +9352,6 @@ function Chart(userOptions, callback) {
|
|
9257
9352
|
// to get the tracker for translating mouse events
|
9258
9353
|
renderer.create(chart, container, chartWidth, chartHeight);
|
9259
9354
|
}
|
9260
|
-
|
9261
|
-
// Issue 110 workaround:
|
9262
|
-
// In Firefox, if a div is positioned by percentage, its pixel position may land
|
9263
|
-
// between pixels. The container itself doesn't display this, but an SVG element
|
9264
|
-
// inside this container will be drawn at subpixel precision. In order to draw
|
9265
|
-
// sharp lines, this must be compensated for. This doesn't seem to work inside
|
9266
|
-
// iframes though (like in jsFiddle).
|
9267
|
-
var subPixelFix, rect;
|
9268
|
-
if (isFirefox && container.getBoundingClientRect) {
|
9269
|
-
subPixelFix = function () {
|
9270
|
-
css(container, { left: 0, top: 0 });
|
9271
|
-
rect = container.getBoundingClientRect();
|
9272
|
-
css(container, {
|
9273
|
-
left: (-(rect.left - pInt(rect.left))) + PX,
|
9274
|
-
top: (-(rect.top - pInt(rect.top))) + PX
|
9275
|
-
});
|
9276
|
-
};
|
9277
|
-
|
9278
|
-
// run the fix now
|
9279
|
-
subPixelFix();
|
9280
|
-
|
9281
|
-
// run it on resize
|
9282
|
-
addEvent(win, 'resize', subPixelFix);
|
9283
|
-
|
9284
|
-
// remove it on chart destroy
|
9285
|
-
addEvent(chart, 'destroy', function () {
|
9286
|
-
removeEvent(win, 'resize', subPixelFix);
|
9287
|
-
});
|
9288
|
-
}
|
9289
9355
|
}
|
9290
9356
|
|
9291
9357
|
/**
|
@@ -9391,11 +9457,11 @@ function Chart(userOptions, callback) {
|
|
9391
9457
|
var width = optionsChart.width || renderTo.offsetWidth,
|
9392
9458
|
height = optionsChart.height || renderTo.offsetHeight,
|
9393
9459
|
target = e ? e.target : win; // #805 - MooTools doesn't supply e
|
9394
|
-
|
9460
|
+
|
9395
9461
|
// Width and height checks for display:none. Target is doc in IE8 and Opera,
|
9396
9462
|
// win in Firefox, Chrome and IE9.
|
9397
9463
|
if (width && height && (target === win || target === doc)) {
|
9398
|
-
|
9464
|
+
|
9399
9465
|
if (width !== containerWidth || height !== containerHeight) {
|
9400
9466
|
clearTimeout(reflowTimeout);
|
9401
9467
|
reflowTimeout = setTimeout(function () {
|
@@ -9663,6 +9729,8 @@ function Chart(userOptions, callback) {
|
|
9663
9729
|
axis.setScale();
|
9664
9730
|
});
|
9665
9731
|
getMargins();
|
9732
|
+
|
9733
|
+
maxTicks = null; // reset for second pass
|
9666
9734
|
each(axes, function (axis) {
|
9667
9735
|
axis.setTickPositions(true); // update to reflect the new margins
|
9668
9736
|
});
|
@@ -9893,8 +9961,8 @@ function Chart(userOptions, callback) {
|
|
9893
9961
|
each(chart.callbacks, function (fn) {
|
9894
9962
|
fn.apply(chart, [chart]);
|
9895
9963
|
});
|
9896
|
-
|
9897
|
-
|
9964
|
+
|
9965
|
+
|
9898
9966
|
// If the chart was rendered outside the top container, put it back in
|
9899
9967
|
if (renderToClone) {
|
9900
9968
|
renderTo.appendChild(container);
|
@@ -10050,8 +10118,8 @@ Point.prototype = {
|
|
10050
10118
|
// copy options directly to point
|
10051
10119
|
extend(point, options);
|
10052
10120
|
point.options = options;
|
10053
|
-
|
10054
|
-
// This is the fastest way to detect if there are individual point dataLabels that need
|
10121
|
+
|
10122
|
+
// This is the fastest way to detect if there are individual point dataLabels that need
|
10055
10123
|
// to be considered in drawDataLabels. These can only occur in object configs.
|
10056
10124
|
if (options.dataLabels) {
|
10057
10125
|
series._hasPointLabels = true;
|
@@ -10060,7 +10128,7 @@ Point.prototype = {
|
|
10060
10128
|
point.name = options[0];
|
10061
10129
|
point.y = options[1];
|
10062
10130
|
}
|
10063
|
-
|
10131
|
+
|
10064
10132
|
/*
|
10065
10133
|
* If no x is set by now, get auto incremented value. All points must have an
|
10066
10134
|
* x value, however the y value can be null to create a gap in the series
|
@@ -10069,8 +10137,8 @@ Point.prototype = {
|
|
10069
10137
|
if (point.x === UNDEFINED) {
|
10070
10138
|
point.x = x === UNDEFINED ? series.autoIncrement() : x;
|
10071
10139
|
}
|
10072
|
-
|
10073
|
-
|
10140
|
+
|
10141
|
+
|
10074
10142
|
|
10075
10143
|
},
|
10076
10144
|
|
@@ -10080,19 +10148,23 @@ Point.prototype = {
|
|
10080
10148
|
destroy: function () {
|
10081
10149
|
var point = this,
|
10082
10150
|
series = point.series,
|
10083
|
-
|
10151
|
+
chart = series.chart,
|
10152
|
+
hoverPoints = chart.hoverPoints,
|
10084
10153
|
prop;
|
10085
10154
|
|
10086
|
-
|
10155
|
+
chart.pointCount--;
|
10087
10156
|
|
10088
10157
|
if (hoverPoints) {
|
10089
10158
|
point.setState();
|
10090
10159
|
erase(hoverPoints, point);
|
10160
|
+
if (!hoverPoints.length) {
|
10161
|
+
chart.hoverPoints = null;
|
10162
|
+
}
|
10163
|
+
|
10091
10164
|
}
|
10092
|
-
if (point ===
|
10165
|
+
if (point === chart.hoverPoint) {
|
10093
10166
|
point.onMouseOut();
|
10094
10167
|
}
|
10095
|
-
series.chart.hoverPoints = null;
|
10096
10168
|
|
10097
10169
|
// remove all events
|
10098
10170
|
if (point.graphic || point.dataLabel) { // removeEvent and destroyElements are performance expensive
|
@@ -10101,7 +10173,7 @@ Point.prototype = {
|
|
10101
10173
|
}
|
10102
10174
|
|
10103
10175
|
if (point.legendItem) { // pies have legend items
|
10104
|
-
|
10176
|
+
chart.legend.destroyItem(point);
|
10105
10177
|
}
|
10106
10178
|
|
10107
10179
|
for (prop in point) {
|
@@ -10231,28 +10303,28 @@ Point.prototype = {
|
|
10231
10303
|
for (i in match) {
|
10232
10304
|
key = match[i];
|
10233
10305
|
if (isString(key) && key !== pointFormat) { // IE matches more than just the variables
|
10234
|
-
|
10306
|
+
|
10235
10307
|
// Split it further into parts
|
10236
10308
|
parts = (' ' + key).split(splitter); // add empty string because IE and the rest handles it differently
|
10237
10309
|
obj = { 'point': point, 'series': series }[parts[1]];
|
10238
10310
|
prop = parts[2];
|
10239
|
-
|
10311
|
+
|
10240
10312
|
// Add some preformatting
|
10241
|
-
if (obj === point && (prop === 'y' || prop === 'open' || prop === 'high' ||
|
10242
|
-
prop === 'low' || prop === 'close')) {
|
10243
|
-
replacement = (seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix || '') +
|
10313
|
+
if (obj === point && (prop === 'y' || prop === 'open' || prop === 'high' ||
|
10314
|
+
prop === 'low' || prop === 'close')) {
|
10315
|
+
replacement = (seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix || '') +
|
10244
10316
|
numberFormat(point[prop], pick(seriesTooltipOptions.valueDecimals, seriesTooltipOptions.yDecimals, originalDecimals)) +
|
10245
10317
|
(seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix || '');
|
10246
|
-
|
10318
|
+
|
10247
10319
|
// Automatic replacement
|
10248
10320
|
} else {
|
10249
10321
|
replacement = obj[prop];
|
10250
10322
|
}
|
10251
|
-
|
10323
|
+
|
10252
10324
|
pointFormat = pointFormat.replace(key, replacement);
|
10253
10325
|
}
|
10254
10326
|
}
|
10255
|
-
|
10327
|
+
|
10256
10328
|
return pointFormat;
|
10257
10329
|
},
|
10258
10330
|
|
@@ -10525,7 +10597,7 @@ Series.prototype = {
|
|
10525
10597
|
|
10526
10598
|
series.chart = chart;
|
10527
10599
|
series.options = options = series.setOptions(options); // merge with plotOptions
|
10528
|
-
|
10600
|
+
|
10529
10601
|
// bind the axes
|
10530
10602
|
series.bindAxes();
|
10531
10603
|
|
@@ -10538,7 +10610,7 @@ Series.prototype = {
|
|
10538
10610
|
visible: options.visible !== false, // true by default
|
10539
10611
|
selected: options.selected === true // false by default
|
10540
10612
|
});
|
10541
|
-
|
10613
|
+
|
10542
10614
|
// special
|
10543
10615
|
if (useCanVG) {
|
10544
10616
|
options.animation = false;
|
@@ -10564,9 +10636,9 @@ Series.prototype = {
|
|
10564
10636
|
series.setData(options.data, false);
|
10565
10637
|
|
10566
10638
|
},
|
10567
|
-
|
10568
|
-
|
10569
|
-
|
10639
|
+
|
10640
|
+
|
10641
|
+
|
10570
10642
|
/**
|
10571
10643
|
* Set the xAxis and yAxis properties of cartesian series, and register the series
|
10572
10644
|
* in the axis.series array
|
@@ -10576,31 +10648,31 @@ Series.prototype = {
|
|
10576
10648
|
seriesOptions = series.options,
|
10577
10649
|
chart = series.chart,
|
10578
10650
|
axisOptions;
|
10579
|
-
|
10651
|
+
|
10580
10652
|
if (series.isCartesian) {
|
10581
|
-
|
10653
|
+
|
10582
10654
|
each(['xAxis', 'yAxis'], function (AXIS) { // repeat for xAxis and yAxis
|
10583
|
-
|
10655
|
+
|
10584
10656
|
each(chart[AXIS], function (axis) { // loop through the chart's axis objects
|
10585
|
-
|
10657
|
+
|
10586
10658
|
axisOptions = axis.options;
|
10587
|
-
|
10588
|
-
// apply if the series xAxis or yAxis option mathches the number of the
|
10659
|
+
|
10660
|
+
// apply if the series xAxis or yAxis option mathches the number of the
|
10589
10661
|
// axis, or if undefined, use the first axis
|
10590
10662
|
if ((seriesOptions[AXIS] === axisOptions.index) ||
|
10591
10663
|
(seriesOptions[AXIS] === UNDEFINED && axisOptions.index === 0)) {
|
10592
|
-
|
10664
|
+
|
10593
10665
|
// register this series in the axis.series lookup
|
10594
10666
|
axis.series.push(series);
|
10595
|
-
|
10667
|
+
|
10596
10668
|
// set this series.xAxis or series.yAxis reference
|
10597
10669
|
series[AXIS] = axis;
|
10598
|
-
|
10670
|
+
|
10599
10671
|
// mark dirty for redraw
|
10600
10672
|
axis.isDirty = true;
|
10601
10673
|
}
|
10602
10674
|
});
|
10603
|
-
|
10675
|
+
|
10604
10676
|
});
|
10605
10677
|
}
|
10606
10678
|
},
|
@@ -10635,7 +10707,7 @@ Series.prototype = {
|
|
10635
10707
|
pointsLength = points.length;
|
10636
10708
|
|
10637
10709
|
if (pointsLength) { // no action required for []
|
10638
|
-
|
10710
|
+
|
10639
10711
|
// if connect nulls, just remove null points
|
10640
10712
|
if (series.options.connectNulls) {
|
10641
10713
|
i = pointsLength;
|
@@ -10647,7 +10719,7 @@ Series.prototype = {
|
|
10647
10719
|
if (points.length) {
|
10648
10720
|
segments = [points];
|
10649
10721
|
}
|
10650
|
-
|
10722
|
+
|
10651
10723
|
// else, split on null points
|
10652
10724
|
} else {
|
10653
10725
|
each(points, function (point, i) {
|
@@ -10662,7 +10734,7 @@ Series.prototype = {
|
|
10662
10734
|
});
|
10663
10735
|
}
|
10664
10736
|
}
|
10665
|
-
|
10737
|
+
|
10666
10738
|
// register it
|
10667
10739
|
series.segments = segments;
|
10668
10740
|
},
|
@@ -10685,13 +10757,13 @@ Series.prototype = {
|
|
10685
10757
|
plotOptions.series,
|
10686
10758
|
itemOptions
|
10687
10759
|
);
|
10688
|
-
|
10760
|
+
|
10689
10761
|
// Re-insert the data array to the options and the original config (#717)
|
10690
10762
|
options.data = itemOptions.data = data;
|
10691
|
-
|
10763
|
+
|
10692
10764
|
// the tooltip options are merged between global and series specific options
|
10693
10765
|
series.tooltipOptions = merge(chartOptions.tooltip, options.tooltip);
|
10694
|
-
|
10766
|
+
|
10695
10767
|
return options;
|
10696
10768
|
|
10697
10769
|
},
|
@@ -10714,7 +10786,7 @@ Series.prototype = {
|
|
10714
10786
|
defaultSymbols = chart.options.symbols,
|
10715
10787
|
counters = chart.counters;
|
10716
10788
|
series.symbol = seriesMarkerOption.symbol || defaultSymbols[counters.symbol++];
|
10717
|
-
|
10789
|
+
|
10718
10790
|
// don't substract radius in image symbols (#604)
|
10719
10791
|
if (/^url/.test(series.symbol)) {
|
10720
10792
|
seriesMarkerOption.radius = 0;
|
@@ -10747,7 +10819,7 @@ Series.prototype = {
|
|
10747
10819
|
setAnimation(animation, chart);
|
10748
10820
|
|
10749
10821
|
// Make graph animate sideways
|
10750
|
-
if (graph && shift) {
|
10822
|
+
if (graph && shift) {
|
10751
10823
|
graph.shift = currentShift + 1;
|
10752
10824
|
}
|
10753
10825
|
if (area) {
|
@@ -10756,7 +10828,7 @@ Series.prototype = {
|
|
10756
10828
|
}
|
10757
10829
|
area.isArea = true; // needed in animation, both with and without shift
|
10758
10830
|
}
|
10759
|
-
|
10831
|
+
|
10760
10832
|
// Optional redraw, defaults to true
|
10761
10833
|
redraw = pick(redraw, true);
|
10762
10834
|
|
@@ -10772,7 +10844,7 @@ Series.prototype = {
|
|
10772
10844
|
// Shift the first point off the parallel arrays
|
10773
10845
|
// todo: consider series.removePoint(i) method
|
10774
10846
|
if (shift) {
|
10775
|
-
if (data[0]) {
|
10847
|
+
if (data[0] && data[0].remove) {
|
10776
10848
|
data[0].remove(false);
|
10777
10849
|
} else {
|
10778
10850
|
data.shift();
|
@@ -10803,16 +10875,17 @@ Series.prototype = {
|
|
10803
10875
|
initialColor = series.initialColor,
|
10804
10876
|
chart = series.chart,
|
10805
10877
|
firstPoint = null,
|
10878
|
+
xAxis = series.xAxis,
|
10806
10879
|
i;
|
10807
10880
|
|
10808
10881
|
// reset properties
|
10809
10882
|
series.xIncrement = null;
|
10810
|
-
series.pointRange = (
|
10811
|
-
|
10883
|
+
series.pointRange = (xAxis && xAxis.categories && 1) || options.pointRange;
|
10884
|
+
|
10812
10885
|
if (defined(initialColor)) { // reset colors for pie
|
10813
10886
|
chart.counters.color = initialColor;
|
10814
10887
|
}
|
10815
|
-
|
10888
|
+
|
10816
10889
|
// parallel arrays
|
10817
10890
|
var xData = [],
|
10818
10891
|
yData = [],
|
@@ -10826,15 +10899,15 @@ Series.prototype = {
|
|
10826
10899
|
// way. Although the 'for' loops are similar, they are repeated inside each
|
10827
10900
|
// if-else conditional for max performance.
|
10828
10901
|
if (dataLength > turboThreshold) {
|
10829
|
-
|
10902
|
+
|
10830
10903
|
// find the first non-null point
|
10831
10904
|
i = 0;
|
10832
10905
|
while (firstPoint === null && i < dataLength) {
|
10833
10906
|
firstPoint = data[i];
|
10834
10907
|
i++;
|
10835
10908
|
}
|
10836
|
-
|
10837
|
-
|
10909
|
+
|
10910
|
+
|
10838
10911
|
if (isNumber(firstPoint)) { // assume all points are numbers
|
10839
10912
|
var x = pick(options.pointStart, 0),
|
10840
10913
|
pointInterval = pick(options.pointInterval, 1);
|
@@ -10884,6 +10957,13 @@ Series.prototype = {
|
|
10884
10957
|
}
|
10885
10958
|
}
|
10886
10959
|
|
10960
|
+
// reset minRange (#878)
|
10961
|
+
// TODO: In protofy, run this code instead:
|
10962
|
+
// if (xAxis) xAxis.minRange = UNDEFINED;
|
10963
|
+
if (xAxis && xAxis.setMinRange) {
|
10964
|
+
xAxis.setMinRange(); // to undefined
|
10965
|
+
}
|
10966
|
+
|
10887
10967
|
// redraw
|
10888
10968
|
series.isDirty = series.isDirtyData = chart.isDirtyBox = true;
|
10889
10969
|
if (pick(redraw, true)) {
|
@@ -10948,7 +11028,7 @@ Series.prototype = {
|
|
10948
11028
|
isCartesian = series.isCartesian;
|
10949
11029
|
|
10950
11030
|
// If the series data or axes haven't changed, don't go through this. Return false to pass
|
10951
|
-
// the message on to override methods like in data grouping.
|
11031
|
+
// the message on to override methods like in data grouping.
|
10952
11032
|
if (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) {
|
10953
11033
|
return false;
|
10954
11034
|
}
|
@@ -10963,7 +11043,7 @@ Series.prototype = {
|
|
10963
11043
|
if (processedXData[dataLength - 1] < min || processedXData[0] > max) {
|
10964
11044
|
processedXData = [];
|
10965
11045
|
processedYData = [];
|
10966
|
-
|
11046
|
+
|
10967
11047
|
// only crop if it's actually spilling out
|
10968
11048
|
} else if (processedXData[0] < min || processedXData[dataLength - 1] > max) {
|
10969
11049
|
|
@@ -10980,15 +11060,15 @@ Series.prototype = {
|
|
10980
11060
|
cropEnd = i + 1;
|
10981
11061
|
break;
|
10982
11062
|
}
|
10983
|
-
|
11063
|
+
|
10984
11064
|
}
|
10985
11065
|
processedXData = processedXData.slice(cropStart, cropEnd);
|
10986
11066
|
processedYData = processedYData.slice(cropStart, cropEnd);
|
10987
11067
|
cropped = true;
|
10988
11068
|
}
|
10989
11069
|
}
|
10990
|
-
|
10991
|
-
|
11070
|
+
|
11071
|
+
|
10992
11072
|
// Find the closest distance between processed points
|
10993
11073
|
for (i = processedXData.length - 1; i > 0; i--) {
|
10994
11074
|
distance = processedXData[i] - processedXData[i - 1];
|
@@ -10996,18 +11076,18 @@ Series.prototype = {
|
|
10996
11076
|
closestPointRange = distance;
|
10997
11077
|
}
|
10998
11078
|
}
|
10999
|
-
|
11079
|
+
|
11000
11080
|
// Record the properties
|
11001
11081
|
series.cropped = cropped; // undefined or true
|
11002
11082
|
series.cropStart = cropStart;
|
11003
11083
|
series.processedXData = processedXData;
|
11004
11084
|
series.processedYData = processedYData;
|
11005
|
-
|
11085
|
+
|
11006
11086
|
if (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC
|
11007
11087
|
series.pointRange = closestPointRange || 1;
|
11008
11088
|
}
|
11009
11089
|
series.closestPointRange = closestPointRange;
|
11010
|
-
|
11090
|
+
|
11011
11091
|
},
|
11012
11092
|
|
11013
11093
|
/**
|
@@ -11053,7 +11133,7 @@ Series.prototype = {
|
|
11053
11133
|
}
|
11054
11134
|
|
11055
11135
|
// Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when
|
11056
|
-
// swithching view from non-grouped data to grouped data (#637)
|
11136
|
+
// swithching view from non-grouped data to grouped data (#637)
|
11057
11137
|
if (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) {
|
11058
11138
|
for (i = 0; i < dataLength; i++) {
|
11059
11139
|
if (i === cropStart && !hasGroupedData) { // when has grouped data, clear all points
|
@@ -11091,7 +11171,7 @@ Series.prototype = {
|
|
11091
11171
|
isLastSeries,
|
11092
11172
|
allStackSeries = yAxis.series,
|
11093
11173
|
i = allStackSeries.length;
|
11094
|
-
|
11174
|
+
|
11095
11175
|
// Is it the last visible series?
|
11096
11176
|
while (i--) {
|
11097
11177
|
if (allStackSeries[i].visible) {
|
@@ -11101,7 +11181,7 @@ Series.prototype = {
|
|
11101
11181
|
break;
|
11102
11182
|
}
|
11103
11183
|
}
|
11104
|
-
|
11184
|
+
|
11105
11185
|
// Translate each point
|
11106
11186
|
for (i = 0; i < dataLength; i++) {
|
11107
11187
|
var point = points[i],
|
@@ -11111,7 +11191,7 @@ Series.prototype = {
|
|
11111
11191
|
stack = yAxis.stacks[(yValue < options.threshold ? '-' : '') + series.stackKey],
|
11112
11192
|
pointStack,
|
11113
11193
|
pointStackTotal;
|
11114
|
-
|
11194
|
+
|
11115
11195
|
// get the plotX translation
|
11116
11196
|
point.plotX = mathRound(xAxis.translate(xValue, 0, 0, 0, 1) * 10) / 10; // Math.round fixes #591
|
11117
11197
|
|
@@ -11121,11 +11201,11 @@ Series.prototype = {
|
|
11121
11201
|
pointStackTotal = pointStack.total;
|
11122
11202
|
pointStack.cum = yBottom = pointStack.cum - yValue; // start from top
|
11123
11203
|
yValue = yBottom + yValue;
|
11124
|
-
|
11204
|
+
|
11125
11205
|
if (isLastSeries) {
|
11126
11206
|
yBottom = options.threshold;
|
11127
11207
|
}
|
11128
|
-
|
11208
|
+
|
11129
11209
|
if (stacking === 'percent') {
|
11130
11210
|
yBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0;
|
11131
11211
|
yValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0;
|
@@ -11137,17 +11217,17 @@ Series.prototype = {
|
|
11137
11217
|
}
|
11138
11218
|
|
11139
11219
|
// Set translated yBottom or remove it
|
11140
|
-
point.yBottom = defined(yBottom) ?
|
11220
|
+
point.yBottom = defined(yBottom) ?
|
11141
11221
|
yAxis.translate(yBottom, 0, 1, 0, 1) :
|
11142
11222
|
null;
|
11143
|
-
|
11223
|
+
|
11144
11224
|
// general hook, used for Highstock compare mode
|
11145
11225
|
if (hasModifyValue) {
|
11146
11226
|
yValue = series.modifyValue(yValue, point);
|
11147
11227
|
}
|
11148
11228
|
|
11149
11229
|
// Set the the plotY value, reset it for redraws
|
11150
|
-
point.plotY = (typeof yValue === 'number') ?
|
11230
|
+
point.plotY = (typeof yValue === 'number') ?
|
11151
11231
|
mathRound(yAxis.translate(yValue, 0, 1, 0, 1) * 10) / 10 : // Math.round fixes #591
|
11152
11232
|
UNDEFINED;
|
11153
11233
|
|
@@ -11172,10 +11252,9 @@ Series.prototype = {
|
|
11172
11252
|
setTooltipPoints: function (renew) {
|
11173
11253
|
var series = this,
|
11174
11254
|
chart = series.chart,
|
11175
|
-
inverted = chart.inverted,
|
11176
11255
|
points = [],
|
11177
11256
|
pointsLength,
|
11178
|
-
plotSize =
|
11257
|
+
plotSize = chart.plotSizeX,
|
11179
11258
|
low,
|
11180
11259
|
high,
|
11181
11260
|
xAxis = series.xAxis,
|
@@ -11201,10 +11280,10 @@ Series.prototype = {
|
|
11201
11280
|
// loop the concatenated points and apply each point to all the closest
|
11202
11281
|
// pixel positions
|
11203
11282
|
if (xAxis && xAxis.reversed) {
|
11204
|
-
points = points.reverse()
|
11283
|
+
points = points.reverse();
|
11205
11284
|
}
|
11206
11285
|
|
11207
|
-
//each
|
11286
|
+
// Assign each pixel position to the nearest point
|
11208
11287
|
pointsLength = points.length;
|
11209
11288
|
for (i = 0; i < pointsLength; i++) {
|
11210
11289
|
point = points[i];
|
@@ -11214,7 +11293,7 @@ Series.prototype = {
|
|
11214
11293
|
plotSize;
|
11215
11294
|
|
11216
11295
|
while (low <= high) {
|
11217
|
-
tooltipPoints[
|
11296
|
+
tooltipPoints[low++] = point;
|
11218
11297
|
}
|
11219
11298
|
}
|
11220
11299
|
series.tooltipPoints = tooltipPoints;
|
@@ -11229,7 +11308,7 @@ Series.prototype = {
|
|
11229
11308
|
xDateFormat = tooltipOptions.xDateFormat || '%A, %b %e, %Y',
|
11230
11309
|
xAxis = series.xAxis,
|
11231
11310
|
isDateTime = xAxis && xAxis.options.type === 'datetime';
|
11232
|
-
|
11311
|
+
|
11233
11312
|
return tooltipOptions.headerFormat
|
11234
11313
|
.replace('{point.key}', isDateTime ? dateFormat(xDateFormat, key) : key)
|
11235
11314
|
.replace('{series.name}', series.name)
|
@@ -11556,7 +11635,7 @@ Series.prototype = {
|
|
11556
11635
|
|
11557
11636
|
// remove all events
|
11558
11637
|
removeEvent(series);
|
11559
|
-
|
11638
|
+
|
11560
11639
|
// erase from axes
|
11561
11640
|
each(['xAxis', 'yAxis'], function (AXIS) {
|
11562
11641
|
axis = series[AXIS];
|
@@ -11616,11 +11695,11 @@ Series.prototype = {
|
|
11616
11695
|
* Draw the data labels
|
11617
11696
|
*/
|
11618
11697
|
drawDataLabels: function () {
|
11619
|
-
|
11698
|
+
|
11620
11699
|
var series = this,
|
11621
11700
|
seriesOptions = series.options,
|
11622
11701
|
options = seriesOptions.dataLabels;
|
11623
|
-
|
11702
|
+
|
11624
11703
|
if (options.enabled || series._hasPointLabels) {
|
11625
11704
|
var x,
|
11626
11705
|
y,
|
@@ -11649,8 +11728,8 @@ Series.prototype = {
|
|
11649
11728
|
|
11650
11729
|
if (isBarLike) {
|
11651
11730
|
var defaultYs = {
|
11652
|
-
top: fontBaseline,
|
11653
|
-
middle: fontBaseline - fontLineHeight / 2,
|
11731
|
+
top: fontBaseline,
|
11732
|
+
middle: fontBaseline - fontLineHeight / 2,
|
11654
11733
|
bottom: -fontLineHeight + fontBaseline
|
11655
11734
|
};
|
11656
11735
|
if (stacking) {
|
@@ -11667,12 +11746,12 @@ Series.prototype = {
|
|
11667
11746
|
// In non stacked series the default label placement is on top of the bars
|
11668
11747
|
if (vAlignIsNull) {
|
11669
11748
|
options = merge(options, {verticalAlign: 'top'});
|
11670
|
-
|
11749
|
+
|
11671
11750
|
// If no y delta is specified, try to create a good default (like default bar)
|
11672
11751
|
} else if (yIsNull) {
|
11673
11752
|
options = merge(options, { y: defaultYs[options.verticalAlign]});
|
11674
11753
|
}
|
11675
|
-
|
11754
|
+
|
11676
11755
|
}
|
11677
11756
|
}
|
11678
11757
|
|
@@ -11690,13 +11769,13 @@ Series.prototype = {
|
|
11690
11769
|
} else {
|
11691
11770
|
dataLabelsGroup.translate(groupLeft, groupTop);
|
11692
11771
|
}
|
11693
|
-
|
11772
|
+
|
11694
11773
|
// make the labels for each point
|
11695
11774
|
generalOptions = options;
|
11696
11775
|
each(points, function (point) {
|
11697
|
-
|
11776
|
+
|
11698
11777
|
dataLabel = point.dataLabel;
|
11699
|
-
|
11778
|
+
|
11700
11779
|
// Merge in individual options from point
|
11701
11780
|
options = generalOptions; // reset changes from previous points
|
11702
11781
|
pointOptions = point.options;
|
@@ -11704,52 +11783,52 @@ Series.prototype = {
|
|
11704
11783
|
options = merge(options, pointOptions.dataLabels);
|
11705
11784
|
}
|
11706
11785
|
enabled = options.enabled;
|
11707
|
-
|
11786
|
+
|
11708
11787
|
// Get the positions
|
11709
11788
|
if (enabled) {
|
11710
11789
|
var plotX = (point.barX && point.barX + point.barW / 2) || pick(point.plotX, -999),
|
11711
11790
|
plotY = pick(point.plotY, -999),
|
11712
|
-
|
11791
|
+
|
11713
11792
|
// if options.y is null, which happens by default on column charts, set the position
|
11714
11793
|
// above or below the column depending on the threshold
|
11715
|
-
individualYDelta = options.y === null ?
|
11716
|
-
(point.y >= seriesOptions.threshold ?
|
11717
|
-
-fontLineHeight + fontBaseline : // below the threshold
|
11794
|
+
individualYDelta = options.y === null ?
|
11795
|
+
(point.y >= seriesOptions.threshold ?
|
11796
|
+
-fontLineHeight + fontBaseline : // below the threshold
|
11718
11797
|
fontBaseline) : // above the threshold
|
11719
11798
|
options.y;
|
11720
|
-
|
11799
|
+
|
11721
11800
|
x = (inverted ? chart.plotWidth - plotY : plotX) + options.x;
|
11722
11801
|
y = mathRound((inverted ? chart.plotHeight - plotX : plotY) + individualYDelta);
|
11723
|
-
|
11802
|
+
|
11724
11803
|
}
|
11725
|
-
|
11804
|
+
|
11726
11805
|
// If the point is outside the plot area, destroy it. #678, #820
|
11727
11806
|
if (dataLabel && series.isCartesian && (!chart.isInsidePlot(x, y) || !enabled)) {
|
11728
11807
|
point.dataLabel = dataLabel.destroy();
|
11729
|
-
|
11730
|
-
// Individual labels are disabled if the are explicitly disabled
|
11808
|
+
|
11809
|
+
// Individual labels are disabled if the are explicitly disabled
|
11731
11810
|
// in the point options, or if they fall outside the plot area.
|
11732
11811
|
} else if (enabled) {
|
11733
|
-
|
11812
|
+
|
11734
11813
|
var align = options.align;
|
11735
|
-
|
11814
|
+
|
11736
11815
|
// Get the string
|
11737
11816
|
str = options.formatter.call(point.getLabelConfig(), options);
|
11738
|
-
|
11817
|
+
|
11739
11818
|
// in columns, align the string to the column
|
11740
11819
|
if (seriesType === 'column') {
|
11741
11820
|
x += { left: -1, right: 1 }[align] * point.barW / 2 || 0;
|
11742
11821
|
}
|
11743
|
-
|
11822
|
+
|
11744
11823
|
if (!stacking && inverted && point.y < 0) {
|
11745
11824
|
align = 'right';
|
11746
11825
|
x -= 10;
|
11747
11826
|
}
|
11748
|
-
|
11827
|
+
|
11749
11828
|
// Determine the color
|
11750
11829
|
options.style.color = pick(options.color, options.style.color, series.color, 'black');
|
11751
|
-
|
11752
|
-
|
11830
|
+
|
11831
|
+
|
11753
11832
|
// update existing label
|
11754
11833
|
if (dataLabel) {
|
11755
11834
|
// vertically centered
|
@@ -11777,7 +11856,7 @@ Series.prototype = {
|
|
11777
11856
|
fill: options.backgroundColor,
|
11778
11857
|
stroke: options.borderColor,
|
11779
11858
|
'stroke-width': options.borderWidth,
|
11780
|
-
r: options.borderRadius,
|
11859
|
+
r: options.borderRadius || 0,
|
11781
11860
|
rotation: options.rotation,
|
11782
11861
|
padding: options.padding,
|
11783
11862
|
zIndex: 1
|
@@ -11786,13 +11865,13 @@ Series.prototype = {
|
|
11786
11865
|
.add(dataLabelsGroup)
|
11787
11866
|
.shadow(options.shadow);
|
11788
11867
|
}
|
11789
|
-
|
11868
|
+
|
11790
11869
|
if (isBarLike && seriesOptions.stacking && dataLabel) {
|
11791
11870
|
var barX = point.barX,
|
11792
11871
|
barY = point.barY,
|
11793
11872
|
barW = point.barW,
|
11794
11873
|
barH = point.barH;
|
11795
|
-
|
11874
|
+
|
11796
11875
|
dataLabel.align(options, null,
|
11797
11876
|
{
|
11798
11877
|
x: inverted ? chart.plotWidth - barY - barH : barX,
|
@@ -11801,8 +11880,8 @@ Series.prototype = {
|
|
11801
11880
|
height: inverted ? barW : barH
|
11802
11881
|
});
|
11803
11882
|
}
|
11804
|
-
|
11805
|
-
|
11883
|
+
|
11884
|
+
|
11806
11885
|
}
|
11807
11886
|
});
|
11808
11887
|
}
|
@@ -11883,17 +11962,17 @@ Series.prototype = {
|
|
11883
11962
|
areaSegmentPath.push(L, segmentPath[1], segmentPath[2]);
|
11884
11963
|
}
|
11885
11964
|
if (options.stacking && series.type !== 'areaspline') {
|
11886
|
-
|
11887
|
-
// Follow stack back. Todo: implement areaspline. A general solution could be to
|
11965
|
+
|
11966
|
+
// Follow stack back. Todo: implement areaspline. A general solution could be to
|
11888
11967
|
// reverse the entire graphPath of the previous series, though may be hard with
|
11889
11968
|
// splines and with series with different extremes
|
11890
11969
|
for (i = segment.length - 1; i >= 0; i--) {
|
11891
|
-
|
11970
|
+
|
11892
11971
|
// step line?
|
11893
11972
|
if (i < segment.length - 1 && options.step) {
|
11894
11973
|
areaSegmentPath.push(segment[i + 1].plotX, segment[i].yBottom);
|
11895
11974
|
}
|
11896
|
-
|
11975
|
+
|
11897
11976
|
areaSegmentPath.push(segment[i].plotX, segment[i].yBottom);
|
11898
11977
|
}
|
11899
11978
|
|
@@ -11962,17 +12041,17 @@ Series.prototype = {
|
|
11962
12041
|
group = series.group,
|
11963
12042
|
trackerGroup = series.trackerGroup,
|
11964
12043
|
chart = series.chart;
|
11965
|
-
|
12044
|
+
|
11966
12045
|
// A fixed size is needed for inversion to work
|
11967
|
-
function setInvert() {
|
12046
|
+
function setInvert() {
|
11968
12047
|
var size = {
|
11969
12048
|
width: series.yAxis.len,
|
11970
12049
|
height: series.xAxis.len
|
11971
12050
|
};
|
11972
|
-
|
12051
|
+
|
11973
12052
|
// Set the series.group size
|
11974
12053
|
group.attr(size).invert();
|
11975
|
-
|
12054
|
+
|
11976
12055
|
// Set the tracker group size
|
11977
12056
|
if (trackerGroup) {
|
11978
12057
|
trackerGroup.attr(size).invert();
|
@@ -11986,7 +12065,7 @@ Series.prototype = {
|
|
11986
12065
|
|
11987
12066
|
// Do it now
|
11988
12067
|
setInvert(); // do it now
|
11989
|
-
|
12068
|
+
|
11990
12069
|
// On subsequent render and redraw, just do setInvert without setting up events again
|
11991
12070
|
series.invertGroups = setInvert;
|
11992
12071
|
},
|
@@ -12021,7 +12100,7 @@ Series.prototype = {
|
|
12021
12100
|
chart.clipRect = clipRect;
|
12022
12101
|
}
|
12023
12102
|
}
|
12024
|
-
|
12103
|
+
|
12025
12104
|
|
12026
12105
|
// the group
|
12027
12106
|
if (!series.group) {
|
@@ -12057,12 +12136,12 @@ Series.prototype = {
|
|
12057
12136
|
if (series.options.enableMouseTracking !== false) {
|
12058
12137
|
series.drawTracker();
|
12059
12138
|
}
|
12060
|
-
|
12139
|
+
|
12061
12140
|
// Handle inverted series and tracker groups
|
12062
12141
|
if (chart.inverted) {
|
12063
12142
|
series.invertGroups();
|
12064
12143
|
}
|
12065
|
-
|
12144
|
+
|
12066
12145
|
// Do the initial clipping. This must be done after inverting for VML.
|
12067
12146
|
if (doClip && !series.hasRendered) {
|
12068
12147
|
group.clip(clipRect);
|
@@ -12070,7 +12149,7 @@ Series.prototype = {
|
|
12070
12149
|
series.trackerGroup.clip(chart.clipRect);
|
12071
12150
|
}
|
12072
12151
|
}
|
12073
|
-
|
12152
|
+
|
12074
12153
|
|
12075
12154
|
// run the animation
|
12076
12155
|
if (doAnimation) {
|
@@ -12271,26 +12350,26 @@ Series.prototype = {
|
|
12271
12350
|
drawTrackerGroup: function () {
|
12272
12351
|
var trackerGroup = this.trackerGroup,
|
12273
12352
|
chart = this.chart;
|
12274
|
-
|
12353
|
+
|
12275
12354
|
if (this.isCartesian) {
|
12276
|
-
|
12355
|
+
|
12277
12356
|
// Generate it on first call
|
12278
|
-
if (!trackerGroup) {
|
12357
|
+
if (!trackerGroup) {
|
12279
12358
|
this.trackerGroup = trackerGroup = chart.renderer.g()
|
12280
12359
|
.attr({
|
12281
12360
|
zIndex: this.options.zIndex || 1
|
12282
12361
|
})
|
12283
12362
|
.add(chart.trackerGroup);
|
12284
|
-
|
12363
|
+
|
12285
12364
|
}
|
12286
12365
|
// Place it on first and subsequent (redraw) calls
|
12287
12366
|
trackerGroup.translate(this.xAxis.left, this.yAxis.top);
|
12288
|
-
|
12367
|
+
|
12289
12368
|
}
|
12290
|
-
|
12369
|
+
|
12291
12370
|
return trackerGroup;
|
12292
12371
|
},
|
12293
|
-
|
12372
|
+
|
12294
12373
|
/**
|
12295
12374
|
* Draw the tracker object that sits above all data labels and markers to
|
12296
12375
|
* track mouse events on the graph or points. For the line type charts
|
@@ -12333,15 +12412,15 @@ Series.prototype = {
|
|
12333
12412
|
trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY,
|
12334
12413
|
L, singlePoint.plotX + snap, singlePoint.plotY);
|
12335
12414
|
}
|
12336
|
-
|
12337
|
-
|
12415
|
+
|
12416
|
+
|
12338
12417
|
|
12339
12418
|
// draw the tracker
|
12340
12419
|
if (tracker) {
|
12341
12420
|
tracker.attr({ d: trackerPath });
|
12342
12421
|
|
12343
12422
|
} else { // create
|
12344
|
-
|
12423
|
+
|
12345
12424
|
series.tracker = renderer.path(trackerPath)
|
12346
12425
|
.attr({
|
12347
12426
|
isTracker: true,
|
@@ -12612,7 +12691,7 @@ var ColumnSeries = extendClass(Series, {
|
|
12612
12691
|
r: options.borderRadius,
|
12613
12692
|
strokeWidth: borderWidth
|
12614
12693
|
};
|
12615
|
-
|
12694
|
+
|
12616
12695
|
if (borderWidth % 2) { // correct for shorting in crisp method, visible in stacked columns with 1px border
|
12617
12696
|
shapeArgs.y -= 1;
|
12618
12697
|
shapeArgs.height += 1;
|
@@ -12670,7 +12749,7 @@ var ColumnSeries = extendClass(Series, {
|
|
12670
12749
|
.attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE])
|
12671
12750
|
.add(series.group)
|
12672
12751
|
.shadow(options.shadow);
|
12673
|
-
|
12752
|
+
|
12674
12753
|
}
|
12675
12754
|
|
12676
12755
|
}
|
@@ -12691,13 +12770,17 @@ var ColumnSeries = extendClass(Series, {
|
|
12691
12770
|
cursor = options.cursor,
|
12692
12771
|
css = cursor && { cursor: cursor },
|
12693
12772
|
trackerGroup = series.drawTrackerGroup(),
|
12694
|
-
rel
|
12695
|
-
|
12773
|
+
rel,
|
12774
|
+
plotY,
|
12775
|
+
validPlotY;
|
12776
|
+
|
12696
12777
|
each(series.points, function (point) {
|
12697
12778
|
tracker = point.tracker;
|
12698
12779
|
shapeArgs = point.trackerArgs || point.shapeArgs;
|
12780
|
+
plotY = point.plotY;
|
12781
|
+
validPlotY = !series.isCartesian || (plotY !== UNDEFINED && !isNaN(plotY));
|
12699
12782
|
delete shapeArgs.strokeWidth;
|
12700
|
-
if (point.y !== null) {
|
12783
|
+
if (point.y !== null && validPlotY) {
|
12701
12784
|
if (tracker) {// update
|
12702
12785
|
tracker.attr(shapeArgs);
|
12703
12786
|
|
@@ -12761,7 +12844,7 @@ var ColumnSeries = extendClass(Series, {
|
|
12761
12844
|
// start values
|
12762
12845
|
graphic.attr({
|
12763
12846
|
height: 0,
|
12764
|
-
y: defined(threshold) ?
|
12847
|
+
y: defined(threshold) ?
|
12765
12848
|
yAxis.getThreshold(threshold) :
|
12766
12849
|
yAxis.translate(yAxis.getExtremes().min, 0, 1, 0, 1)
|
12767
12850
|
});
|
@@ -12852,10 +12935,10 @@ var ScatterSeries = extendClass(Series, {
|
|
12852
12935
|
while (i--) {
|
12853
12936
|
graphic = points[i].graphic;
|
12854
12937
|
if (graphic) { // doesn't exist for null points
|
12855
|
-
graphic.element._i = i;
|
12938
|
+
graphic.element._i = i;
|
12856
12939
|
}
|
12857
12940
|
}
|
12858
|
-
|
12941
|
+
|
12859
12942
|
// Add the event listeners, we need to do this only once
|
12860
12943
|
if (!series._hasTracking) {
|
12861
12944
|
series.group
|
@@ -13040,17 +13123,20 @@ var PieSeries = extendClass(Series, {
|
|
13040
13123
|
* Extend the basic setData method by running processData and generatePoints immediately,
|
13041
13124
|
* in order to access the points from the legend.
|
13042
13125
|
*/
|
13043
|
-
setData: function () {
|
13044
|
-
Series.prototype.setData.
|
13126
|
+
setData: function (data, redraw) {
|
13127
|
+
Series.prototype.setData.call(this, data, false);
|
13045
13128
|
this.processData();
|
13046
13129
|
this.generatePoints();
|
13130
|
+
if (pick(redraw, true)) {
|
13131
|
+
this.chart.redraw();
|
13132
|
+
}
|
13047
13133
|
},
|
13048
13134
|
/**
|
13049
13135
|
* Do translation for pie slices
|
13050
13136
|
*/
|
13051
13137
|
translate: function () {
|
13052
13138
|
this.generatePoints();
|
13053
|
-
|
13139
|
+
|
13054
13140
|
var total = 0,
|
13055
13141
|
series = this,
|
13056
13142
|
cumulative = -0.25, // start at top
|
@@ -13315,7 +13401,7 @@ var PieSeries = extendClass(Series, {
|
|
13315
13401
|
// assume equal label heights
|
13316
13402
|
labelHeight = halves[0][0] && halves[0][0].dataLabel && halves[0][0].dataLabel.getBBox().height;
|
13317
13403
|
|
13318
|
-
/* Loop over the points in each
|
13404
|
+
/* Loop over the points in each half, starting from the top and bottom
|
13319
13405
|
* of the pie to detect overlapping labels.
|
13320
13406
|
*/
|
13321
13407
|
while (i--) {
|
@@ -13328,115 +13414,126 @@ var PieSeries = extendClass(Series, {
|
|
13328
13414
|
length = points.length,
|
13329
13415
|
slotIndex;
|
13330
13416
|
|
13331
|
-
|
13332
|
-
|
13333
|
-
|
13334
|
-
slots
|
13335
|
-
|
13336
|
-
|
13337
|
-
|
13338
|
-
|
13339
|
-
|
13340
|
-
|
13341
|
-
|
13342
|
-
|
13343
|
-
|
13344
|
-
|
13345
|
-
|
13346
|
-
|
13347
|
-
|
13348
|
-
|
13349
|
-
|
13350
|
-
|
13351
|
-
|
13352
|
-
|
13353
|
-
|
13354
|
-
|
13355
|
-
|
13356
|
-
|
13357
|
-
//
|
13358
|
-
|
13359
|
-
|
13360
|
-
|
13361
|
-
|
13362
|
-
|
13363
|
-
|
13364
|
-
|
13365
|
-
|
13366
|
-
|
13367
|
-
|
13417
|
+
// Only do anti-collision when we are outside the pie and have connectors (#856)
|
13418
|
+
if (distanceOption > 0) {
|
13419
|
+
|
13420
|
+
// build the slots
|
13421
|
+
for (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) {
|
13422
|
+
slots.push(pos);
|
13423
|
+
// visualize the slot
|
13424
|
+
/*
|
13425
|
+
var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0),
|
13426
|
+
slotY = pos + chart.plotTop;
|
13427
|
+
if (!isNaN(slotX)) {
|
13428
|
+
chart.renderer.rect(slotX, slotY - 7, 100, labelHeight)
|
13429
|
+
.attr({
|
13430
|
+
'stroke-width': 1,
|
13431
|
+
stroke: 'silver'
|
13432
|
+
})
|
13433
|
+
.add();
|
13434
|
+
chart.renderer.text('Slot '+ (slots.length - 1), slotX, slotY + 4)
|
13435
|
+
.attr({
|
13436
|
+
fill: 'silver'
|
13437
|
+
}).add();
|
13438
|
+
}
|
13439
|
+
// */
|
13440
|
+
}
|
13441
|
+
slotsLength = slots.length;
|
13442
|
+
|
13443
|
+
// if there are more values than available slots, remove lowest values
|
13444
|
+
if (length > slotsLength) {
|
13445
|
+
// create an array for sorting and ranking the points within each quarter
|
13446
|
+
rankArr = [].concat(points);
|
13447
|
+
rankArr.sort(sort);
|
13448
|
+
j = length;
|
13449
|
+
while (j--) {
|
13450
|
+
rankArr[j].rank = j;
|
13451
|
+
}
|
13452
|
+
j = length;
|
13453
|
+
while (j--) {
|
13454
|
+
if (points[j].rank >= slotsLength) {
|
13455
|
+
points.splice(j, 1);
|
13456
|
+
}
|
13368
13457
|
}
|
13458
|
+
length = points.length;
|
13369
13459
|
}
|
13370
|
-
length = points.length;
|
13371
|
-
}
|
13372
13460
|
|
13373
|
-
|
13374
|
-
|
13375
|
-
|
13461
|
+
// The label goes to the nearest open slot, but not closer to the edge than
|
13462
|
+
// the label's index.
|
13463
|
+
for (j = 0; j < length; j++) {
|
13376
13464
|
|
13377
|
-
|
13378
|
-
|
13465
|
+
point = points[j];
|
13466
|
+
labelPos = point.labelPos;
|
13379
13467
|
|
13380
|
-
|
13381
|
-
|
13382
|
-
|
13468
|
+
var closest = 9999,
|
13469
|
+
distance,
|
13470
|
+
slotI;
|
13383
13471
|
|
13384
|
-
|
13385
|
-
|
13386
|
-
|
13387
|
-
|
13388
|
-
|
13389
|
-
|
13472
|
+
// find the closest slot index
|
13473
|
+
for (slotI = 0; slotI < slotsLength; slotI++) {
|
13474
|
+
distance = mathAbs(slots[slotI] - labelPos[1]);
|
13475
|
+
if (distance < closest) {
|
13476
|
+
closest = distance;
|
13477
|
+
slotIndex = slotI;
|
13478
|
+
}
|
13390
13479
|
}
|
13391
|
-
}
|
13392
13480
|
|
13393
|
-
|
13394
|
-
|
13395
|
-
|
13396
|
-
|
13397
|
-
|
13398
|
-
|
13399
|
-
|
13400
|
-
|
13401
|
-
|
13402
|
-
|
13403
|
-
|
13404
|
-
|
13405
|
-
|
13406
|
-
|
13481
|
+
// if that slot index is closer to the edges of the slots, move it
|
13482
|
+
// to the closest appropriate slot
|
13483
|
+
if (slotIndex < j && slots[j] !== null) { // cluster at the top
|
13484
|
+
slotIndex = j;
|
13485
|
+
} else if (slotsLength < length - j + slotIndex && slots[j] !== null) { // cluster at the bottom
|
13486
|
+
slotIndex = slotsLength - length + j;
|
13487
|
+
while (slots[slotIndex] === null) { // make sure it is not taken
|
13488
|
+
slotIndex++;
|
13489
|
+
}
|
13490
|
+
} else {
|
13491
|
+
// Slot is taken, find next free slot below. In the next run, the next slice will find the
|
13492
|
+
// slot above these, because it is the closest one
|
13493
|
+
while (slots[slotIndex] === null) { // make sure it is not taken
|
13494
|
+
slotIndex++;
|
13495
|
+
}
|
13407
13496
|
}
|
13408
|
-
}
|
13409
13497
|
|
13410
|
-
|
13411
|
-
|
13498
|
+
usedSlots.push({ i: slotIndex, y: slots[slotIndex] });
|
13499
|
+
slots[slotIndex] = null; // mark as taken
|
13500
|
+
}
|
13501
|
+
// sort them in order to fill in from the top
|
13502
|
+
usedSlots.sort(sort);
|
13412
13503
|
}
|
13413
|
-
// sort them in order to fill in from the top
|
13414
|
-
usedSlots.sort(sort);
|
13415
|
-
|
13416
13504
|
|
13417
13505
|
// now the used slots are sorted, fill them up sequentially
|
13418
13506
|
for (j = 0; j < length; j++) {
|
13419
13507
|
|
13508
|
+
var slot, naturalY;
|
13509
|
+
|
13420
13510
|
point = points[j];
|
13421
13511
|
labelPos = point.labelPos;
|
13422
13512
|
dataLabel = point.dataLabel;
|
13423
|
-
var slot = usedSlots.pop(),
|
13424
|
-
naturalY = labelPos[1];
|
13425
|
-
|
13426
13513
|
visibility = point.visible === false ? HIDDEN : VISIBLE;
|
13427
|
-
|
13514
|
+
naturalY = labelPos[1];
|
13515
|
+
|
13516
|
+
if (distanceOption > 0) {
|
13517
|
+
slot = usedSlots.pop();
|
13518
|
+
slotIndex = slot.i;
|
13519
|
+
|
13520
|
+
// if the slot next to currrent slot is free, the y value is allowed
|
13521
|
+
// to fall back to the natural position
|
13522
|
+
y = slot.y;
|
13523
|
+
if ((naturalY > y && slots[slotIndex + 1] !== null) ||
|
13524
|
+
(naturalY < y && slots[slotIndex - 1] !== null)) {
|
13525
|
+
y = naturalY;
|
13526
|
+
}
|
13428
13527
|
|
13429
|
-
|
13430
|
-
// to fall back to the natural position
|
13431
|
-
y = slot.y;
|
13432
|
-
if ((naturalY > y && slots[slotIndex + 1] !== null) ||
|
13433
|
-
(naturalY < y && slots[slotIndex - 1] !== null)) {
|
13528
|
+
} else {
|
13434
13529
|
y = naturalY;
|
13435
13530
|
}
|
13436
13531
|
|
13437
13532
|
// get the x - use the natural x position for first and last slot, to prevent the top
|
13438
13533
|
// and botton slice connectors from touching each other on either side
|
13439
|
-
x =
|
13534
|
+
x = options.justify ?
|
13535
|
+
seriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) :
|
13536
|
+
series.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i);
|
13440
13537
|
|
13441
13538
|
// move or place the data label
|
13442
13539
|
dataLabel
|
@@ -13538,6 +13635,6 @@ extend(Highcharts, {
|
|
13538
13635
|
extendClass: extendClass,
|
13539
13636
|
placeBox: placeBox,
|
13540
13637
|
product: 'Highcharts',
|
13541
|
-
version: '2.2.
|
13638
|
+
version: '2.2.2'
|
13542
13639
|
});
|
13543
13640
|
}());
|