app/assets/javascripts/highcharts.js in highcharts-rails-5.0.9 vs app/assets/javascripts/highcharts.js in highcharts-rails-5.0.10
- old
+ new
@@ -1,7 +1,7 @@
/**
- * @license Highcharts JS v5.0.9 (2017-03-08)
+ * @license Highcharts JS v5.0.10 (2017-03-31)
*
* (c) 2009-2016 Torstein Honsi
*
* License: www.highcharts.com/license
*/
@@ -15,11 +15,11 @@
root.Highcharts = factory(root);
}
}(typeof window !== 'undefined' ? window : this, function(win) {
var Highcharts = (function() {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
/* global window */
var win = window,
@@ -33,11 +33,11 @@
isFirefox = /Firefox/.test(userAgent),
hasBidiBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4; // issue #38
var Highcharts = win.Highcharts ? win.Highcharts.error(16, true) : {
product: 'Highcharts',
- version: '5.0.9',
+ version: '5.0.10',
deg2rad: Math.PI * 2 / 360,
doc: doc,
hasBidiBug: hasBidiBug,
hasTouch: doc && doc.documentElement.ontouchstart !== undefined,
isMS: isMS,
@@ -59,11 +59,11 @@
};
return Highcharts;
}());
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
/* eslint max-len: ["warn", 80, 4] */
@@ -2089,11 +2089,11 @@
//--- End compatibility section ---
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var each = H.each,
isNumber = H.isNumber,
@@ -2137,12 +2137,12 @@
parse: function(result) {
return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1];
}
}],
- // Collection of named colors. Can be extended from the outside by adding colors
- // to Highcharts.Color.prototype.names.
+ // Collection of named colors. Can be extended from the outside by adding
+ // colors to Highcharts.Color.prototype.names.
names: {
white: '#ffffff',
black: '#000000'
},
@@ -2155,11 +2155,15 @@
rgba,
i,
parser,
len;
- this.input = input = this.names[input] || input;
+ this.input = input = this.names[
+ input && input.toLowerCase ?
+ input.toLowerCase() :
+ ''
+ ] || input;
// Gradients
if (input && input.stops) {
this.stops = map(input.stops, function(stop) {
return new H.Color(stop[1]);
@@ -2286,11 +2290,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var SVGElement,
SVGRenderer,
@@ -2482,14 +2486,14 @@
id,
key = [],
value;
// Apply linear or radial gradients
- if (color.linearGradient) {
- gradName = 'linearGradient';
- } else if (color.radialGradient) {
+ if (color.radialGradient) {
gradName = 'radialGradient';
+ } else if (color.linearGradient) {
+ gradName = 'linearGradient';
}
if (gradName) {
gradAttr = color[gradName];
gradients = renderer.gradients;
@@ -2506,13 +2510,18 @@
gradientUnits: 'userSpaceOnUse'
};
}
// Correct the radial gradient for the radial reference system
- if (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) {
+ if (
+ gradName === 'radialGradient' &&
+ radialReference &&
+ !defined(gradAttr.gradientUnits)
+ ) {
radAttr = gradAttr; // Save the radial attributes for updating
- gradAttr = merge(gradAttr,
+ gradAttr = merge(
+ gradAttr,
renderer.getRadialAttr(radialReference, radAttr), {
gradientUnits: 'userSpaceOnUse'
}
);
}
@@ -2597,57 +2606,62 @@
* });
*/
applyTextOutline: function(textOutline) {
var elem = this.element,
tspans,
+ tspan,
hasContrast = textOutline.indexOf('contrast') !== -1,
styles = {},
color,
strokeWidth,
- firstRealChild;
+ firstRealChild,
+ i;
// When the text shadow is set to contrast, use dark stroke for light
// text and vice versa.
if (hasContrast) {
styles.textOutline = textOutline = textOutline.replace(
/contrast/g,
this.renderer.getContrast(elem.style.fill)
);
}
- this.fakeTS = true; // Fake text shadow
-
- // In order to get the right y position of the clone,
- // copy over the y setter
- this.ySetter = this.xSetter;
-
- tspans = [].slice.call(elem.getElementsByTagName('tspan'));
-
// Extract the stroke width and color
textOutline = textOutline.split(' ');
color = textOutline[textOutline.length - 1];
strokeWidth = textOutline[0];
- if (strokeWidth && strokeWidth !== 'none') {
+ if (strokeWidth && strokeWidth !== 'none' && H.svg) {
+ this.fakeTS = true; // Fake text shadow
+
+ tspans = [].slice.call(elem.getElementsByTagName('tspan'));
+
+ // In order to get the right y position of the clone,
+ // copy over the y setter
+ this.ySetter = this.xSetter;
+
// Since the stroke is applied on center of the actual outline, we
// need to double it to get the correct stroke-width outside the
// glyphs.
strokeWidth = strokeWidth.replace(
/(^[\d\.]+)(.*?)$/g,
function(match, digit, unit) {
return (2 * digit) + unit;
}
);
- // Remove shadows from previous runs
- each(tspans, function(tspan) {
+ // Remove shadows from previous runs. Iterate from the end to
+ // support removing items inside the cycle (#6472).
+ i = tspans.length;
+ while (i--) {
+ tspan = tspans[i];
if (tspan.getAttribute('class') === 'highcharts-text-outline') {
// Remove then erase
erase(tspans, elem.removeChild(tspan));
}
- });
+ }
// For each of the tspans, create a stroked copy behind it.
firstRealChild = elem.firstChild;
each(tspans, function(tspan, y) {
var clone;
@@ -2767,11 +2781,16 @@
// running animation of this property
if (!continueAnimation) {
stop(this, key);
}
- if (this.symbolName && /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(key)) {
+ // Special handling of symbol attributes
+ if (
+ this.symbolName &&
+ /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)$/
+ .test(key)
+ ) {
if (!hasSetSymbolSize) {
this.symbolAttr(hash);
hasSetSymbolSize = true;
}
skipAttr = true;
@@ -2984,12 +3003,12 @@
hyphenate,
hasNew = !oldStyles,
// These CSS properties are interpreted internally by the SVG
// renderer, but are not supported by SVG and should not be added to
// the DOM. In styled mode, no CSS should find its way to the DOM
- // whatsoever (#6173).
- svgPseudoProps = ['textOverflow', 'width'];
+ // whatsoever (#6173, #6474).
+ svgPseudoProps = ['textOutline', 'textOverflow', 'width'];
// convert legacy
if (styles && styles.color) {
styles.fill = styles.color;
}
@@ -3617,10 +3636,21 @@
// remove events
element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = element.point = null;
stop(wrapper); // stop running animations
if (wrapper.clipPath) {
+ // Look for existing references to this clipPath and remove them
+ // before destroying the element (#6196).
+ each(
+ wrapper.element.ownerSVGElement.querySelectorAll('[clip-path]'),
+ function(el) {
+ if (el.getAttribute('clip-path')
+ .indexOf(wrapper.clipPath.element.id) > -1) {
+ el.removeAttribute('clip-path');
+ }
+ }
+ );
wrapper.clipPath = wrapper.clipPath.destroy();
}
// Destroy stops in case this is a gradient object
if (wrapper.stops) {
@@ -4059,11 +4089,11 @@
.replace(/ /g, '%20') : // replace spaces (needed for Safari only)
'';
// Add description
desc = this.createElement('desc').add();
- desc.element.appendChild(doc.createTextNode('Created with Highcharts 5.0.9'));
+ desc.element.appendChild(doc.createTextNode('Created with Highcharts 5.0.10'));
renderer.defs = this.createElement('defs').add();
renderer.allowHTML = allowHTML;
renderer.forExport = forExport;
@@ -4206,10 +4236,62 @@
cy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2],
r: gradAttr.r * radialReference[2]
};
},
+ getSpanWidth: function(wrapper, tspan) {
+ var renderer = this,
+ bBox = wrapper.getBBox(true),
+ actualWidth = bBox.width;
+
+ // Old IE cannot measure the actualWidth for SVG elements (#2314)
+ if (!svg && renderer.forExport) {
+ actualWidth = renderer.measureSpanWidth(tspan.firstChild.data, wrapper.styles);
+ }
+ return actualWidth;
+ },
+
+ applyEllipsis: function(wrapper, tspan, text, width) {
+ var renderer = this,
+ actualWidth = renderer.getSpanWidth(wrapper, tspan),
+ wasTooLong = actualWidth > width,
+ str = text,
+ currentIndex,
+ minIndex = 0,
+ maxIndex = text.length,
+ updateTSpan = function(s) {
+ tspan.removeChild(tspan.firstChild);
+ if (s) {
+ tspan.appendChild(doc.createTextNode(s));
+ }
+ };
+ if (wasTooLong) {
+ while (minIndex <= maxIndex) {
+ currentIndex = Math.ceil((minIndex + maxIndex) / 2);
+ str = text.substring(0, currentIndex) + '\u2026';
+ updateTSpan(str);
+ actualWidth = renderer.getSpanWidth(wrapper, tspan);
+ if (minIndex === maxIndex) {
+ // Complete
+ minIndex = maxIndex + 1;
+ } else if (actualWidth > width) {
+ // Too large. Set max index to current.
+ maxIndex = currentIndex - 1;
+ } else {
+ // Within width. Set min index to current.
+ minIndex = currentIndex;
+ }
+ }
+ // If max index was 0 it means just ellipsis was also to large.
+ if (maxIndex === 0) {
+ // Remove ellipses.
+ updateTSpan('');
+ }
+ }
+ return wasTooLong;
+ },
+
/**
* Parse a simple HTML string into SVG tspans. Called internally when text
* is set on an SVGElement. The function supports a subset of HTML tags,
* CSS text features like `width`, `text-overflow`, `white-space`, and
* also attributes like `href` and `style`.
@@ -4235,10 +4317,11 @@
textOutline = textStyles && textStyles.textOutline,
ellipsis = textStyles && textStyles.textOverflow === 'ellipsis',
noWrap = textStyles && textStyles.whiteSpace === 'nowrap',
fontSize = textStyles && textStyles.fontSize,
textCache,
+ isSubsequentLine,
i = childNodes.length,
tempParent = width && !wrapper.added && this.box,
getLineHeight = function(tspan) {
var fontSizeStyle;
@@ -4369,11 +4452,11 @@
// Append it
textNode.appendChild(tspan);
// first span on subsequent line, add the line height
- if (!spanNo && lineNo) {
+ if (!spanNo && isSubsequentLine) {
// allow getting the right offset height in exporting in IE
if (!svg && forExport) {
css(tspan, {
display: 'block'
@@ -4396,48 +4479,32 @@
// Check width and apply soft breaks or ellipsis
if (width) {
var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
hasWhiteSpace = spans.length > 1 || lineNo || (words.length > 1 && !noWrap),
tooLong,
- actualWidth,
rest = [],
+ actualWidth,
dy = getLineHeight(tspan),
- rotation = wrapper.rotation,
- wordStr = span, // for ellipsis
- cursor = wordStr.length, // binary search cursor
- bBox;
+ rotation = wrapper.rotation;
- while ((hasWhiteSpace || ellipsis) && (words.length || rest.length)) {
- wrapper.rotation = 0; // discard rotation when computing box
- bBox = wrapper.getBBox(true);
- actualWidth = bBox.width;
+ if (ellipsis) {
+ wasTooLong = renderer.applyEllipsis(wrapper, tspan, span, width);
+ }
- // Old IE cannot measure the actualWidth for SVG elements (#2314)
- if (!svg && renderer.forExport) {
- actualWidth = renderer.measureSpanWidth(tspan.firstChild.data, wrapper.styles);
- }
-
+ while (!ellipsis && hasWhiteSpace && (words.length || rest.length)) {
+ wrapper.rotation = 0; // discard rotation when computing box
+ actualWidth = renderer.getSpanWidth(wrapper, tspan);
tooLong = actualWidth > width;
// For ellipsis, do a binary search for the correct string length
if (wasTooLong === undefined) {
wasTooLong = tooLong; // First time
}
- if (ellipsis && wasTooLong) {
- cursor /= 2;
- if (wordStr === '' || (!tooLong && cursor < 0.5)) {
- words = []; // All ok, break out
- } else {
- wordStr = span.substring(0, wordStr.length + (tooLong ? -1 : 1) * Math.ceil(cursor));
- words = [wordStr + (width > 3 ? '\u2026' : '')];
- tspan.removeChild(tspan.firstChild);
- }
-
- // Looping down, this is the first word sequence that is not too long,
- // so we can move on to build the next line.
- } else if (!tooLong || words.length === 1) {
+ // Looping down, this is the first word sequence that is not too long,
+ // so we can move on to build the next line.
+ if (!tooLong || words.length === 1) {
words = rest;
rest = [];
if (words.length && !noWrap) {
tspan = doc.createElementNS(SVG_NS, 'tspan');
@@ -4466,10 +4533,12 @@
spanNo++;
}
}
});
+ // To avoid beginning lines that doesn't add to the textNode (#6144)
+ isSubsequentLine = isSubsequentLine || textNode.childNodes.length;
});
if (wasTooLong) {
wrapper.attr('title', wrapper.textStr);
}
@@ -5805,11 +5874,11 @@
H.Renderer = SVGRenderer;
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var attr = H.attr,
createElement = H.createElement,
@@ -6167,11 +6236,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var VMLRenderer,
@@ -7318,11 +7387,11 @@
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var color = H.color,
each = H.each,
@@ -7364,11 +7433,11 @@
},
global: {
useUTC: true,
//timezoneOffset: 0,
- VMLRadialGradientURL: 'http://code.highcharts.com/5.0.9/gfx/vml-radial-gradient.png'
+ VMLRadialGradientURL: 'http://code.highcharts.com/5.0.10/gfx/vml-radial-gradient.png'
},
chart: {
//animation: true,
//alignTicks: false,
@@ -7706,11 +7775,11 @@
setTimeMethods();
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var arrayMax = H.arrayMax,
arrayMin = H.arrayMin,
@@ -7799,13 +7868,13 @@
// Grouping and zIndex
groupAttribs.zIndex = zIndex;
groupName += '-' + zIndex;
- group = axis[groupName];
+ group = axis.plotLinesAndBandsGroups[groupName];
if (!group) {
- axis[groupName] = group = renderer.g('plot-' + groupName)
+ axis.plotLinesAndBandsGroups[groupName] = group = renderer.g('plot-' + groupName)
.attr(groupAttribs).add();
}
// Create the path
if (isNew) {
@@ -7954,23 +8023,30 @@
/**
* Create the path for a plot band
*/
getPlotBandPath: function(from, to) {
var toPath = this.getPlotLinePath(to, null, null, true),
- path = this.getPlotLinePath(from, null, null, true);
+ path = this.getPlotLinePath(from, null, null, true),
+ // #4964 check if chart is inverted or plotband is on yAxis
+ horiz = this.horiz,
+ plus = 1,
+ outside =
+ (from < this.min && to < this.min) ||
+ (from > this.max && to > this.max);
if (path && toPath) {
// Flat paths don't need labels (#3836)
- path.flat = path.toString() === toPath.toString();
+ if (outside) {
+ path.flat = path.toString() === toPath.toString();
+ plus = 0;
+ }
+ // Add 1 pixel, when coordinates are the same
path.push(
- toPath[4],
- toPath[5],
- toPath[1],
- toPath[2],
- 'z' // #5909
+ horiz && toPath[4] === path[4] ? toPath[4] + plus : toPath[4], !horiz && toPath[5] === path[5] ? toPath[5] + plus : toPath[5],
+ horiz && toPath[1] === path[1] ? toPath[1] + plus : toPath[1], !horiz && toPath[2] === path[2] ? toPath[2] + plus : toPath[2]
);
} else { // outside the axis area
path = null;
}
@@ -8032,11 +8108,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var correctFloat = H.correctFloat,
defined = H.defined,
@@ -8542,11 +8618,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
@@ -8842,10 +8918,13 @@
//axis.axisGroup = undefined;
//axis.gridGroup = undefined;
//axis.axisTitle = undefined;
//axis.axisLine = undefined;
+ // Placeholder for plotlines and plotbands groups
+ axis.plotLinesAndBandsGroups = {};
+
// Shorthand types
axis.isLog = type === 'logarithmic';
axis.isDatetimeAxis = isDatetimeAxis;
axis.positiveValuesOnly = axis.isLog && !axis.allowNegativeLog;
@@ -9463,11 +9542,13 @@
} else {
x = nameX;
}
// Write the last point's name to the names array
- this.names[x] = point.name;
+ if (x !== undefined) {
+ this.names[x] = point.name;
+ }
return x;
},
/**
@@ -9492,11 +9573,11 @@
each(series.points, function(point, i) {
var x;
if (point.options) {
x = axis.nameToX(point);
- if (x !== point.x) {
+ if (x !== undefined && x !== point.x) {
point.x = x;
series.xData[i] = x;
}
}
});
@@ -9701,22 +9782,25 @@
axis.max += length * maxPadding;
}
}
}
- // Handle options for floor, ceiling, softMin and softMax
+ // Handle options for floor, ceiling, softMin and softMax (#6359)
+ if (isNumber(options.softMin)) {
+ axis.min = Math.min(axis.min, options.softMin);
+ }
+ if (isNumber(options.softMax)) {
+ axis.max = Math.max(axis.max, options.softMax);
+ }
if (isNumber(options.floor)) {
axis.min = Math.max(axis.min, options.floor);
- } else if (isNumber(options.softMin)) {
- axis.min = Math.min(axis.min, options.softMin);
}
if (isNumber(options.ceiling)) {
axis.max = Math.min(axis.max, options.ceiling);
- } else if (isNumber(options.softMax)) {
- axis.max = Math.max(axis.max, options.softMax);
}
+
// When the threshold is soft, adjust the extreme value only if
// the data extreme and the padded extreme land on either side of the threshold. For example,
// a series of [0, 1, 2, 3] would make the yAxis add a tick for -1 because of the
// default minPadding and startOnTick options. This is prevented by the softThreshold
// option.
@@ -9887,11 +9971,11 @@
var roundedMin = tickPositions[0],
roundedMax = tickPositions[tickPositions.length - 1],
minPointOffset = this.minPointOffset || 0;
if (!this.isLinked) {
- if (startOnTick) {
+ if (startOnTick && roundedMin !== -Infinity) { // #6502
this.min = roundedMin;
} else {
while (this.min - minPointOffset > tickPositions[0]) {
tickPositions.shift();
}
@@ -11051,10 +11135,11 @@
destroy: function(keepEvents) {
var axis = this,
stacks = axis.stacks,
stackKey,
plotLinesAndBands = axis.plotLinesAndBands,
+ plotGroup,
i,
n;
// Remove the events
if (!keepEvents) {
@@ -11084,10 +11169,15 @@
if (axis[prop]) {
axis[prop] = axis[prop].destroy();
}
});
+ // Destroy each generated group for plotlines and plotbands
+ for (plotGroup in axis.plotLinesAndBandsGroups) {
+ axis.plotLinesAndBandsGroups[plotGroup] = axis.plotLinesAndBandsGroups[plotGroup].destroy();
+ }
+
// Delete all properties and fall back to the prototype.
for (n in axis) {
if (axis.hasOwnProperty(n) && inArray(n, axis.keepProps) === -1) {
delete axis[n];
}
@@ -11201,11 +11291,11 @@
extend(H.Axis.prototype, AxisPlotLineOrBandExtension);
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Axis = H.Axis,
Date = H.Date,
@@ -11461,11 +11551,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Axis = H.Axis,
getMagnitude = H.getMagnitude,
@@ -11584,11 +11674,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var dateFormat = H.dateFormat,
each = H.each,
@@ -12336,11 +12426,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
attr = H.attr,
@@ -12495,12 +12585,15 @@
// Find nearest points on all series
each(series, function(s) {
// Skip hidden series
noSharedTooltip = s.noSharedTooltip && shared;
directTouch = !shared && s.directTouch;
- if (s.visible && !noSharedTooltip && !directTouch && pick(s.options.enableMouseTracking, true)) { // #3821
- kdpointT = s.searchPoint(e, !noSharedTooltip && s.kdDimensions === 1); // #3828
+ if (s.visible && !directTouch && pick(s.options.enableMouseTracking, true)) { // #3821
+ // #3828
+ kdpointT = s.searchPoint(
+ e, !noSharedTooltip && s.options.findNearestPointBy.indexOf('y') < 0
+ );
if (kdpointT && kdpointT.series) { // Point.series becomes null when reset and before redraw (#5197)
kdpoints.push(kdpointT);
}
}
});
@@ -12529,11 +12622,11 @@
}
return result;
});
// Remove points with different x-positions, required for shared tooltip and crosshairs (#4645):
- if (shared) {
+ if (shared && kdpoints[0] && !kdpoints[0].series.noSharedTooltip) {
i = kdpoints.length;
while (i--) {
if (kdpoints[i].x !== kdpoints[0].x || kdpoints[i].series.noSharedTooltip) {
kdpoints.splice(i, 1);
}
@@ -12551,13 +12644,13 @@
}
return point;
},
getHoverData: function(existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) {
- var i,
- hoverPoint = existingHoverPoint,
+ var hoverPoint = existingHoverPoint,
hoverSeries = existingHoverSeries,
+ searchSeries,
hoverPoints;
// If it has a hoverPoint and that series requires direct touch (like columns, #3899), or we're on
// a noSharedTooltip series among shared tooltip series (#4546), use the hoverPoint . Otherwise,
// search the k-d tree.
@@ -12585,33 +12678,32 @@
hoverPoints = [hoverPoint];
}
} else {
hoverPoints = [hoverPoint];
}
- } else if (hoverSeries && !hoverSeries.options.stickyTracking) {
- hoverPoints = this.getKDPoints([hoverSeries], shared, e);
- hoverPoint = hoverPoints[0];
- hoverSeries = hoverPoint && hoverPoint.series;
- } else {
+ // When the hovered series has stickyTracking false.
+ } else if (hoverSeries && !hoverSeries.stickyTracking) {
if (!shared) {
- // For hovering over the empty parts of the plot area (hoverSeries is undefined).
- // If there is one series with point tracking (combo chart), don't go to nearest neighbour.
- if (!hoverSeries) {
- for (i = 0; i < series.length; i++) {
- if (series[i].directTouch || !series[i].options.stickyTracking) {
- series = [];
- }
- }
- // When we have non-shared tooltip and sticky tracking is disabled,
- // search for the closest point only on hovered series: #5533, #5476
- } else if (!hoverSeries.options.stickyTracking) {
- series = [hoverSeries];
- }
+ series = [hoverSeries];
}
hoverPoints = this.getKDPoints(series, shared, e);
+ hoverPoint = H.find(hoverPoints, function(p) {
+ return p.series === hoverSeries;
+ });
+ // When the hoverSeries has stickyTracking or there is no series hovered.
+ } else {
+ // Avoid series with stickyTracking
+ searchSeries = H.grep(series, function(s) {
+ return s.stickyTracking;
+ });
+ hoverPoints = this.getKDPoints(searchSeries, shared, e);
hoverPoint = hoverPoints[0];
hoverSeries = hoverPoint && hoverPoint.series;
+ // If
+ if (shared) {
+ hoverPoints = this.getKDPoints(series, shared, e);
+ }
}
// Keep the order of series in tooltip
// Must be done after assigning of hoverPoint
hoverPoints.sort(function(p1, p2) {
return p1.series.index - p2.series.index;
@@ -12634,11 +12726,11 @@
tooltip = chart.tooltip,
shared = tooltip ? tooltip.shared : false,
hoverPoint = p || chart.hoverPoint,
hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries,
// onMouseOver or already hovering a series with directTouch
- isDirectTouch = !!p || (hoverSeries && hoverSeries.directTouch),
+ isDirectTouch = !!p || (!shared && hoverSeries && hoverSeries.directTouch),
hoverData = this.getHoverData(hoverPoint, hoverSeries, series, isDirectTouch, shared, e),
useSharedTooltip,
followPointer,
anchor,
points;
@@ -12646,11 +12738,14 @@
// Update variables from hoverData.
hoverPoint = hoverData.hoverPoint;
hoverSeries = hoverData.hoverSeries;
followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer;
useSharedTooltip = shared && hoverPoint && !hoverPoint.series.noSharedTooltip;
- points = useSharedTooltip ? hoverData.hoverPoints : [hoverPoint];
+ points = (useSharedTooltip ?
+ hoverData.hoverPoints :
+ (hoverPoint ? [hoverPoint] : [])
+ );
// Refresh tooltip for kdpoint if new hover point or tooltip was hidden // #3926, #4200
if (
hoverPoint &&
// !(hoverSeries && hoverSeries.directTouch) &&
@@ -12701,19 +12796,24 @@
chart.pointer.onDocumentMouseMove(e);
}
});
}
- // Crosshair. For each hover point, loop over axes and draw cross if that point
- // belongs to the axis (#4927).
- each(points, function drawPointCrosshair(point) { // #5269
- each(chart.axes, function drawAxisCrosshair(axis) {
- // In case of snap = false, point is undefined, and we draw the crosshair anyway (#5066)
- if (!point || point.series && point.series[axis.coll] === axis) { // #5658
- axis.drawCrosshair(e, point);
- }
- });
+ // Draw crosshairs (#4927, #5269 #5066, #5658)
+ each(chart.axes, function drawAxisCrosshair(axis) {
+ // Snap is true. For each hover point, loop over the axes and draw a
+ // crosshair if that point belongs to the axis.
+ // @todo Consider only one crosshair per axis.
+ if (pick(axis.crosshair.snap, true)) {
+ each(points, function(p) {
+ if (p.series[axis.coll] === axis) {
+ axis.drawCrosshair(e, p);
+ }
+ });
+ } else {
+ axis.drawCrosshair(e);
+ }
});
},
/**
* Reset the tracking by hiding the tooltip, the hover series state and the hover point
@@ -13089,11 +13189,11 @@
onTrackerMouseOut: function(e) {
var series = this.chart.hoverSeries,
relatedTarget = e.relatedTarget || e.toElement;
- if (series && relatedTarget && !series.options.stickyTracking &&
+ if (series && relatedTarget && !series.stickyTracking &&
!this.inClass(relatedTarget, 'highcharts-tooltip') &&
(!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465
!this.inClass(relatedTarget, 'highcharts-tracker') // #5553
)
) {
@@ -13179,11 +13279,19 @@
* Destroys the Pointer object and disconnects DOM events.
*/
destroy: function() {
var prop;
- removeEvent(this.chart.container, 'mouseleave', this.onContainerMouseLeave);
+ if (this.unDocMouseMove) {
+ this.unDocMouseMove();
+ }
+
+ removeEvent(
+ this.chart.container,
+ 'mouseleave',
+ this.onContainerMouseLeave
+ );
if (!H.chartCount) {
removeEvent(doc, 'mouseup', this.onDocumentMouseUp);
removeEvent(doc, 'touchend', this.onDocumentTouchEnd);
}
@@ -13197,11 +13305,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var charts = H.charts,
each = H.each,
@@ -13474,11 +13582,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
charts = H.charts,
@@ -13593,11 +13701,11 @@
}
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Legend,
@@ -13655,22 +13763,21 @@
this.itemStyle = options.itemStyle;
this.itemHiddenStyle = merge(this.itemStyle, options.itemHiddenStyle);
this.itemMarginTop = options.itemMarginTop || 0;
this.padding = padding;
- this.initialItemX = padding;
- this.initialItemY = padding - 5; // 5 is the number of pixels above the text
+ this.initialItemY = padding - 5; // 5 is pixels above the text
this.maxItemWidth = 0;
this.itemHeight = 0;
this.symbolWidth = pick(options.symbolWidth, 16);
this.pages = [];
},
/**
- * Update the legend with new options. Equivalent to running chart.update with a legend
- * configuration option.
+ * Update the legend with new options. Equivalent to running chart.update
+ * with a legend configuration option.
* @param {Object} options Legend options
* @param {Boolean} redraw Whether to redraw the chart, defaults to true.
*/
update: function(options, redraw) {
var chart = this.chart;
@@ -13687,11 +13794,13 @@
* Set the colors for the legend item
* @param {Object} item A Series or Point instance
* @param {Object} visible Dimmed or colored
*/
colorizeItem: function(item, visible) {
- item.legendGroup[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden');
+ item.legendGroup[visible ? 'removeClass' : 'addClass'](
+ 'highcharts-legend-item-hidden'
+ );
var legend = this,
options = legend.options,
legendItem = item.legendItem,
@@ -13707,12 +13816,12 @@
key;
if (legendItem) {
legendItem.css({
fill: textColor,
- color: textColor
- }); // color for #1553, oldIE
+ color: textColor // #1553, oldIE
+ });
}
if (legendLine) {
legendLine.attr({
stroke: symbolColor
});
@@ -13751,11 +13860,13 @@
checkbox = item.checkbox,
legendGroup = item.legendGroup;
if (legendGroup && legendGroup.element) {
legendGroup.translate(
- ltr ? itemX : legend.legendWidth - itemX - 2 * symbolPadding - 4,
+ ltr ?
+ itemX :
+ legend.legendWidth - itemX - 2 * symbolPadding - 4,
itemY
);
}
if (checkbox) {
@@ -13770,15 +13881,18 @@
*/
destroyItem: function(item) {
var checkbox = item.checkbox;
// destroy SVG elements
- each(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function(key) {
- if (item[key]) {
- item[key] = item[key].destroy();
+ each(
+ ['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'],
+ function(key) {
+ if (item[key]) {
+ item[key] = item[key].destroy();
+ }
}
- });
+ );
if (checkbox) {
discardElement(item.checkbox);
}
},
@@ -13826,15 +13940,18 @@
each(this.allItems, function(item) {
var checkbox = item.checkbox,
top;
if (checkbox) {
- top = translateY + titleHeight + checkbox.y + (scrollOffset || 0) + 3;
+ top = translateY + titleHeight + checkbox.y +
+ (scrollOffset || 0) + 3;
css(checkbox, {
- left: (alignAttr.translateX + item.checkboxOffset + checkbox.x - 20) + 'px',
+ left: (alignAttr.translateX + item.checkboxOffset +
+ checkbox.x - 20) + 'px',
top: top + 'px',
- display: top > translateY - 6 && top < translateY + clipHeight - 6 ? '' : 'none'
+ display: top > translateY - 6 && top < translateY +
+ clipHeight - 6 ? '' : 'none'
});
}
});
}
},
@@ -13849,11 +13966,21 @@
titleHeight = 0,
bBox;
if (titleOptions.text) {
if (!this.title) {
- this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, null, null, 'legend-title')
+ this.title = this.chart.renderer.label(
+ titleOptions.text,
+ padding - 3,
+ padding - 4,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 'legend-title'
+ )
.attr({
zIndex: 1
})
.css(titleOptions.style)
@@ -13874,11 +14001,12 @@
* Set the legend item text
*/
setText: function(item) {
var options = this.options;
item.legendItem.attr({
- text: options.labelFormat ? H.format(options.labelFormat, item) : options.labelFormatter.call(item)
+ text: options.labelFormat ?
+ H.format(options.labelFormat, item) : options.labelFormatter.call(item)
});
},
/**
* Render a single specific legend item
@@ -13901,28 +14029,34 @@
ltr = !options.rtl,
itemHeight,
widthOption = options.width,
itemMarginBottom = options.itemMarginBottom || 0,
itemMarginTop = legend.itemMarginTop,
- initialItemX = legend.initialItemX,
bBox,
itemWidth,
li = item.legendItem,
isSeries = !item.series,
- series = !isSeries && item.series.drawLegendSymbol ? item.series : item,
+ series = !isSeries && item.series.drawLegendSymbol ?
+ item.series :
+ item,
seriesOptions = series.options,
- showCheckbox = legend.createCheckboxForItem && seriesOptions && seriesOptions.showCheckbox,
+ showCheckbox = legend.createCheckboxForItem &&
+ seriesOptions &&
+ seriesOptions.showCheckbox,
useHTML = options.useHTML,
- fontSize = 12;
+ fontSize = 12,
+ itemClassName = item.options.className;
if (!li) { // generate it once, later move it
- // Generate the group box
- // A group to hold the symbol and text. Text is to be appended in Legend class.
+ // Generate the group box, a group to hold the symbol and text. Text
+ // is to be appended in Legend class.
item.legendGroup = renderer.g('legend-item')
- .addClass('highcharts-' + series.type + '-series highcharts-color-' + item.colorIndex +
- (item.options.className ? ' ' + item.options.className : '') +
+ .addClass(
+ 'highcharts-' + series.type + '-series ' +
+ 'highcharts-color-' + item.colorIndex +
+ (itemClassName ? ' ' + itemClassName : '') +
(isSeries ? ' highcharts-series-' + item.index : '')
)
.attr({
zIndex: 1
})
@@ -13934,19 +14068,21 @@
ltr ? symbolWidth + symbolPadding : -symbolPadding,
legend.baseline || 0,
useHTML
)
- .css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)
+ // merge to prevent modifying original (#1021)
+ .css(merge(item.visible ? itemStyle : itemHiddenStyle))
.attr({
align: ltr ? 'left' : 'right',
zIndex: 2
})
.add(item.legendGroup);
- // Get the baseline for the first item - the font size is equal for all
+ // Get the baseline for the first item - the font size is equal for
+ // all
if (!legend.baseline) {
fontSize = itemStyle.fontSize;
legend.fontMetrics = renderer.fontMetrics(
@@ -13981,32 +14117,46 @@
bBox = li.getBBox();
itemWidth = item.checkboxOffset =
options.itemWidth ||
item.legendItemWidth ||
- symbolWidth + symbolPadding + bBox.width + itemDistance + (showCheckbox ? 20 : 0);
- legend.itemHeight = itemHeight = Math.round(item.legendItemHeight || bBox.height);
+ symbolWidth + symbolPadding + bBox.width + itemDistance +
+ (showCheckbox ? 20 : 0);
+ legend.itemHeight = itemHeight = Math.round(
+ item.legendItemHeight || bBox.height || legend.symbolHeight
+ );
- // if the item exceeds the width, start a new line
- if (horizontal && legend.itemX - initialItemX + itemWidth >
- (widthOption || (chart.chartWidth - 2 * padding - initialItemX - options.x))) {
- legend.itemX = initialItemX;
- legend.itemY += itemMarginTop + legend.lastLineHeight + itemMarginBottom;
+ // If the item exceeds the width, start a new line
+ if (
+ horizontal &&
+ legend.itemX - padding + itemWidth > (
+ widthOption || (
+ chart.spacingBox.width - 2 * padding - options.x
+ )
+ )
+ ) {
+ legend.itemX = padding;
+ legend.itemY += itemMarginTop + legend.lastLineHeight +
+ itemMarginBottom;
legend.lastLineHeight = 0; // reset for next line (#915, #3976)
}
// If the item exceeds the height, start a new column
- /*if (!horizontal && legend.itemY + options.y + itemHeight > chart.chartHeight - spacingTop - spacingBottom) {
+ /*if (!horizontal && legend.itemY + options.y +
+ itemHeight > chart.chartHeight - spacingTop - spacingBottom) {
legend.itemY = legend.initialItemY;
legend.itemX += legend.maxItemWidth;
legend.maxItemWidth = 0;
}*/
// Set the edge positions
legend.maxItemWidth = Math.max(legend.maxItemWidth, itemWidth);
legend.lastItemY = itemMarginTop + legend.itemY + itemMarginBottom;
- legend.lastLineHeight = Math.max(itemHeight, legend.lastLineHeight); // #915
+ legend.lastLineHeight = Math.max( // #915
+ itemHeight,
+ legend.lastLineHeight
+ );
// cache the position of the newly generated or reordered items
item._legendItemPos = [legend.itemX, legend.itemY];
// advance
@@ -14018,65 +14168,82 @@
legend.lastLineHeight = itemHeight;
}
// the width of the widest item
legend.offsetWidth = widthOption || Math.max(
- (horizontal ? legend.itemX - initialItemX - itemDistance : itemWidth) + padding,
+ (horizontal ? legend.itemX - padding - itemDistance : itemWidth) +
+ padding,
legend.offsetWidth
);
},
/**
- * Get all items, which is one item per series for normal series and one item per point
- * for pie series.
+ * Get all items, which is one item per series for normal series and one
+ * item per point for pie series.
*/
getAllItems: function() {
var allItems = [];
each(this.chart.series, function(series) {
var seriesOptions = series && series.options;
- // Handle showInLegend. If the series is linked to another series, defaults to false.
- if (series && pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? undefined : false, true)) {
+ // Handle showInLegend. If the series is linked to another series,
+ // defaults to false.
+ if (series && pick(
+ seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? undefined : false, true
+ )) {
- // Use points or series for the legend item depending on legendType
+ // Use points or series for the legend item depending on
+ // legendType
allItems = allItems.concat(
series.legendItems ||
- (seriesOptions.legendType === 'point' ?
+ (
+ seriesOptions.legendType === 'point' ?
series.data :
- series)
+ series
+ )
);
}
});
return allItems;
},
/**
- * Adjust the chart margins by reserving space for the legend on only one side
- * of the chart. If the position is set to a corner, top or bottom is reserved
- * for horizontal legends and left or right for vertical ones.
+ * Adjust the chart margins by reserving space for the legend on only one
+ * side of the chart. If the position is set to a corner, top or bottom is
+ * reserved for horizontal legends and left or right for vertical ones.
*/
adjustMargins: function(margin, spacing) {
var chart = this.chart,
options = this.options,
- // Use the first letter of each alignment option in order to detect the side
- alignment = options.align.charAt(0) + options.verticalAlign.charAt(0) + options.layout.charAt(0); // #4189 - use charAt(x) notation instead of [x] for IE7
+ // Use the first letter of each alignment option in order to detect
+ // the side. (#4189 - use charAt(x) notation instead of [x] for IE7)
+ alignment = options.align.charAt(0) +
+ options.verticalAlign.charAt(0) +
+ options.layout.charAt(0);
if (!options.floating) {
each([
/(lth|ct|rth)/,
/(rtv|rm|rbv)/,
/(rbh|cb|lbh)/,
/(lbv|lm|ltv)/
], function(alignments, side) {
if (alignments.test(alignment) && !defined(margin[side])) {
- // Now we have detected on which side of the chart we should reserve space for the legend
+ // Now we have detected on which side of the chart we should
+ // reserve space for the legend
chart[marginNames[side]] = Math.max(
chart[marginNames[side]],
- chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] + [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] +
- pick(options.margin, 12) +
- spacing[side]
+ (
+ chart.legend[
+ (side + 1) % 2 ? 'legendHeight' : 'legendWidth'
+ ] + [1, -1, -1, 1][side] * options[
+ (side % 2) ? 'x' : 'y'
+ ] +
+ pick(options.margin, 12) +
+ spacing[side]
+ )
);
}
});
}
},
@@ -14097,11 +14264,11 @@
legendHeight,
box = legend.box,
options = legend.options,
padding = legend.padding;
- legend.itemX = legend.initialItemX;
+ legend.itemX = padding;
legend.itemY = legend.initialItemY;
legend.offsetWidth = 0;
legend.lastItemY = 0;
if (!legendGroup) {
@@ -14124,11 +14291,12 @@
// add each series or point
allItems = legend.getAllItems();
// sort by legendIndex
stableSort(allItems, function(a, b) {
- return ((a.options && a.options.legendIndex) || 0) - ((b.options && b.options.legendIndex) || 0);
+ return ((a.options && a.options.legendIndex) || 0) -
+ ((b.options && b.options.legendIndex) || 0);
});
// reversed legend
if (options.reversed) {
allItems.reverse();
@@ -14143,11 +14311,12 @@
legend.renderItem(item);
});
// Get the box
legendWidth = (options.width || legend.offsetWidth) + padding;
- legendHeight = legend.lastItemY + legend.lastLineHeight + legend.titleHeight;
+ legendHeight = legend.lastItemY + legend.lastLineHeight +
+ legend.titleHeight;
legendHeight = legend.handleOverflow(legendHeight);
legendHeight += padding;
// Draw the border and/or background
if (!box) {
@@ -14189,12 +14358,12 @@
legend.legendWidth = legendWidth;
legend.legendHeight = legendHeight;
- // Now that the legend width and height are established, put the items in the
- // final position
+ // Now that the legend width and height are established, put the items
+ // in the final position
each(allItems, function(item) {
legend.positionItem(item);
});
// 1.x compatibility: positioning based on style
@@ -14203,11 +14372,12 @@
i = 4;
while (i--) {
prop = props[i];
if (options.style[prop] && options.style[prop] !== 'auto') {
options[i < 2 ? 'align' : 'verticalAlign'] = prop;
- options[i < 2 ? 'x' : 'y'] = pInt(options.style[prop]) * (i % 2 ? -1 : 1);
+ options[i < 2 ? 'x' : 'y'] =
+ pInt(options.style[prop]) * (i % 2 ? -1 : 1);
}
}*/
if (display) {
legendGroup.align(merge(options, {
@@ -14220,30 +14390,31 @@
this.positionCheckboxes();
}
},
/**
- * Set up the overflow handling by adding navigation with up and down arrows below the
- * legend.
+ * Set up the overflow handling by adding navigation with up and down arrows
+ * below the legend.
*/
handleOverflow: function(legendHeight) {
var legend = this,
chart = this.chart,
renderer = chart.renderer,
options = this.options,
optionsY = options.y,
alignTop = options.verticalAlign === 'top',
- spaceHeight = chart.spacingBox.height + (alignTop ? -optionsY : optionsY) - this.padding,
+ padding = this.padding,
+ spaceHeight = chart.spacingBox.height +
+ (alignTop ? -optionsY : optionsY) - padding,
maxHeight = options.maxHeight,
clipHeight,
clipRect = this.clipRect,
navOptions = options.navigation,
animation = pick(navOptions.animation, true),
arrowSize = navOptions.arrowSize || 12,
nav = this.nav,
pages = this.pages,
- padding = this.padding,
lastY,
allItems = this.allItems,
clipToHeight = function(height) {
if (height) {
clipRect.attr({
@@ -14263,70 +14434,98 @@
}
};
// Adjust the height
- if (options.layout === 'horizontal' && options.verticalAlign !== 'middle' && !options.floating) {
+ if (
+ options.layout === 'horizontal' &&
+ options.verticalAlign !== 'middle' &&
+ !options.floating
+ ) {
spaceHeight /= 2;
}
if (maxHeight) {
spaceHeight = Math.min(spaceHeight, maxHeight);
}
// Reset the legend height and adjust the clipping rectangle
pages.length = 0;
if (legendHeight > spaceHeight && navOptions.enabled !== false) {
- this.clipHeight = clipHeight = Math.max(spaceHeight - 20 - this.titleHeight - padding, 0);
+ this.clipHeight = clipHeight =
+ Math.max(spaceHeight - 20 - this.titleHeight - padding, 0);
this.currentPage = pick(this.currentPage, 1);
this.fullHeight = legendHeight;
- // Fill pages with Y positions so that the top of each a legend item defines
- // the scroll top for each page (#2098)
+ // Fill pages with Y positions so that the top of each a legend item
+ // defines the scroll top for each page (#2098)
each(allItems, function(item, i) {
var y = item._legendItemPos[1],
h = Math.round(item.legendItem.getBBox().height),
len = pages.length;
- if (!len || (y - pages[len - 1] > clipHeight && (lastY || y) !== pages[len - 1])) {
+ if (!len || (y - pages[len - 1] > clipHeight &&
+ (lastY || y) !== pages[len - 1])) {
pages.push(lastY || y);
len++;
}
- if (i === allItems.length - 1 && y + h - pages[len - 1] > clipHeight) {
+ if (i === allItems.length - 1 &&
+ y + h - pages[len - 1] > clipHeight) {
pages.push(y);
}
if (y !== lastY) {
lastY = y;
}
});
- // Only apply clipping if needed. Clipping causes blurred legend in PDF export (#1787)
+ // Only apply clipping if needed. Clipping causes blurred legend in
+ // PDF export (#1787)
if (!clipRect) {
- clipRect = legend.clipRect = renderer.clipRect(0, padding, 9999, 0);
+ clipRect = legend.clipRect =
+ renderer.clipRect(0, padding, 9999, 0);
legend.contentGroup.clip(clipRect);
}
clipToHeight(clipHeight);
// Add navigation elements
if (!nav) {
- this.nav = nav = renderer.g().attr({
- zIndex: 1
- }).add(this.group);
- this.up = renderer.symbol('triangle', 0, 0, arrowSize, arrowSize)
+ this.nav = nav = renderer.g()
+ .attr({
+ zIndex: 1
+ })
+ .add(this.group);
+
+ this.up = renderer
+ .symbol(
+ 'triangle',
+ 0,
+ 0,
+ arrowSize,
+ arrowSize
+ )
.on('click', function() {
legend.scroll(-1, animation);
})
.add(nav);
+
this.pager = renderer.text('', 15, 10)
.addClass('highcharts-legend-navigation')
.css(navOptions.style)
.add(nav);
- this.down = renderer.symbol('triangle-down', 0, 0, arrowSize, arrowSize)
+
+ this.down = renderer
+ .symbol(
+ 'triangle-down',
+ 0,
+ 0,
+ arrowSize,
+ arrowSize
+ )
.on('click', function() {
legend.scroll(1, animation);
})
.add(nav);
}
@@ -14379,31 +14578,35 @@
translateX: padding,
translateY: clipHeight + this.padding + 7 + this.titleHeight,
visibility: 'visible'
});
this.up.attr({
- 'class': currentPage === 1 ? 'highcharts-legend-nav-inactive' : 'highcharts-legend-nav-active'
+ 'class': currentPage === 1 ?
+ 'highcharts-legend-nav-inactive' : 'highcharts-legend-nav-active'
});
pager.attr({
text: currentPage + '/' + pageCount
});
this.down.attr({
'x': 18 + this.pager.getBBox().width, // adjust to text width
- 'class': currentPage === pageCount ? 'highcharts-legend-nav-inactive' : 'highcharts-legend-nav-active'
+ 'class': currentPage === pageCount ?
+ 'highcharts-legend-nav-inactive' : 'highcharts-legend-nav-active'
});
this.up
.attr({
- fill: currentPage === 1 ? navOptions.inactiveColor : navOptions.activeColor
+ fill: currentPage === 1 ?
+ navOptions.inactiveColor : navOptions.activeColor
})
.css({
cursor: currentPage === 1 ? 'default' : 'pointer'
});
this.down
.attr({
- fill: currentPage === pageCount ? navOptions.inactiveColor : navOptions.activeColor
+ fill: currentPage === pageCount ?
+ navOptions.inactiveColor : navOptions.activeColor
})
.css({
cursor: currentPage === pageCount ? 'default' : 'pointer'
});
@@ -14453,12 +14656,13 @@
}).add(item.legendGroup);
},
/**
- * Get the series' symbol in the legend. This method should be overridable to create custom
- * symbols through Highcharts.seriesTypes[type].prototype.drawLegendSymbols.
+ * Get the series' symbol in the legend. This method should be overridable
+ * to create custom symbols through
+ * Highcharts.seriesTypes[type].prototype.drawLegendSymbols.
*
* @param {Object} legend The legend object
*/
drawLineMarker: function(legend) {
@@ -14469,11 +14673,12 @@
symbolWidth = legend.symbolWidth,
symbolHeight = legend.symbolHeight,
generalRadius = symbolHeight / 2,
renderer = this.chart.renderer,
legendItemGroup = this.legendGroup,
- verticalCenter = legend.baseline - Math.round(legend.fontMetrics.b * 0.3),
+ verticalCenter = legend.baseline -
+ Math.round(legend.fontMetrics.b * 0.3),
attr = {};
// Draw the line
attr = {
@@ -14530,15 +14735,17 @@
};
// Workaround for #2030, horizontal legend items not displaying in IE11 Preview,
// and for #2580, a similar drawing flaw in Firefox 26.
// Explore if there's a general cause for this. The problem may be related
- // to nested group elements, as the legend item texts are within 4 group elements.
+ // to nested group elements, as the legend item texts are within 4 group
+ // elements.
if (/Trident\/7\.0/.test(win.navigator.userAgent) || isFirefox) {
wrap(Legend.prototype, 'positionItem', function(proceed, item) {
var legend = this,
- runPositionItem = function() { // If chart destroyed in sync, this is undefined (#2030)
+ // If chart destroyed in sync, this is undefined (#2030)
+ runPositionItem = function() {
if (item._legendItemPos) {
proceed.call(legend, item);
}
};
@@ -14551,11 +14758,11 @@
}
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
animate = H.animate,
@@ -15102,11 +15309,12 @@
});
chart.layOutTitles(redraw);
},
/**
- * Lay out the chart titles and cache the full offset height for use in getMargins
+ * Lay out the chart titles and cache the full offset height for use
+ * in getMargins
*/
layOutTitles: function(redraw) {
var titleOffset = 0,
requiresDirtyBox,
renderer = this.renderer,
@@ -15124,18 +15332,23 @@
titleSize = renderer.fontMetrics(titleSize, title).b;
title
.css({
- width: (titleOptions.width || spacingBox.width + titleOptions.widthAdjust) + 'px'
+ width: (titleOptions.width ||
+ spacingBox.width + titleOptions.widthAdjust) + 'px'
})
.align(extend({
y: titleOffset + titleSize + (key === 'title' ? -3 : 2)
}, titleOptions), false, 'spacingBox');
if (!titleOptions.floating && !titleOptions.verticalAlign) {
- titleOffset = Math.ceil(titleOffset + title.getBBox().height);
+ titleOffset = Math.ceil(
+ titleOffset +
+ // Skip the cache for HTML (#3481)
+ title.getBBox(titleOptions.useHTML).height
+ );
}
}
}, this);
requiresDirtyBox = this.titleOffset !== titleOffset;
@@ -16154,11 +16367,11 @@
}; // end Chart
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Point,
@@ -16504,11 +16717,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
animObject = H.animObject,
@@ -16667,14 +16880,14 @@
//valueDecimals: null,
//xDateFormat: '%A, %b %e, %Y',
//valuePrefix: '',
//ySuffix: ''
//}
- turboThreshold: 1000
+ turboThreshold: 1000,
// zIndex: null
+ findNearestPointBy: 'x'
-
}, /** @lends Series.prototype */ {
isCartesian: true,
pointClass: Point,
sorted: true, // requires the data to be sorted
requireSorting: true,
@@ -16913,10 +17126,23 @@
userPlotOptions.series && userPlotOptions.series.tooltip,
userPlotOptions[this.type] && userPlotOptions[this.type].tooltip,
itemOptions.tooltip
);
+ // When shared tooltip, stickyTracking is true by default,
+ // unless user says otherwise.
+ this.stickyTracking = pick(
+ itemOptions.stickyTracking,
+ userPlotOptions[this.type] && userPlotOptions[this.type].stickyTracking,
+ userPlotOptions.series && userPlotOptions.series.stickyTracking,
+ (
+ this.tooltipOptions.shared && !this.noSharedTooltip ?
+ true :
+ options.stickyTracking
+ )
+ );
+
// Delete marker object if not allowed (#1125)
if (typeOptions.marker === null) {
delete options.marker;
}
@@ -17298,12 +17524,14 @@
} else {
// splat the y data in case of ohlc data array
point = (new PointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i])));
point.dataGroup = series.groupMap[i];
}
- point.index = cursor; // For faster access in Point.update
- points[i] = point;
+ if (point) { // #6279
+ point.index = cursor; // For faster access in Point.update
+ points[i] = point;
+ }
}
// Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when
// swithching view from non-grouped data to grouped data (#637)
if (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) {
@@ -17352,11 +17580,11 @@
// For points within the visible range, including the first point outside the
// visible range, consider y extremes
validValue = (isNumber(y, true) || isArray(y)) && (!yAxis.positiveValuesOnly || (y.length || y > 0));
withinRange = this.getExtremesFromAll || this.options.getExtremesFromAll || this.cropped ||
- ((xData[i + 1] || x) >= xMin && (xData[i - 1] || x) <= xMax);
+ ((xData[i] || x) >= xMin && (xData[i] || x) <= xMax);
if (validValue && withinRange) {
j = y.length;
if (j) { // array, like ohlc or range data
@@ -17368,10 +17596,11 @@
} else {
activeYData[activeCounter++] = y;
}
}
}
+
this.dataMin = arrayMin(activeYData);
this.dataMax = arrayMax(activeYData);
},
/**
@@ -17580,11 +17809,10 @@
if (clipRect.count.length === 0 && sharedClipKey && chart[sharedClipKey]) {
if (!seriesClipBox) {
chart[sharedClipKey] = chart[sharedClipKey].destroy();
}
if (chart[sharedClipKey + 'm']) {
- this.markerGroup.clip();
chart[sharedClipKey + 'm'] = chart[sharedClipKey + 'm'].destroy();
}
}
}
},
@@ -18424,11 +18652,10 @@
/**
* KD Tree && PointSearching Implementation
*/
- kdDimensions: 1,
kdAxisArray: ['clientX', 'plotY'],
searchPoint: function(e, compareX) {
var series = this,
xAxis = series.xAxis,
@@ -18451,11 +18678,12 @@
// Prevent multiple k-d-trees from being built simultaneously (#6235)
this.buildingKdTree = true;
var series = this,
- dimensions = series.kdDimensions;
+ dimensions = series.options.findNearestPointBy.indexOf('y') > -1 ?
+ 2 : 1;
// Internal function
function _kdtree(points, depth, dimensions) {
var axis,
median,
@@ -18502,11 +18730,13 @@
searchKDTree: function(point, compareX) {
var series = this,
kdX = this.kdAxisArray[0],
kdY = this.kdAxisArray[1],
- kdComparer = compareX ? 'distX' : 'dist';
+ kdComparer = compareX ? 'distX' : 'dist',
+ kdDimensions = series.options.findNearestPointBy.indexOf('y') > -1 ?
+ 2 : 1;
// Set the one and two dimensional distance on the point object
function setDistance(p1, p2) {
var x = (defined(p1[kdX]) && defined(p2[kdX])) ? Math.pow(p1[kdX] - p2[kdX], 2) : null,
y = (defined(p1[kdY]) && defined(p2[kdY])) ? Math.pow(p1[kdY] - p2[kdY], 2) : null,
@@ -18553,21 +18783,20 @@
if (!this.kdTree && !this.buildingKdTree) {
this.buildKDTree();
}
if (this.kdTree) {
- return _search(point,
- this.kdTree, this.kdDimensions, this.kdDimensions);
+ return _search(point, this.kdTree, kdDimensions, kdDimensions);
}
}
}); // end Series prototype
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Axis = H.Axis,
Chart = H.Chart,
@@ -19048,11 +19277,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
animate = H.animate,
@@ -19268,14 +19497,20 @@
if ('className' in optionsChart) {
this.setClassName(optionsChart.className);
}
if ('inverted' in optionsChart || 'polar' in optionsChart) {
- this.propFromSeries(); // Parses options.chart.inverted and options.chart.polar together with the available series
+ // Parse options.chart.inverted and options.chart.polar together
+ // with the available series.
+ this.propFromSeries();
updateAllAxes = true;
}
+ if ('alignTicks' in optionsChart) { // #6452
+ updateAllAxes = true;
+ }
+
for (key in optionsChart) {
if (optionsChart.hasOwnProperty(key)) {
if (inArray('chart.' + key, this.propsRequireUpdateSeries) !== -1) {
updateAllSeries = true;
}
@@ -19332,11 +19567,11 @@
// by an id. If the id is not found, it defaults to the corresponding
// item in the collection, so setting one series without an id, will
// update the first series in the chart. Setting two series without
// an id will update the first and the second respectively (#6019)
// chart.update and responsive.
- each(['xAxis', 'yAxis', 'series'], function(coll) {
+ each(['xAxis', 'yAxis', 'series', 'colorAxis', 'pane'], function(coll) {
if (options[coll]) {
each(splat(options[coll]), function(newOptions, i) {
var item = (
defined(newOptions.id) &&
this.get(newOptions.id)
@@ -19772,11 +20007,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var color = H.color,
each = H.each,
@@ -20103,11 +20338,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var pick = H.pick,
seriesType = H.seriesType;
@@ -20241,11 +20476,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var areaProto = H.seriesTypes.area.prototype,
defaultPlotOptions = H.defaultPlotOptions,
@@ -20263,11 +20498,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var animObject = H.animObject,
color = H.color,
@@ -20288,10 +20523,11 @@
* @augments Series
*/
seriesType('column', 'line', {
borderRadius: 0,
//colorByPoint: undefined,
+ crisp: true,
groupPadding: 0.2,
//grouping: true,
marker: null, // point options are specified in the base options
pointPadding: 0.1,
//pointWidth: null,
@@ -20446,13 +20682,15 @@
yCrisp += 1;
}
// Horizontal. We need to first compute the exact right edge, then round it
// and compute the width from there.
- right = Math.round(x + w) + xCrisp;
- x = Math.round(x) + xCrisp;
- w = right - x;
+ if (this.options.crisp) {
+ right = Math.round(x + w) + xCrisp;
+ x = Math.round(x) + xCrisp;
+ w = right - x;
+ }
// Vertical
bottom = Math.round(y + h) + yCrisp;
fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656
y = Math.round(y) + yCrisp;
@@ -20729,11 +20967,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var seriesType = H.seriesType;
@@ -20746,21 +20984,22 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Series = H.Series,
seriesType = H.seriesType;
/**
* The scatter series type
*/
seriesType('scatter', 'line', {
lineWidth: 0,
+ findNearestPointBy: 'xy',
marker: {
enabled: true // Overrides auto-enabling in line series (#3647)
},
tooltip: {
@@ -20775,22 +21014,21 @@
sorted: false,
requireSorting: false,
noSharedTooltip: true,
trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
takeOrdinalPosition: false, // #2342
- kdDimensions: 2,
drawGraph: function() {
if (this.options.lineWidth) {
Series.prototype.drawGraph.call(this);
}
}
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var pick = H.pick,
relativeLength = H.relativeLength;
@@ -20835,11 +21073,11 @@
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
CenteredSeriesMixin = H.CenteredSeriesMixin,
@@ -21336,11 +21574,11 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
arrayMax = H.arrayMax,
@@ -21535,13 +21773,13 @@
// Determine the color
style.color = pick(options.color, style.color, series.color, '#000000');
// Get automated contrast color
if (style.color === 'contrast') {
+ point.contrastColor = renderer.getContrast(point.color || series.color);
style.color = options.inside || options.distance < 0 || !!seriesOptions.stacking ?
- renderer.getContrast(point.color || series.color) :
- '#000000';
+ point.contrastColor : '#000000';
}
if (seriesOptions.cursor) {
style.cursor = seriesOptions.cursor;
}
@@ -21703,11 +21941,18 @@
alignAttr = dataLabel.alignAttr;
}
// Handle justify or crop
if (justify) {
- this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew);
+ point.isLabelJustified = this.justifyDataLabel(
+ dataLabel,
+ options,
+ alignAttr,
+ bBox,
+ alignTo,
+ isNew
+ );
// Now check that the data label is within the plot area
} else if (pick(options.crop, true)) {
visible = chart.isInsidePlot(alignAttr.x, alignAttr.y) && chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height);
}
@@ -21789,10 +22034,12 @@
if (justified) {
dataLabel.placed = !isNew;
dataLabel.align(options, null, alignTo);
}
+
+ return justified;
};
/**
* Override the base drawDataLabels method by pie specific functionality
*/
@@ -22209,42 +22456,60 @@
inverted || inside ? 'middle' : below ? 'top' : 'bottom'
);
// Call the parent method
Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
+
+ // If label was justified and we have contrast, set it:
+ if (point.isLabelJustified && point.contrastColor) {
+ point.dataLabel.css({
+ color: point.contrastColor
+ });
+ }
};
}
}(Highcharts));
(function(H) {
/**
- * (c) 2009-2016 Torstein Honsi
+ * (c) 2009-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
/**
- * Highcharts module to hide overlapping data labels. This module is included in Highcharts.
+ * Highcharts module to hide overlapping data labels. This module is included in
+ * Highcharts.
*/
var Chart = H.Chart,
each = H.each,
pick = H.pick,
addEvent = H.addEvent;
- // Collect potensial overlapping data labels. Stack labels probably don't need to be
- // considered because they are usually accompanied by data labels that lie inside the columns.
+ // Collect potensial overlapping data labels. Stack labels probably don't need
+ // to be considered because they are usually accompanied by data labels that lie
+ // inside the columns.
Chart.prototype.callbacks.push(function(chart) {
function collectAndHide() {
var labels = [];
each(chart.series || [], function(series) {
var dlOptions = series.options.dataLabels,
- collections = series.dataLabelCollections || ['dataLabel']; // Range series have two collections
- if ((dlOptions.enabled || series._hasPointLabels) && !dlOptions.allowOverlap && series.visible) { // #3866
+ // Range series have two collections
+ collections = series.dataLabelCollections || ['dataLabel'];
+
+ if (
+ (dlOptions.enabled || series._hasPointLabels) &&
+ !dlOptions.allowOverlap &&
+ series.visible
+ ) { // #3866
each(collections, function(coll) {
each(series.points, function(point) {
if (point[coll]) {
- point[coll].labelrank = pick(point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118
+ point[coll].labelrank = pick(
+ point.labelrank,
+ point.shapeArgs && point.shapeArgs.height
+ ); // #4118
labels.push(point[coll]);
}
});
});
}
@@ -22259,12 +22524,12 @@
addEvent(chart, 'redraw', collectAndHide);
});
/**
- * Hide overlapping labels. Labels are moved and faded in and out on zoom to provide a smooth
- * visual imression.
+ * Hide overlapping labels. Labels are moved and faded in and out on zoom to
+ * provide a smooth visual imression.
*/
Chart.prototype.hideOverlappingLabels = function(labels) {
var len = labels.length,
label,
@@ -22294,29 +22559,35 @@
label.oldOpacity = label.opacity;
label.newOpacity = 1;
}
}
- // Prevent a situation in a gradually rising slope, that each label
- // will hide the previous one because the previous one always has
- // lower rank.
+ // Prevent a situation in a gradually rising slope, that each label will
+ // hide the previous one because the previous one always has lower rank.
labels.sort(function(a, b) {
return (b.labelrank || 0) - (a.labelrank || 0);
});
// Detect overlapping labels
for (i = 0; i < len; i++) {
label1 = labels[i];
for (j = i + 1; j < len; ++j) {
label2 = labels[j];
- if (label1 && label2 && label1.placed && label2.placed && label1.newOpacity !== 0 && label2.newOpacity !== 0) {
+ if (
+ label1 && label2 &&
+ label1 !== label2 && // #6465, polar chart with connectEnds
+ label1.placed && label2.placed &&
+ label1.newOpacity !== 0 && label2.newOpacity !== 0
+ ) {
pos1 = label1.alignAttr;
pos2 = label2.alignAttr;
- parent1 = label1.parentGroup; // Different panes have different positions
+ // Different panes have different positions
+ parent1 = label1.parentGroup;
parent2 = label2.parentGroup;
- padding = 2 * (label1.box ? 0 : label1.padding); // Substract the padding if no background or border (#4333)
+ // Substract the padding if no background or border (#4333)
+ padding = 2 * (label1.box ? 0 : label1.padding);
isIntersecting = intersectRect(
pos1.x + parent1.translateX,
pos1.y + parent1.translateY,
label1.width - padding,
label1.height - padding,
@@ -22325,11 +22596,12 @@
label2.width - padding,
label2.height - padding
);
if (isIntersecting) {
- (label1.labelrank < label2.labelrank ? label1 : label2).newOpacity = 0;
+ (label1.labelrank < label2.labelrank ? label1 : label2)
+ .newOpacity = 0;
}
}
}
}
@@ -22341,33 +22613,38 @@
if (label) {
newOpacity = label.newOpacity;
if (label.oldOpacity !== newOpacity && label.placed) {
- // Make sure the label is completely hidden to avoid catching clicks (#4362)
+ // Make sure the label is completely hidden to avoid catching
+ // clicks (#4362)
if (newOpacity) {
label.show(true);
} else {
complete = function() {
label.hide();
};
}
// Animate or set the opacity
label.alignAttr.opacity = newOpacity;
- label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete);
+ label[label.isOld ? 'animate' : 'attr'](
+ label.alignAttr,
+ null,
+ complete
+ );
}
label.isOld = true;
}
});
};
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var addEvent = H.addEvent,
Chart = H.Chart,
@@ -23143,11 +23420,11 @@
fireEvent(series, 'mouseOut');
}
// hide the tooltip
- if (tooltip && !options.stickyTracking && (!tooltip.shared || series.noSharedTooltip)) {
+ if (tooltip && !series.stickyTracking && (!tooltip.shared || series.noSharedTooltip)) {
tooltip.hide();
}
// set normal state
series.setState();
@@ -23322,10 +23599,10 @@
});
}(Highcharts));
(function(H) {
/**
- * (c) 2010-2016 Torstein Honsi
+ * (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Chart = H.Chart,
each = H.each,