highcharts-js-rails 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.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
|
}());
|