app/assets/javascripts/highcharts.js in highcharts-rails-5.0.11 vs app/assets/javascripts/highcharts.js in highcharts-rails-5.0.12
- old
+ new
@@ -1,7 +1,7 @@
/**
- * @license Highcharts JS v5.0.11 (2017-05-04)
+ * @license Highcharts JS v5.0.12 (2017-05-24)
*
* (c) 2009-2016 Torstein Honsi
*
* License: www.highcharts.com/license
*/
@@ -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.11',
+ version: '5.0.12',
deg2rad: Math.PI * 2 / 360,
doc: doc,
hasBidiBug: hasBidiBug,
hasTouch: doc && doc.documentElement.ontouchstart !== undefined,
isMS: isMS,
@@ -57,11 +57,11 @@
},
/**
* An array containing the current chart objects in the page. A chart's
* position in the array is preserved throughout the page's lifetime. When
* a chart is destroyed, the array item becomes `undefined`.
- * @type {Array}
+ * @type {Array.<Highcharts.Chart>}
* @memberOf Highcharts
*/
charts: []
};
return Highcharts;
@@ -468,11 +468,24 @@
return [start, end];
}
}; // End of Fx prototype
+ /**
+ * Handle animation of the color attributes directly.
+ */
+ H.Fx.prototype.fillSetter =
+ H.Fx.prototype.strokeSetter = function() {
+ this.elem.attr(
+ this.prop,
+ H.color(this.start).tweenTo(H.color(this.end), this.pos),
+ null,
+ true
+ );
+ };
+
/**
* Utility function to extend an object with the members of another.
*
* @function #extend
* @memberOf Highcharts
@@ -2003,10 +2016,14 @@
// docs: add to API + extending Highcharts
H.seriesType = function(type, parent, options, props, pointProps) {
var defaultOptions = H.getOptions(),
seriesTypes = H.seriesTypes;
+ if (seriesTypes[type]) {
+ return H.error(27); // Series type already defined
+ }
+
// Merge the options
defaultOptions.plotOptions[type] = H.merge(
defaultOptions.plotOptions[parent],
options
);
@@ -2226,10 +2243,11 @@
}],
// Collection of named colors. Can be extended from the outside by adding
// colors to Highcharts.Color.prototype.names.
names: {
+ none: 'rgba(255,255,255,0)',
white: '#ffffff',
black: '#000000'
},
/**
@@ -2367,10 +2385,49 @@
* @param {Number} alpha
*/
setOpacity: function(alpha) {
this.rgba[3] = alpha;
return this;
+ },
+
+ /*
+ * Return an intermediate color between two colors.
+ *
+ * @param {Highcharts.Color} to
+ * The color object to tween to.
+ * @param {Number} pos
+ * The intermediate position, where 0 is the from color (current
+ * color item), and 1 is the `to` color.
+ *
+ * @return {String}
+ * The intermediate color in rgba notation.
+ */
+ tweenTo: function(to, pos) {
+ // Check for has alpha, because rgba colors perform worse due to lack of
+ // support in WebKit.
+ var from = this,
+ hasAlpha,
+ ret;
+
+ // Unsupported color, return to-color (#3920)
+ if (!to.rgba.length) {
+ ret = to.input || 'none';
+
+ // Interpolate
+ } else {
+ from = from.rgba;
+ to = to.rgba;
+ hasAlpha = (to[3] !== 1 || from[3] !== 1);
+ ret = (hasAlpha ? 'rgba(' : 'rgb(') +
+ Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' +
+ Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' +
+ Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) +
+ (hasAlpha ?
+ (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) :
+ '') + ')';
+ }
+ return ret;
}
};
H.color = function(input) {
return new H.Color(input);
};
@@ -2424,27 +2481,29 @@
/**
* @typedef {Object} SVGDOMElement - An SVG DOM element.
*/
/**
* The SVGElement prototype is a JavaScript wrapper for SVG elements used in the
- * rendering layer of Highcharts. Combined with the {@link SVGRenderer} object,
- * these prototypes allow freeform annotation in the charts or even in HTML
- * pages without instanciating a chart. The SVGElement can also wrap HTML
- * labels, when `text` or `label` elements are created with the `useHTML`
- * parameter.
+ * rendering layer of Highcharts. Combined with the {@link
+ * Highcharts.SVGRenderer} object, these prototypes allow freeform annotation
+ * in the charts or even in HTML pages without instanciating a chart. The
+ * SVGElement can also wrap HTML labels, when `text` or `label` elements are
+ * created with the `useHTML` parameter.
*
* The SVGElement instances are created through factory functions on the
- * {@link SVGRenderer} object, like [rect]{@link SVGRenderer#rect},
- * [path]{@link SVGRenderer#path}, [text]{@link SVGRenderer#text}, [label]{@link
- * SVGRenderer#label}, [g]{@link SVGRenderer#g} and more.
+ * {@link Highcharts.SVGRenderer} object, like
+ * [rect]{@link Highcharts.SVGRenderer#rect}, [path]{@link
+ * Highcharts.SVGRenderer#path}, [text]{@link Highcharts.SVGRenderer#text},
+ * [label]{@link Highcharts.SVGRenderer#label}, [g]{@link
+ * Highcharts.SVGRenderer#g} and more.
*
- * @class
+ * @class Highcharts.SVGElement
*/
SVGElement = H.SVGElement = function() {
return this;
};
- SVGElement.prototype = {
+ extend(SVGElement.prototype, /** @lends Highcharts.SVGElement.prototype */ {
// Default base for animation
opacity: 1,
SVG_NS: SVG_NS,
@@ -2459,12 +2518,14 @@
/**
* Initialize the SVG renderer. This function only exists to make the
* initiation process overridable. It should not be called directly.
*
- * @param {SVGRenderer} renderer The SVGRenderer instance to initialize to.
- * @param {String} nodeName The SVG node name.
+ * @param {HighchartsSVGRenderer} renderer
+ * The SVGRenderer instance to initialize to.
+ * @param {String} nodeName
+ * The SVG node name.
* @returns {void}
*/
init: function(renderer, nodeName) {
/**
@@ -2476,22 +2537,26 @@
createElement(nodeName) :
doc.createElementNS(this.SVG_NS, nodeName);
/**
* The renderer that the SVGElement belongs to.
- * @type {SVGRenderer}
+ * @type {Highcharts.SVGRenderer}
*/
this.renderer = renderer;
},
/**
* Animate to given attributes or CSS properties.
*
* @param {SVGAttributes} params SVG attributes or CSS to animate.
* @param {AnimationOptions} [options] Animation options.
* @param {Function} [complete] Function to perform at the end of animation.
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ *
+ * @sample highcharts/members/element-on/
+ * Setting some attributes by animation
+ *
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
animate: function(params, options, complete) {
var animOptions = H.animObject(
pick(options, this.renderer.globalAnimation, true)
);
@@ -2807,20 +2872,23 @@
* @param {string} [val] - If the type of the first argument is `string`,
* the second can be a value, which will serve as a single attribute
* setter. If the first argument is a string and the second is undefined,
* the function serves as a getter and the current value of the property
* is returned.
- * @param {Function} complete - A callback function to execute after setting
+ * @param {Function} [complete] - A callback function to execute after setting
* the attributes. This makes the function compliant and interchangeable
* with the {@link SVGElement#animate} function.
- * @param {boolean} continueAnimation - Used internally when `.attr` is
+ * @param {boolean} [continueAnimation=true] Used internally when `.attr` is
* called as part of an animation step. Otherwise, calling `.attr` for an
* attribute will stop animation for that attribute.
*
* @returns {SVGElement|string|number} If used as a setter, it returns the
* current {@link SVGElement} so the calls can be chained. If used as a
* getter, the current value of the attribute is returned.
+ *
+ * @sample highcharts/members/renderer-rect/
+ * Setting some attributes
*
* @example
* // Set multiple attributes
* element.attr({
* stroke: 'red',
@@ -2895,28 +2963,36 @@
}
}
}, this);
- // Update transform. Do this outside the loop to prevent redundant updating for batch setting
- // of attributes.
- if (this.doTransform) {
- this.updateTransform();
- this.doTransform = false;
- }
-
+ this.afterSetters();
}
// In accordance with animate, run a complete callback
if (complete) {
complete();
}
return ret;
},
+ /**
+ * This method is executed in the end of {attr}, after setting all attributes in the hash.
+ * In can be used to efficiently consolidate multiple attributes in one SVG property -- e.g.,
+ * translate, rotate and scale are merged in one "transform" attribute in the SVG node.
+ */
+ afterSetters: function() {
+ // Update transform. Do this outside the loop to prevent redundant updating for batch setting
+ // of attributes.
+ if (this.doTransform) {
+ this.updateTransform();
+ this.doTransform = false;
+ }
+ },
+
/**
* Update the shadow elements with new attributes.
*
* @private
* @param {String} key - The attribute name.
@@ -2947,11 +3023,11 @@
*
* @param {string} className - The new class name to add.
* @param {boolean} [replace=false] - When true, the existing class name(s)
* will be overwritten with the new one. When false, the new one is
* added.
- * @returns {SVGElement} Return the SVG element for chainability.
+ * @returns {Highcharts.SVGElement} Return the SVG element for chainability.
*/
addClass: function(className, replace) {
var currentClassName = this.attr('class') || '';
if (currentClassName.indexOf(className) === -1) {
@@ -2975,11 +3051,11 @@
},
/**
* Remove a class name from the element.
* @param {string} className The class name to remove.
- * @return {SVGElement} Returns the SVG element for chainability.
+ * @return {Highcharts.SVGElement} Returns the SVG element for chainability.
*/
removeClass: function(className) {
attr(this.element, 'class', (attr(this.element, 'class') || '').replace(className, ''));
return this;
},
@@ -3012,11 +3088,11 @@
/**
* Apply a clipping rectangle to this element.
*
* @param {ClipRect} [clipRect] - The clipping rectangle. If skipped, the
* current clip is removed.
- * @returns {SVGElement} Returns the SVG element to allow chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVG element to allow chaining.
*/
clip: function(clipRect) {
return this.attr(
'clip-path',
clipRect ?
@@ -3072,11 +3148,14 @@
* Set styles for the element. In addition to CSS styles supported by
* native SVG and HTML elements, there are also some custom made for
* Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text
* elements.
* @param {CSSObject} styles The new CSS styles.
- * @returns {SVGElement} Return the SVG element for chaining.
+ * @returns {Highcharts.SVGElement} Return the SVG element for chaining.
+ *
+ * @sample highcharts/members/renderer-text-on-chart/
+ * Styled text
*/
css: function(styles) {
var oldStyles = this.styles,
newStyles = {},
elem = this.element,
@@ -3187,11 +3266,14 @@
* @param {string} eventType - The event type. If the type is `click`,
* Highcharts will internally translate it to a `touchstart` event on
* touch devices, to prevent the browser from waiting for a click event
* from firing.
* @param {Function} handler - The handler callback.
- * @returns {SVGElement} The SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} The SVGElement for chaining.
+ *
+ * @sample highcharts/members/element-on/
+ * A clickable rectangle
*/
on: function(eventType, handler) {
var svgElement = this,
element = svgElement.element;
@@ -3220,11 +3302,11 @@
* a shape regardless of positioning inside the chart. Used on pie slices
* to make all the slices have the same radial reference point.
*
* @param {Array} coordinates The center reference. The format is
* `[centerX, centerY, diameter]` in pixels.
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
setRadialReference: function(coordinates) {
var existingGradient = this.renderer.gradients[this.element.gradient];
this.element.radialReference = coordinates;
@@ -3261,11 +3343,11 @@
* charts, where the points and graphs are drawn as if not inverted, then
* the series group elements are inverted.
*
* @param {boolean} inverted - Whether to invert or not. An inverted shape
* can be un-inverted by setting it to false.
- * @returns {SVGElement} Return the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Return the SVGElement for chaining.
*/
invert: function(inverted) {
var wrapper = this;
wrapper.inverted = inverted;
wrapper.updateTransform();
@@ -3319,24 +3401,27 @@
element.setAttribute('transform', transform.join(' '));
}
},
/**
- * Bring the element to the front.
+ * Bring the element to the front. Alternatively, a new zIndex can be set.
*
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
+ *
+ * @sample highcharts/members/element-tofront/
+ * Click an element to bring it to front
*/
toFront: function() {
var element = this.element;
element.parentNode.appendChild(element);
return this;
},
/**
* Align the element relative to the chart or another box.
- * ß
+ *
* @param {Object} [alignOptions] The alignment options. The function can be
* called without this parameter in order to re-align an element after the
* box has been updated.
* @param {string} [alignOptions.align=left] Horizontal alignment. Can be
* one of `left`, `center` and `right`.
@@ -3350,11 +3435,11 @@
* rather than `x` and `y` attributes.
* @param {String|Object} box The box to align to, needs a width and height.
* When the box is a string, it refers to an object in the Renderer. For
* example, when box is `spacingBox`, it refers to `Renderer.spacingBox`
* which holds `width`, `height`, `x` and `y` properties.
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
align: function(alignOptions, alignByTranslate, box) {
var align,
vAlign,
x,
@@ -3436,10 +3521,13 @@
* @param {number} [rot] Override the element's rotation. This is internally
* used on axis labels with a value of 0 to find out what the bounding box
* would be have been if it were not rotated.
* @returns {Object} The bounding box with `x`, `y`, `width` and `height`
* properties.
+ *
+ * @sample highcharts/members/renderer-on-chart/
+ * Draw a rectangle based on a text's bounding box
*/
getBBox: function(reload, rot) {
var wrapper = this,
bBox, // = wrapper.bBox,
renderer = wrapper.renderer,
@@ -3596,11 +3684,11 @@
*
* @param {boolean} [inherit=false] Set the visibility attribute to
* `inherit` rather than `visible`. The difference is that an element with
* `visibility="visible"` will be visible even if the parent is hidden.
*
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
show: function(inherit) {
return this.attr({
visibility: inherit ? 'inherit' : 'visible'
});
@@ -3608,11 +3696,11 @@
/**
* Hide the element, equivalent to setting the `visibility` attribute to
* `hidden`.
*
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
hide: function() {
return this.attr({
visibility: 'hidden'
});
@@ -3639,14 +3727,15 @@
},
/**
* Add the element to the DOM. All elements must be added this way.
*
- * @param {SVGElement|SVGDOMElement} [parent] The parent item to add it to.
- * If undefined, the element is added to the {@link SVGRenderer.box}.
+ * @param {Highcharts.SVGElement|SVGDOMElement} [parent] The parent item to add it to.
+ * If undefined, the element is added to the {@link
+ * Highcharts.SVGRenderer.box}.
*
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*
* @sample highcharts/members/renderer-g - Elements added to a group
*/
add: function(parent) {
@@ -3791,17 +3880,17 @@
* filters.
*
* @param {boolean|ShadowOptions} shadowOptions The shadow options. If
* `true`, the default options are applied. If `false`, the current
* shadow will be removed.
- * @param {SVGElement} [group] The SVG group element where the shadows will
+ * @param {Highcharts.SVGElement} [group] The SVG group element where the shadows will
* be applied. The default is to add it to the same parent as the current
* element. Internally, this is ised for pie slices, where all the
* shadows are added to an element behind all the slices.
* @param {boolean} [cutOff] Used internally for column shadows.
*
- * @returns {SVGElement} Returns the SVGElement for chaining.
+ * @returns {Highcharts.SVGElement} Returns the SVGElement for chaining.
*
* @example
* renderer.rect(10, 100, 100, 100)
* .attr({ fill: 'red' })
* .shadow(true);
@@ -3882,11 +3971,12 @@
return this._defaultGetter(key);
},
/**
* Get the current value of an attribute or pseudo attribute, used mainly
- * for animation. Called internally from the {@link SVGRenderer#attr}
+ * for animation. Called internally from the {@link
+ * Highcharts.SVGRenderer#attr}
* function.
*
* @private
*/
_defaultGetter: function(key) {
@@ -4057,11 +4147,11 @@
return inserted;
},
_defaultSetter: function(value, key, element) {
element.setAttribute(key, value);
}
- };
+ });
// Some shared setters and getters
SVGElement.prototype.yGetter = SVGElement.prototype.xGetter;
SVGElement.prototype.translateXSetter = SVGElement.prototype.translateYSetter =
SVGElement.prototype.rotationSetter = SVGElement.prototype.verticalAlignSetter =
@@ -4109,20 +4199,20 @@
* var renderer = new Highcharts.Renderer(parentNode, 600, 400);
*
* @sample highcharts/members/renderer-on-chart - Annotating a chart programmatically.
* @sample highcharts/members/renderer-basic - Independedt SVG drawing.
*
- * @class
+ * @class Highcharts.SVGRenderer
*/
SVGRenderer = H.SVGRenderer = function() {
this.init.apply(this, arguments);
};
- SVGRenderer.prototype = {
+ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
/**
* A pointer to the renderer's associated Element class. The VMLRenderer
* will have a pointer to VMLElement here.
- * @type {SVGElement}
+ * @type {Highcharts.SVGElement}
*/
Element: SVGElement,
SVG_NS: SVG_NS,
/**
* Initialize the SVGRenderer. Overridable initiator function that takes
@@ -4157,11 +4247,11 @@
* @type {SVGDOMElement}
*/
this.box = element;
/**
* The wrapper for the root `svg` node of the renderer.
- * @type {SVGElement}
+ * @type {Highcharts.SVGElement}
*/
this.boxWrapper = boxWrapper;
renderer.alignedObjects = [];
/**
@@ -4177,11 +4267,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.11'));
+ desc.element.appendChild(doc.createTextNode('Created with Highcharts 5.0.12'));
renderer.defs = this.createElement('defs').add();
renderer.allowHTML = allowHTML;
renderer.forExport = forExport;
@@ -4294,11 +4384,11 @@
* {@link SVGElement}, but this function is itself mostly called from
* primitive factories like {@link SVGRenderer#path}, {@link
* SVGRenderer#rect} or {@link SVGRenderer#text}.
*
* @param {string} nodeName - The node name, for example `rect`, `g` etc.
- * @returns {SVGElement} The generated SVGElement.
+ * @returns {Highcharts.SVGElement} The generated SVGElement.
*/
createElement: function(nodeName) {
var wrapper = new this.Element();
wrapper.init(this, nodeName);
return wrapper;
@@ -4382,11 +4472,11 @@
* 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`.
* @private
- * @param {SVGElement} wrapper The parent SVGElement.
+ * @param {Highcharts.SVGElement} wrapper The parent SVGElement.
*/
buildText: function(wrapper) {
var textNode = wrapper.element,
renderer = this,
forExport = renderer.forExport,
@@ -4459,11 +4549,11 @@
// Complex strings, add more logic
} else {
clsRegex = /<.*class="([^"]+)".*>/;
styleRegex = /<.*style="([^"]+)".*>/;
- hrefRegex = /<.*href="(http[^"]+)".*>/;
+ hrefRegex = /<.*href="([^"]+)".*>/;
if (tempParent) {
tempParent.appendChild(textNode); // attach it to the DOM to read offset width
}
@@ -4846,17 +4936,23 @@
*
* @example
* var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z'])
* .attr({ stroke: '#ff00ff' })
* .add();
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-path-on-chart/
+ * Draw a path in a chart
+ * @sample highcharts/members/renderer-path/
+ * Draw a path independent from a chart
+ *
*/
/**
* Draw a path, wraps the SVG `path` element.
*
* @param {SVGAttributes} [attribs] The initial attributes.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
*/
path: function(path) {
var attribs = {
fill: 'none'
@@ -4874,17 +4970,19 @@
* Draw a circle, wraps the SVG `circle` element.
*
* @param {number} [x] The center x position.
* @param {number} [y] The center y position.
* @param {number} [r] The radius.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-circle/ Drawing a circle
*/
/**
* Draw a circle, wraps the SVG `circle` element.
*
* @param {SVGAttributes} [attribs] The initial attributes.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
*/
circle: function(x, y, r) {
var attribs = isObject(x) ? x : {
x: x,
y: y,
@@ -4908,16 +5006,19 @@
* @param {number} [innerR=0] Inner radius like used in donut charts.
* @param {number} [start=0] The starting angle of the arc in radians, where
* 0 is to the right and `-Math.PI/2` is up.
* @param {number} [end=0] The ending angle of the arc in radians, where 0
* is to the right and `-Math.PI/2` is up.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-arc/
+ * Drawing an arc
*/
/**
* Draw and return an arc. Overloaded function that takes arguments object.
* @param {SVGAttributes} attribs Initial SVG attributes.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
*/
arc: function(x, y, r, innerR, start, end) {
var arc,
options;
@@ -4951,17 +5052,23 @@
* @param {number} [width] Width of the rectangle.
* @param {number} [height] Height of the rectangle.
* @param {number} [r] Border corner radius.
* @param {number} [strokeWidth] A stroke width can be supplied to allow
* crisp drawing.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
*/
/**
* Draw and return a rectangle.
- * @param {SVGAttributes} [attributes] General SVG attributes for the
- * rectangle.
- * @returns {SVGElement} The generated wrapper element.
+ * @param {SVGAttributes} [attributes]
+ * General SVG attributes for the rectangle.
+ * @return {Highcharts.SVGElement}
+ * The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-rect-on-chart/
+ * Draw a rectangle in a chart
+ * @sample highcharts/members/renderer-rect/
+ * Draw a rectangle independent from a chart
*/
rect: function(x, y, width, height, r, strokeWidth) {
r = isObject(x) ? x.r : r;
@@ -5026,15 +5133,20 @@
alignedObjects[i].align();
}
},
/**
- * Create and return an svg group element.
+ * Create and return an svg group element. Child {@link Highcharts.SVGElement}
+ * objects are added to the group by using the group as the first parameter
+ * in {@link Highcharts.SVGElement#add|add()}.
*
* @param {string} [name] The group will be given a class name of
* `highcharts-{name}`. This can be used for styling and scripting.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-g/
+ * Show and hide grouped objects
*/
g: function(name) {
var elem = this.createElement('g');
return name ? elem.attr({
'class': 'highcharts-' + name
@@ -5048,11 +5160,16 @@
* @param {number} [y] The Y position.
* @param {number} [width] The image width. If omitted, it defaults to the
* image file width.
* @param {number} [height] The image height. If omitted it defaults to the
* image file height.
- * @returns {SVGElement} The generated wrapper element.
+ * @returns {Highcharts.SVGElement} The generated wrapper element.
+ *
+ * @sample highcharts/members/renderer-image-on-chart/
+ * Add an image in a chart
+ * @sample highcharts/members/renderer-image/
+ * Add an image independent of a chart
*/
image: function(src, x, y, width, height) {
var attribs = {
preserveAspectRatio: 'none'
},
@@ -5461,11 +5578,11 @@
return path;
}
},
/**
- * @typedef {SVGElement} ClipRect - A clipping rectangle that can be applied
+ * @typedef {Highcharts.SVGElement} ClipRect - A clipping rectangle that can be applied
* to one or more {@link SVGElement} instances. It is instanciated with the
* {@link SVGRenderer#clipRect} function and applied with the {@link
* SVGElement#clip} function.
*
* @example
@@ -5505,15 +5622,31 @@
/**
- * Add text to the SVG object
- * @param {String} str
- * @param {number} x Left position
- * @param {number} y Top position
- * @param {Boolean} useHTML Use HTML to render the text
+ * Draw text. The text can contain a subset of HTML, like spans and anchors
+ * and some basic text styling of these. For more advanced features like
+ * border and background, use {@link Highcharts.SVGRenderer#label} instead.
+ * To update the text after render, run `text.attr({ text: 'New text' })`.
+ * @param {String} str
+ * The text of (subset) HTML to draw.
+ * @param {number} x
+ * The x position of the text's lower left corner.
+ * @param {number} y
+ * The y position of the text's lower left corner.
+ * @param {Boolean} [useHTML=false]
+ * Use HTML to render the text.
+ *
+ * @return {Highcharts.SVGElement} The text object.
+ *
+ * @sample highcharts/members/renderer-text-on-chart/
+ * Annotate the chart freely
+ * @sample highcharts/members/renderer-on-chart/
+ * Annotate with a border and in response to the data
+ * @sample highcharts/members/renderer-text/
+ * Formatted text
*/
text: function(str, x, y, useHTML) {
// declare variables
var renderer = this,
@@ -5624,24 +5757,46 @@
y: y
};
},
/**
- * Add a label, a text item that can hold a colored or gradient background
- * as well as a border and shadow. Supported custom attributes include
- * `padding`.
+ * Draw a label, which is an extended text element with support for border
+ * and background. Highcharts creates a `g` element with a text and a `path`
+ * or `rect` inside, to make it behave somewhat like a HTML div. Border and
+ * background are set through `stroke`, `stroke-width` and `fill` attributes
+ * using the {@link Highcharts.SVGElement#attr|attr} method. To update the
+ * text after render, run `label.attr({ text: 'New text' })`.
*
- * @param {string} str
- * @param {number} x
- * @param {number} y
- * @param {String} shape
- * @param {number} anchorX In case the shape has a pointer, like a flag, this is the
- * coordinates it should be pinned to
- * @param {number} anchorY
- * @param {Boolean} baseline Whether to position the label relative to the text baseline,
- * like renderer.text, or to the upper border of the rectangle.
- * @param {String} className Class name for the group
+ * @param {string} str
+ * The initial text string or (subset) HTML to render.
+ * @param {number} x
+ * The x position of the label's left side.
+ * @param {number} y
+ * The y position of the label's top side or baseline, depending on
+ * the `baseline` parameter.
+ * @param {String} shape
+ * The shape of the label's border/background, if any. Defaults to
+ * `rect`. Other possible values are `callout` or other shapes
+ * defined in {@link Highcharts.SVGRenderer#symbols}.
+ * @param {number} anchorX
+ * In case the `shape` has a pointer, like a flag, this is the
+ * coordinates it should be pinned to.
+ * @param {number} anchorY
+ * In case the `shape` has a pointer, like a flag, this is the
+ * coordinates it should be pinned to.
+ * @param {Boolean} baseline
+ * Whether to position the label relative to the text baseline,
+ * like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the
+ * upper border of the rectangle.
+ * @param {String} className
+ * Class name for the group.
+ *
+ * @return {Highcharts.SVGElement}
+ * The generated label.
+ *
+ * @sample highcharts/members/renderer-label-on-chart/
+ * A label on the chart
*/
label: function(str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
var renderer = this,
wrapper = renderer.g(className !== 'button' && 'label'),
@@ -5957,11 +6112,11 @@
// Release local pointers (#1298)
wrapper = renderer = updateBoxSize = updateTextPadding = boxAttr = null;
}
});
}
- }; // end SVGRenderer
+ }); // end SVGRenderer
// general renderer
H.Renderer = SVGRenderer;
@@ -7525,11 +7680,11 @@
},
global: {
useUTC: true,
//timezoneOffset: 0,
- VMLRadialGradientURL: 'http://code.highcharts.com/5.0.11/gfx/vml-radial-gradient.png'
+ VMLRadialGradientURL: 'http://code.highcharts.com/5.0.12/gfx/vml-radial-gradient.png'
},
chart: {
//animation: true,
//alignTicks: false,
@@ -7641,11 +7796,12 @@
},*/
itemStyle: {
color: '#333333',
fontSize: '12px',
- fontWeight: 'bold'
+ fontWeight: 'bold',
+ textOverflow: 'ellipsis'
},
itemHoverStyle: {
//cursor: 'pointer', removed as of #601
color: '#000000'
},
@@ -7894,10 +8050,11 @@
H.Tick = function(axis, pos, type, noLabel) {
this.axis = axis;
this.pos = pos;
this.type = type || '';
this.isNew = true;
+ this.isNewLabel = true;
if (!type && !noLabel) {
this.addLabel();
}
};
@@ -8333,13 +8490,15 @@
}
// Set the new position, and show or hide
if (show && isNumber(xy.y)) {
xy.opacity = opacity;
- label[tick.isNew ? 'attr' : 'animate'](xy);
+ label[tick.isNewLabel ? 'attr' : 'animate'](xy);
+ tick.isNewLabel = false;
} else {
label.attr('y', -9999); // #1338
+ tick.isNewLabel = true;
}
tick.isNew = false;
}
},
@@ -8420,11 +8579,11 @@
syncTimeout = H.syncTimeout,
Tick = H.Tick;
/**
* Create a new axis object. Called internally when instanciating a new chart or
- * adding axes by {@link Chart#addAxis}.
+ * adding axes by {@link Highcharts.Chart#addAxis}.
*
* A chart can have from 0 axes (pie chart) to multiples. In a normal, single
* series cartesian chart, there is one X axis and one Y axis.
*
* The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is
@@ -8453,11 +8612,14 @@
};
H.extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ {
/**
- * Default options for the X axis - the Y axis has extended defaults
+ * Default options for the X axis - the Y axis has extended defaults.
+ *
+ * @private
+ * @type {Object}
*/
defaultOptions: {
// allowDecimals: null,
// alternateGridColor: null,
// categories: [],
@@ -8556,11 +8718,14 @@
// tickWidth: 1
},
/**
- * This options set extends the defaultOptions for Y axes
+ * This options set extends the defaultOptions for Y axes.
+ *
+ * @private
+ * @type {Object}
*/
defaultYAxisOptions: {
endOnTick: true,
tickPixelInterval: 72,
showLastLabel: true,
@@ -8600,11 +8765,14 @@
// tickWidth: 0
},
/**
- * These options extend the defaultOptions for left axes
+ * These options extend the defaultOptions for left axes.
+ *
+ * @private
+ * @type {Object}
*/
defaultLeftAxisOptions: {
labels: {
x: -15
},
@@ -8612,11 +8780,14 @@
rotation: 270
}
},
/**
- * These options extend the defaultOptions for right axes
+ * These options extend the defaultOptions for right axes.
+ *
+ * @private
+ * @type {Object}
*/
defaultRightAxisOptions: {
labels: {
x: 15
},
@@ -8624,11 +8795,14 @@
rotation: 90
}
},
/**
- * These options extend the defaultOptions for bottom axes
+ * These options extend the defaultOptions for bottom axes.
+ *
+ * @private
+ * @type {Object}
*/
defaultBottomAxisOptions: {
labels: {
autoRotation: [-45],
x: 0
@@ -8638,11 +8812,14 @@
title: {
rotation: 0
}
},
/**
- * These options extend the defaultOptions for top axes
+ * These options extend the defaultOptions for top axes.
+ *
+ * @private
+ * @type {Object}
*/
defaultTopAxisOptions: {
labels: {
autoRotation: [-45],
x: 0
@@ -8664,11 +8841,11 @@
axis = this;
axis.chart = chart;
// Flag, is the axis horizontal
- axis.horiz = chart.inverted ? !isXAxis : isXAxis;
+ axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis;
// Flag, isXAxis
axis.isXAxis = isXAxis;
axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis');
@@ -8793,11 +8970,11 @@
}
axis.series = axis.series || []; // populated by Series
// inverted charts have reversed xAxes as default
- if (chart.inverted && isXAxis && axis.reversed === undefined) {
+ if (chart.inverted && !axis.isZAxis && isXAxis && axis.reversed === undefined) {
axis.reversed = true;
}
// register event listeners
objectEach(events, function(event, eventType) {
@@ -8831,11 +9008,15 @@
);
},
/**
* The default label formatter. The context is a special config object for
- * the label.
+ * the label. In apps, use the {@link
+ * https://api.highcharts.com/highcharts/xAxis.labels.formatter|
+ * labels.formatter} instead except when a modification is needed.
+ *
+ * @private
*/
defaultLabelFormatter: function() {
var axis = this.axis,
value = this.value,
categories = axis.categories,
@@ -9136,11 +9317,22 @@
null :
chart.renderer.crispLine(['M', x1, y1, 'L', x2, y2], lineWidth || 1);
},
/**
- * Set the tick positions of a linear axis to round values like whole tens or every five.
+ * Internal function to et the tick positions of a linear axis to round
+ * values like whole tens or every five.
+ *
+ * @param {Number} tickInterval
+ * The normalized tick interval
+ * @param {Number} min
+ * Axis minimum.
+ * @param {Number} max
+ * Axis maximum.
+ *
+ * @return {Array.<Number>}
+ * An array of numbers where ticks should be placed.
*/
getLinearTickPositions: function(tickInterval, min, max) {
var pos,
lastPos,
roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval),
@@ -9242,18 +9434,20 @@
/**
* Adjust the min and max for the minimum range. Keep in mind that the series data is
* not yet processed, so we don't have information on data cropping and grouping, or
* updated axis.pointRange or series.pointRange. The data can't be processed until
* we have finally established min and max.
+ *
+ * @private
*/
adjustForMinRange: function() {
var axis = this,
options = axis.options,
min = axis.min,
max = axis.max,
zoomOffset,
- spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange,
+ spaceAvailable,
closestDataRange,
i,
distance,
xData,
loopLength,
@@ -9285,10 +9479,12 @@
}
}
// if minRange is exceeded, adjust
if (max - min < axis.minRange) {
+
+ spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange;
minRange = axis.minRange;
zoomOffset = (minRange - max + min) / 2;
// if min and max options have been set, don't go beyond it
minArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)];
@@ -9316,11 +9512,13 @@
axis.min = min;
axis.max = max;
},
/**
- * Find the closestPointRange across all series
+ * Find the closestPointRange across all series.
+ *
+ * @private
*/
getClosest: function() {
var ret;
if (this.categories) {
@@ -9383,11 +9581,11 @@
updateNames: function() {
var axis = this;
if (this.names.length > 0) {
this.names.length = 0;
- this.minRange = undefined;
+ this.minRange = this.userMinRange; // Reset
each(this.series || [], function(series) {
// Reset incrementer (#5928)
series.xIncrement = null;
@@ -9841,12 +10039,15 @@
}
}
},
/**
- * Check if there are multiple axes in the same pane
- * @returns {Boolean} There are other axes
+ * Check if there are multiple axes in the same pane.
+ *
+ * @private
+ * @return {Boolean}
+ * True if there are other axes.
*/
alignToOthers: function() {
var others = {}, // Whether there is another axis to pair with this one
hasOther,
options = this.options;
@@ -9911,11 +10112,13 @@
this.tickAmount = tickAmount;
},
/**
* When using multiple axes, adjust the number of ticks to match the highest
- * number of ticks in that group
+ * number of ticks in that group.
+ *
+ * @private
*/
adjustTickAmount: function() {
var tickInterval = this.tickInterval,
tickPositions = this.tickPositions,
tickAmount = this.tickAmount,
@@ -10015,28 +10218,32 @@
* values are rounded off to the nearest tick. To prevent this, these
* options can be set to false before calling setExtremes. Also, setExtremes
* will not allow a range lower than the `minRange` option, which by default
* is the range of five points.
*
- * @param {Number} [newMin]
- * The new minimum value.
- * @param {Number} [newMax]
- * The new maximum value.
- * @param {Boolean} [redraw=true]
- * Whether to redraw the chart or wait for an explicit call to
- * {@link Highcharts.Chart#redraw}
- * @param {AnimationOptions} [animation=true]
- * Enable or modify animations.
- * @param {Object} [eventArguments]
- * Arguments to be accessed in event handler.
+ * @param {Number} [newMin]
+ * The new minimum value.
+ * @param {Number} [newMax]
+ * The new maximum value.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart or wait for an explicit call to
+ * {@link Highcharts.Chart#redraw}
+ * @param {AnimationOptions} [animation=true]
+ * Enable or modify animations.
+ * @param {Object} [eventArguments]
+ * Arguments to be accessed in event handler.
*
* @sample highcharts/members/axis-setextremes/
- * Set extremes from a button
+ * Set extremes from a button
* @sample highcharts/members/axis-setextremes-datetime/
- * Set extremes on a datetime axis
+ * Set extremes on a datetime axis
* @sample highcharts/members/axis-setextremes-off-ticks/
- * Set extremes off ticks
+ * Set extremes off ticks
+ * @sample stock/members/axis-setextremes/
+ * Set extremes in Highstock
+ * @sample maps/members/axis-setextremes/
+ * Set extremes in Highmaps
*/
setExtremes: function(newMin, newMax, redraw, animation, eventArguments) {
var axis = this,
chart = axis.chart;
@@ -10172,11 +10379,15 @@
/**
* Get the current extremes for the axis.
*
* @returns {Extremes}
* An object containing extremes information.
- * @sample members/axis-getextremes/ Report extremes by click on a button
+ *
+ * @sample members/axis-getextremes/
+ * Report extremes by click on a button
+ * @sample maps/members/axis-getextremes/
+ * Get extremes in Highmaps
*/
getExtremes: function() {
var axis = this,
isLog = axis.isLog,
lin2log = axis.lin2log;
@@ -10212,12 +10423,17 @@
return axis.translate(threshold, 0, 1, 0, 1);
},
/**
- * Compute auto alignment for the axis label based on which side the axis is on
- * and the given rotation for the label
+ * Compute auto alignment for the axis label based on which side the axis is
+ * on and the given rotation for the label.
+ *
+ * @param {Number} rotation
+ * The rotation in degrees as set by either the `rotation` or
+ * `autoRotation` options.
+ * @private
*/
autoLabelAlign: function(rotation) {
var ret,
angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360;
@@ -10253,13 +10469,14 @@
/**
* Return the size of the labels
*/
labelMetrics: function() {
+ var index = this.tickPositions && this.tickPositions[0] || 0;
return this.chart.renderer.fontMetrics(
this.options.labels.style && this.options.labels.style.fontSize,
- this.ticks[0] && this.ticks[0].label
+ this.ticks[index] && this.ticks[index].label
);
},
/**
* Prevent the ticks from getting so close we can't draw the labels. On a horizontal
@@ -10523,12 +10740,16 @@
axis.axisTitle[display ? 'show' : 'hide'](true);
},
/**
* Generates a tick for initial positioning.
- * @param {number} pos - The tick position in axis values.
- * @param {number} i - The index of the tick in axis.tickPositions.
+ *
+ * @private
+ * @param {number} pos
+ * The tick position in axis values.
+ * @param {number} i
+ * The index of the tick in {@link Axis.tickPositions}.
*/
generateTick: function(pos) {
var ticks = this.ticks;
if (!ticks[pos]) {
@@ -10548,11 +10769,11 @@
options = axis.options,
tickPositions = axis.tickPositions,
ticks = axis.ticks,
horiz = axis.horiz,
side = axis.side,
- invertedSide = chart.inverted ? [1, 0, 3, 2][side] : side,
+ invertedSide = chart.inverted && !axis.isZAxis ? [1, 0, 3, 2][side] : side,
hasData,
showAxis,
titleOffset = 0,
titleOffsetOption,
titleMargin = 0,
@@ -10681,25 +10902,39 @@
hasData && tickPositions.length && tickSize ?
tickSize[0] + directionFactor * axis.offset :
0 // #4866
);
- // Decide the clipping needed to keep the graph inside the plot area and axis lines
- clip = options.offset ? 0 : Math.floor(axis.axisLine.strokeWidth() / 2) * 2; // #4308, #4371
- clipOffset[invertedSide] = Math.max(clipOffset[invertedSide], clip);
+ // Decide the clipping needed to keep the graph inside the plot area and
+ // axis lines
+ clip = Math.floor(axis.axisLine.strokeWidth() / 2) * 2; // #4308, #4371
+ if (options.offset > 0) {
+ clip -= options.offset * 2;
+ }
+ clipOffset[invertedSide] = Math.max(
+ clipOffset[invertedSide] || clip,
+ clip
+ );
},
/**
- * Get the path for the axis line
+ * Internal function to get the path for the axis line. Extended for polar
+ * charts.
+ *
+ * @param {Number} lineWidth
+ * The line width in pixels.
+ * @return {Array}
+ * The SVG path definition in array form.
*/
getLinePath: function(lineWidth) {
var chart = this.chart,
opposite = this.opposite,
offset = this.offset,
horiz = this.horiz,
lineLeft = this.left + (opposite ? this.width : 0) + offset,
- lineTop = chart.chartHeight - this.bottom - (opposite ? this.height : 0) + offset;
+ lineTop = chart.chartHeight - this.bottom -
+ (opposite ? this.height : 0) + offset;
if (opposite) {
lineWidth *= -1; // crispify the other way - #1480, #1687
}
@@ -10966,15 +11201,18 @@
// Show or hide the line depending on options.showEmpty
axisLine[showAxis ? 'show' : 'hide'](true);
}
if (axisTitle && showAxis) {
-
- axisTitle[axisTitle.isNew ? 'attr' : 'animate'](
- axis.getTitlePosition()
- );
- axisTitle.isNew = false;
+ var titleXy = axis.getTitlePosition();
+ if (isNumber(titleXy.y)) {
+ axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy);
+ axisTitle.isNew = false;
+ } else {
+ axisTitle.attr('y', -9999);
+ axisTitle.isNew = true;
+ }
}
// Stacked totals:
if (stackLabelOptions && stackLabelOptions.enabled) {
axis.renderStackTotals();
@@ -11009,11 +11247,16 @@
// Properties to survive after destroy, needed for Axis.update (#4317,
// #5773, #5881).
keepProps: ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin'],
/**
- * Destroys an Axis instance.
+ * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint
+ * to fully remove the axis.
+ *
+ * @private
+ * @param {Boolean} keepEvents
+ * Whether to preserve events, used internally in Axis.update.
*/
destroy: function(keepEvents) {
var axis = this,
stacks = axis.stacks,
plotLinesAndBands = axis.plotLinesAndBands,
@@ -11062,14 +11305,17 @@
}
});
},
/**
- * Draw the crosshair
- *
- * @param {Object} e The event arguments from the modified pointer event
- * @param {Object} point The Point object
+ * Internal function to draw a crosshair.
+ *
+ * @param {PointerEvent} [e]
+ * The event arguments from the modified pointer event, extended
+ * with `chartX` and `chartY`
+ * @param {Point} [point]
+ * The Point object if the crosshair snaps to points.
*/
drawCrosshair: function(e, point) {
var path,
options = this.crosshair,
@@ -12411,10 +12657,22 @@
// update text
if (tooltip.split) {
this.renderSplit(text, pointOrPoints);
} else {
+
+ // Prevent the tooltip from flowing over the chart box (#6659)
+
+ if (!options.style.width) {
+
+ label.css({
+ width: this.chart.spacingBox.width
+ });
+
+ }
+
+
label.attr({
text: text && text.join ? text.join('') : text
});
// Set the stroke color of the box to reflect the point
@@ -12783,13 +13041,30 @@
this.zoomVert = (zoomY && !inverted) || (zoomX && inverted);
this.hasZoom = zoomX || zoomY;
},
/**
- * Add crossbrowser support for chartX and chartY
- * @param {Object} e The event object in standard browsers
+ * @typedef {Object} PointerEvent
+ * A native browser mouse or touch event, extended with position
+ * information relative to the {@link Chart.container}.
+ * @property {Number} chartX
+ * The X coordinate of the pointer interaction relative to the
+ * chart.
+ * @property {Number} chartY
+ * The Y coordinate of the pointer interaction relative to the
+ * chart.
+ *
*/
+ /**
+ * Add crossbrowser support for chartX and chartY.
+ *
+ * @param {Object} e
+ * The event object in standard browsers.
+ *
+ * @return {PointerEvent}
+ * A browser event with extended properties `chartX` and `chartY`
+ */
normalize: function(e, chartPosition) {
var chartX,
chartY,
ePos;
@@ -12917,68 +13192,97 @@
target = target.parentNode;
}
return point;
},
- getHoverData: function(existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) {
+ getChartCoordinatesFromPoint: function(point, inverted) {
+ var series = point.series,
+ xAxis = series.xAxis,
+ yAxis = series.yAxis;
+
+ if (xAxis && yAxis) {
+ return inverted ? {
+ chartX: xAxis.len + xAxis.pos - point.clientX,
+ chartY: yAxis.len + yAxis.pos - point.plotY
+ } : {
+ chartX: point.clientX + xAxis.pos,
+ chartY: point.plotY + yAxis.pos
+ };
+ }
+ },
+
+ /**
+ * Calculates what is the current hovered point/points and series.
+ *
+ * @private
+ *
+ * @param {undefined|Point} existingHoverPoint
+ * The point currrently beeing hovered.
+ * @param {undefined|Series} existingHoverSeries
+ * The series currently beeing hovered.
+ * @param {Array<.Series>} series
+ * All the series in the chart.
+ * @param {boolean} isDirectTouch
+ * Is the pointer directly hovering the point.
+ * @param {boolean} shared
+ * Whether it is a shared tooltip or not.
+ * @param {object} coordinates
+ * Chart coordinates of the pointer.
+ * @param {number} coordinates.chartX
+ * @param {number} coordinates.chartY
+ *
+ * @return {object}
+ * Object containing resulting hover data.
+ */
+ getHoverData: function(
+ existingHoverPoint,
+ existingHoverSeries,
+ series,
+ isDirectTouch,
+ shared,
+ coordinates
+ ) {
var hoverPoint = existingHoverPoint,
hoverSeries = existingHoverSeries,
- searchSeries,
+ searchSeries = shared ? series : [hoverSeries],
+ useExisting = !!(isDirectTouch && existingHoverPoint),
+ notSticky = hoverSeries && !hoverSeries.stickyTracking,
+ isHoverPoint = function(point, i) {
+ return i === 0;
+ },
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.
- // Handle shared tooltip or cases where a series is not yet hovered
- if (isDirectTouch) {
- if (shared) {
- hoverPoints = [];
- each(series, function(s) {
- // Skip hidden series
- var noSharedTooltip = s.noSharedTooltip && shared,
- directTouch = !shared && s.directTouch,
- kdpointT;
- if (s.visible && !noSharedTooltip && !directTouch && pick(s.options.enableMouseTracking, true)) { // #3821
- kdpointT = s.searchKDTree({
- clientX: hoverPoint.clientX,
- plotY: hoverPoint.plotY
- }, !noSharedTooltip && s.kdDimensions === 1);
- if (kdpointT && kdpointT.series) { // Point.series becomes null when reset and before redraw (#5197)
- hoverPoints.push(kdpointT);
- }
- }
- });
- // If kdTree is not built
- if (hoverPoints.length === 0) {
- hoverPoints = [hoverPoint];
- }
- } else {
- hoverPoints = [hoverPoint];
- }
- // When the hovered series has stickyTracking false.
- } else if (hoverSeries && !hoverSeries.stickyTracking) {
- if (!shared) {
- series = [hoverSeries];
- }
- hoverPoints = this.getKDPoints(series, shared, e);
- hoverPoint = H.find(hoverPoints, function(p) {
+ // If there is a hoverPoint and its series requires direct touch (like
+ // columns, #3899), or we're on a noSharedTooltip series among shared
+ // tooltip series (#4546), use the existing hoverPoint.
+ if (useExisting) {
+ isHoverPoint = function(p) {
+ return p === existingHoverPoint;
+ };
+ } else if (notSticky) {
+ isHoverPoint = function(p) {
return p.series === hoverSeries;
- });
- // When the hoverSeries has stickyTracking or there is no series hovered.
+ };
} else {
- // Avoid series with stickyTracking
+ // Avoid series with stickyTracking false
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);
- }
}
+ hoverPoints = (useExisting && !shared) ?
+ // Non-shared tooltips with directTouch don't use the k-d-tree
+ [existingHoverPoint] :
+ this.getKDPoints(searchSeries, shared, coordinates);
+ hoverPoint = H.find(hoverPoints, isHoverPoint);
+ hoverSeries = hoverPoint && hoverPoint.series;
+
+ // In this case we could only look for the hoverPoint in series with
+ // stickyTracking, but we should still include all series in the shared
+ // tooltip.
+ if (!useExisting && !notSticky && shared) {
+ hoverPoints = this.getKDPoints(series, shared, coordinates);
+ }
// 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;
});
@@ -13000,28 +13304,41 @@
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),
- hoverData = this.getHoverData(hoverPoint, hoverSeries, series, isDirectTouch, shared, e),
+ isDirectTouch = !!p || (
+ (hoverSeries && hoverSeries.directTouch) &&
+ pointer.isDirectTouch
+ ),
+ hoverData = this.getHoverData(
+ hoverPoint,
+ hoverSeries,
+ series,
+ isDirectTouch,
+ shared,
+ e
+ ),
useSharedTooltip,
followPointer,
anchor,
points;
-
// Update variables from hoverData.
hoverPoint = hoverData.hoverPoint;
hoverSeries = hoverData.hoverSeries;
followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer;
- useSharedTooltip = shared && hoverPoint && !hoverPoint.series.noSharedTooltip;
+ useSharedTooltip = (
+ shared &&
+ hoverPoint &&
+ !hoverPoint.series.noSharedTooltip
+ );
points = (useSharedTooltip ?
hoverData.hoverPoints :
(hoverPoint ? [hoverPoint] : [])
);
-
- // Refresh tooltip for kdpoint if new hover point or tooltip was hidden // #3926, #4200
+ // Refresh tooltip for kdpoint if new hover point or tooltip was hidden
+ // #3926, #4200
if (
hoverPoint &&
// !(hoverSeries && hoverSeries.directTouch) &&
(hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))
) {
@@ -13038,17 +13355,15 @@
if (chart.hoverSeries !== hoverSeries) {
hoverSeries.onMouseOver();
}
// If tracking is on series in stead of on each point,
- // fire mouseOver on hover point.
- if (hoverSeries && !hoverSeries.directTouch) { // #4448
- if (chart.hoverPoint) {
- chart.hoverPoint.firePointEvent('mouseOut');
- }
- hoverPoint.firePointEvent('mouseOver');
+ // fire mouseOver on hover point. // #4448
+ if (chart.hoverPoint) {
+ chart.hoverPoint.firePointEvent('mouseOut');
}
+ hoverPoint.firePointEvent('mouseOver');
chart.hoverPoints = points;
chart.hoverPoint = hoverPoint;
// Draw tooltip if necessary
if (tooltip) {
tooltip.refresh(useSharedTooltip ? points : hoverPoint, e);
@@ -13075,26 +13390,31 @@
// Issues related to crosshair #4927, #5269 #5066, #5658
each(chart.axes, function drawAxisCrosshair(axis) {
var snap = pick(axis.crosshair.snap, true);
if (!snap) {
axis.drawCrosshair(e);
- // axis has snapping crosshairs, and one of the hover points is belongs to axis
+
+ // Axis has snapping crosshairs, and one of the hover points belongs
+ // to axis
} else if (H.find(points, function(p) {
return p.series[axis.coll] === axis;
})) {
axis.drawCrosshair(e, hoverPoint);
- // axis has snapping crosshairs, but no hover point is not belonging to axis
+ // Axis has snapping crosshairs, but no hover point belongs to axis
} else {
axis.hideCrosshair();
}
});
},
/**
- * Reset the tracking by hiding the tooltip, the hover series state and the hover point
+ * Reset the tracking by hiding the tooltip, the hover series state and the
+ * hover point
*
- * @param allowMove {Boolean} Instead of destroying the tooltip altogether, allow moving it if possible
+ * @param allowMove {Boolean}
+ * Instead of destroying the tooltip altogether, allow moving it if
+ * possible
*/
reset: function(allowMove, delay) {
var pointer = this,
chart = pointer.chart,
hoverSeries = chart.hoverSeries,
@@ -13462,11 +13782,11 @@
},
onTrackerMouseOut: function(e) {
var series = this.chart.hoverSeries,
relatedTarget = e.relatedTarget || e.toElement;
-
+ this.isDirectTouch = false;
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
)
@@ -13971,17 +14291,17 @@
proceed.call(this);
});
}
}(Highcharts));
- (function(H) {
+ (function(Highcharts) {
/**
* (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
- var Legend,
+ var H = Highcharts,
addEvent = H.addEvent,
css = H.css,
discardElement = H.discardElement,
defined = H.defined,
@@ -13992,19 +14312,23 @@
pick = H.pick,
setAnimation = H.setAnimation,
stableSort = H.stableSort,
win = H.win,
wrap = H.wrap;
+
/**
- * The overview of the chart's series.
+ * The overview of the chart's series. The legend object is instanciated
+ * internally in the chart constructor, and available from `chart.legend`. Each
+ * chart has only one legend.
+ *
* @class
*/
- Legend = H.Legend = function(chart, options) {
+ Highcharts.Legend = function(chart, options) {
this.init(chart, options);
};
- Legend.prototype = {
+ Highcharts.Legend.prototype = {
/**
* Initialize the legend
*/
init: function(chart, options) {
@@ -14044,14 +14368,19 @@
this.pages = [];
},
/**
- * Update the legend with new options. Equivalent to running chart.update
+ * 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.
+ * @param {LegendOptions} options
+ * Legend options.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart.
+ *
+ * @sample highcharts/legend/legend-update/
+ * Legend update
*/
update: function(options, redraw) {
var chart = this.chart;
this.setOptions(merge(true, this.options, options));
@@ -14311,10 +14640,13 @@
item,
seriesOptions = series.options,
showCheckbox = legend.createCheckboxForItem &&
seriesOptions &&
seriesOptions.showCheckbox,
+ // full width minus text width
+ itemExtraWidth = symbolWidth + symbolPadding + itemDistance +
+ (showCheckbox ? 20 : 0),
useHTML = options.useHTML,
fontSize = 12,
itemClassName = item.options.className;
if (!li) { // generate it once, later move it
@@ -14379,21 +14711,32 @@
}
// Colorize the items
legend.colorizeItem(item, item.visible);
+ // Take care of max width and text overflow (#6659)
+
+ if (!itemStyle.width) {
+
+ li.css({
+ width: (options.itemWidth || chart.spacingBox.width) -
+ itemExtraWidth
+ });
+
+ }
+
+
// Always update the text
legend.setText(item);
// calculate the positions for the next line
bBox = li.getBBox();
itemWidth = item.checkboxOffset =
options.itemWidth ||
item.legendItemWidth ||
- symbolWidth + symbolPadding + bBox.width + itemDistance +
- (showCheckbox ? 20 : 0);
+ bBox.width + itemExtraWidth;
legend.itemHeight = itemHeight = Math.round(
item.legendItemHeight || bBox.height || legend.symbolHeight
);
// If the item exceeds the width, start a new line
@@ -15009,11 +15352,11 @@
// 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.
if (/Trident\/7\.0/.test(win.navigator.userAgent) || isFirefox) {
- wrap(Legend.prototype, 'positionItem', function(proceed, item) {
+ wrap(Highcharts.Legend.prototype, 'positionItem', function(proceed, item) {
var legend = this,
// If chart destroyed in sync, this is undefined (#2030)
runPositionItem = function() {
if (item._legendItemPos) {
proceed.call(legend, item);
@@ -15221,10 +15564,34 @@
* @memberof Highcharts.Chart
* @name series
* @type {Array.<Highcharts.Series>}
*/
this.series = [];
+
+ /**
+ * The chart title. The title has an `update` method that allows
+ * modifying the options directly or indirectly via `chart.update`.
+ *
+ * @memberof Highcharts.Chart
+ * @name title
+ * @type Object
+ *
+ * @sample highcharts/members/title-update/
+ * Updating titles
+ */
+
+ /**
+ * The chart subtitle. The subtitle has an `update` method that allows
+ * modifying the options directly or indirectly via `chart.update`.
+ *
+ * @memberof Highcharts.Chart
+ * @name subtitle
+ * @type Object
+ */
+
+
+
this.hasCartesianSeries = optionsChart.showAxes;
//this.axisOffset = undefined;
//this.inverted = undefined;
//this.loadingShown = undefined;
//this.container = undefined;
@@ -15620,15 +15987,22 @@
return serie.selected;
});
},
/**
- * Show the title and subtitle of the chart
+ * Set a new title or subtitle for the chart.
*
- * @param titleOptions {Object} New title options
- * @param subtitleOptions {Object} New subtitle options
+ * @param titleOptions {TitleOptions}
+ * New title options.
+ * @param subtitleOptions {SubtitleOptions}
+ * New subtitle options.
+ * @param redraw {Boolean}
+ * Whether to redraw the chart or wait for a later call to
+ * `chart.redraw()`.
*
+ * @sample highcharts/members/chart-settitle/ Set title text and styles
+ *
*/
setTitle: function(titleOptions, subtitleOptions, redraw) {
var chart = this,
options = chart.options,
chartTitleOptions,
@@ -15797,24 +16171,29 @@
* size is retrieved, reset them. Used on first render and on redraws.
*
* @param {Boolean} revert - Revert to the saved original styles.
*/
temporaryDisplay: function(revert) {
- var node = this.renderTo;
+ var node = this.renderTo,
+ tempStyle;
if (!revert) {
while (node && node.style) {
if (getStyle(node, 'display', false) === 'none') {
node.hcOrigStyle = {
display: node.style.display,
height: node.style.height,
overflow: node.style.overflow
};
- H.css(node, {
+ tempStyle = {
display: 'block',
- height: 0,
overflow: 'hidden'
- });
+ };
+ if (node !== this.renderTo) {
+ tempStyle.height = 0;
+ }
+
+ H.css(node, tempStyle);
if (node.style.setProperty) { // #2631
node.style.setProperty('display', 'block', 'important');
}
}
node = node.parentNode;
@@ -16121,10 +16500,12 @@
*
* @sample highcharts/members/chart-setsize-button/
* Test resizing from buttons
* @sample highcharts/members/chart-setsize-jquery-resizable/
* Add a jQuery UI resizable
+ * @sample stock/members/chart-setsize/
+ * Highstock with UI resizable
*/
setSize: function(width, height, animation) {
var chart = this,
renderer = chart.renderer,
globalAnimation;
@@ -16206,10 +16587,15 @@
plotTop,
plotWidth,
plotHeight,
plotBorderWidth;
+ function clipOffsetSide(side) {
+ var offset = clipOffset[side] || 0;
+ return Math.max(plotBorderWidth || offset, offset) / 2;
+ }
+
chart.plotLeft = plotLeft = Math.round(chart.plotLeft);
chart.plotTop = plotTop = Math.round(chart.plotTop);
chart.plotWidth = plotWidth = Math.max(
0,
Math.round(chartWidth - plotLeft - chart.marginRight)
@@ -16237,25 +16623,25 @@
width: plotWidth,
height: plotHeight
};
plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2);
- clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2);
- clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2);
+ clipX = Math.ceil(clipOffsetSide(3));
+ clipY = Math.ceil(clipOffsetSide(0));
chart.clipBox = {
x: clipX,
y: clipY,
width: Math.floor(
chart.plotSizeX -
- Math.max(plotBorderWidth, clipOffset[1]) / 2 -
+ clipOffsetSide(1) -
clipX
),
height: Math.max(
0,
Math.floor(
chart.plotSizeY -
- Math.max(plotBorderWidth, clipOffset[2]) / 2 -
+ clipOffsetSide(2) -
clipY
)
)
};
@@ -16291,11 +16677,11 @@
// chart.marginRight, chart.marginBottom.
each(marginNames, function(m, side) {
chart[m] = pick(chart.margin[side], chart.spacing[side]);
});
chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left
- chart.clipOffset = [0, 0, 0, 0];
+ chart.clipOffset = [];
},
/**
* Draw the borders and backgrounds for chart and plot area
*/
@@ -16700,11 +17086,14 @@
/**
* Remove the chart and purge memory. This method is called internally
* before adding a second chart into the same container, as well as on
* window unload to prevent leaks.
*
- * @sample highcharts/members/chart-destroy/ Destroy the chart from a button
+ * @sample highcharts/members/chart-destroy/
+ * Destroy the chart from a button
+ * @sample stock/members/chart-destroy/
+ * Destroy with Highstock
*/
destroy: function() {
var chart = this,
axes = chart.axes,
series = chart.series,
@@ -16880,17 +17269,18 @@
}
}); // end Chart
}(Highcharts));
- (function(H) {
+ (function(Highcharts) {
/**
* (c) 2010-2017 Torstein Honsi
*
* License: www.highcharts.com/license
*/
var Point,
+ H = Highcharts,
each = H.each,
extend = H.extend,
erase = H.erase,
fireEvent = H.fireEvent,
@@ -16899,22 +17289,23 @@
isNumber = H.isNumber,
pick = H.pick,
removeEvent = H.removeEvent;
/**
- * The Point object. The point objects are generated from the series.data
+ * The Point object. The point objects are generated from the `series.data`
* configuration objects or raw numbers. They can be accessed from the
- * Series.points array.
- * @constructor Point
+ * `Series.points` array. Other ways to instaniate points are through {@link
+ * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
+ *
+ * @class
*/
- Point = H.Point = function() {};
- Point.prototype = {
+ Highcharts.Point = Point = function() {};
+ Highcharts.Point.prototype = {
+
/**
* Initialize the point. Called internally based on the series.data option.
- * @function #init
- * @memberOf Point
* @param {Object} series The series object containing this point.
* @param {Object} options The data in either number, array or object
* format.
* @param {Number} x Optionally, the X value of the.
* @returns {Object} The Point instance.
@@ -16924,12 +17315,26 @@
var point = this,
colors,
colorCount = series.chart.options.chart.colorCount,
colorIndex;
+ /**
+ * The series object associated with the point.
+ *
+ * @name series
+ * @memberof Highcharts.Point
+ * @type Highcharts.Series
+ */
point.series = series;
+
+ /**
+ * The point's current color.
+ * @name color
+ * @memberof Highcharts.Point
+ * @type {Color}
+ */
point.color = series.color; // #3445
point.applyOptions(options, x);
if (series.options.colorByPoint) {
@@ -16954,12 +17359,10 @@
},
/**
* Apply the options containing the x and y data and possible some extra
* properties. Called on point init or from point.update.
*
- * @function #applyOptions
- * @memberOf Point
* @param {Object} options The point options as defined in series.data.
* @param {Number} x Optionally, the X value.
* @returns {Object} The Point instance.
*/
applyOptions: function(options, x) {
@@ -17226,13 +17629,64 @@
};
}
fireEvent(this, eventType, eventArgs, defaultFunction);
},
+
+ /**
+ * For certain series types, like pie charts, where individual points can
+ * be shown or hidden.
+ *
+ * @name visible
+ * @memberOf Highcharts.Point
+ * @type {Boolean}
+ */
visible: true
};
+ /**
+ * For categorized axes this property holds the category name for the
+ * point. For other axes it holds the X value.
+ *
+ * @name category
+ * @memberOf Highcharts.Point
+ * @type {String|Number}
+ */
+
+ /**
+ * The percentage for points in a stacked series or pies.
+ *
+ * @name percentage
+ * @memberOf Highcharts.Point
+ * @type {Number}
+ */
+
+ /**
+ * The total of values in either a stack for stacked series, or a pie in a pie
+ * series.
+ *
+ * @name total
+ * @memberOf Highcharts.Point
+ * @type {Number}
+ */
+
+ /**
+ * The x value of the point.
+ *
+ * @name x
+ * @memberOf Highcharts.Point
+ * @type {Number}
+ */
+
+ /**
+ * The y value of the point.
+ *
+ * @name y
+ * @memberOf Highcharts.Point
+ * @type {Number}
+ */
+
}(Highcharts));
(function(H) {
/**
* (c) 2010-2017 Torstein Honsi
*
@@ -17265,32 +17719,55 @@
SVGElement = H.SVGElement,
syncTimeout = H.syncTimeout,
win = H.win;
/**
- * The base function which all other series types inherit from. The data in the
- * series is stored in various arrays.
+ * This is the base series prototype that all other series types inherit from.
+ * A new series is initiated either through the {@link https://api.highcharts.com/highcharts/series|
+ * series} option structure, or after the chart is initiated, through {@link
+ * Highcharts.Chart#addSeries}.
*
- * - First, series.options.data contains all the original config options for
- * each point whether added by options or methods like series.addPoint.
- * - Next, series.data contains those values converted to points, but in case
- * the series data length exceeds the cropThreshold, or if the data is grouped,
- * series.data doesn't contain all the points. It only contains the points that
+ * The object can be accessed in a number of ways. All series and point event
+ * handlers give a reference to the `series` object. The chart object has a
+ * {@link Highcharts.Chart.series|series} property that is a collection of all
+ * the chart's series. The point objects and axis objects also have the same
+ * reference.
+ *
+ * Another way to reference the series programmatically is by `id`. Add an id
+ * in the series configuration options, and get the series object by {@link
+ * Highcharts.Chart#get}.
+ *
+ * Configuration options for the series are given in three levels. Options for
+ * all series in a chart are given in the {@link https://api.highcharts.com/highcharts/plotOptions.series|
+ * plotOptions.series} object. Then options for all series of a specific type
+ * are given in the plotOptions of that type, for example `plotOptions.line`.
+ * Next, options for one single series are given in the series array, or as
+ * arguements to `chart.addSeries`.
+ *
+ * The data in the series is stored in various arrays.
+ *
+ * - First, `series.options.data` contains all the original config options for
+ * each point whether added by options or methods like `series.addPoint`.
+ * - Next, `series.data` contains those values converted to points, but in case
+ * the series data length exceeds the `cropThreshold`, or if the data is grouped,
+ * `series.data` doesn't contain all the points. It only contains the points that
* have been created on demand.
- * - Then there's series.points that contains all currently visible point
+ * - Then there's `series.points` that contains all currently visible point
* objects. In case of cropping, the cropped-away points are not part of this
- * array. The series.points array starts at series.cropStart compared to
- * series.data and series.options.data. If however the series data is grouped,
+ * array. The `series.points` array starts at `series.cropStart` compared to
+ * `series.data` and `series.options.data`. If however the series data is grouped,
* these can't be correlated one to one.
- * - series.xData and series.processedXData contain clean x values, equivalent
- * to series.data and series.points.
- * - series.yData and series.processedYData contain clean y values, equivalent
- * to series.data and series.points.
+ * - `series.xData` and `series.processedXData` contain clean x values, equivalent
+ * to `series.data` and `series.points`.
+ * - `series.yData` and `series.processedYData` contain clean y values, equivalent
+ * to `series.data` and `series.points`.
*
- * @constructor Series
- * @param {Object} chart - The chart instance.
- * @param {Object} options - The series options.
+ * @class Highcharts.Series
+ * @param {Highcharts.Chart} chart
+ * The chart instance.
+ * @param {Object} options
+ * The series options.
*/
H.Series = H.seriesType('line', null, { // base series options
//cursor: 'default',
//dashStyle: null,
@@ -17407,11 +17884,11 @@
//}
turboThreshold: 1000,
// zIndex: null
findNearestPointBy: 'x'
- }, /** @lends Series.prototype */ {
+ }, /** @lends Highcharts.Series.prototype */ {
isCartesian: true,
pointClass: Point,
sorted: true, // requires the data to be sorted
requireSorting: true,
directTouch: false,
@@ -17424,22 +17901,73 @@
var series = this,
events,
chartSeries = chart.series,
lastSeries;
+ /**
+ * Read only. The chart that the series belongs to.
+ *
+ * @name chart
+ * @memberOf Series
+ * @type {Chart}
+ */
series.chart = chart;
+
+ /**
+ * Read only. The series' type, like "line", "area", "column" etc. The
+ * type in the series options anc can be altered using {@link
+ * Series#update}.
+ *
+ * @name type
+ * @memberOf Series
+ * @type String
+ */
+
+ /**
+ * Read only. The series' current options. To update, use {@link
+ * Series#update}.
+ *
+ * @name options
+ * @memberOf Series
+ * @type SeriesOptions
+ */
series.options = options = series.setOptions(options);
series.linkedSeries = [];
// bind the axes
series.bindAxes();
// set some variables
extend(series, {
+ /**
+ * The series name as given in the options. Defaults to
+ * "Series {n}".
+ *
+ * @name name
+ * @memberOf Series
+ * @type {String}
+ */
name: options.name,
state: '',
+ /**
+ * Read only. The series' visibility state as set by {@link
+ * Series#show}, {@link Series#hide}, or in the initial
+ * configuration.
+ *
+ * @name visible
+ * @memberOf Series
+ * @type {Boolean}
+ */
visible: options.visible !== false, // true by default
+ /**
+ * Read only. The series' selected state as set by {@link
+ * Highcharts.Series#select}.
+ *
+ * @name selected
+ * @memberOf Series
+ * @type {Boolean}
+ */
selected: options.selected === true // false by default
});
// register event listeners
events = options.events;
@@ -17555,10 +18083,26 @@
// register this series in the axis.series lookup
series.insert(axis.series);
// set this series.xAxis or series.yAxis reference
+ /**
+ * Read only. The unique xAxis object associated with the
+ * series.
+ *
+ * @name xAxis
+ * @memberOf Series
+ * @type Axis
+ */
+ /**
+ * Read only. The unique yAxis object associated with the
+ * series.
+ *
+ * @name yAxis
+ * @memberOf Series
+ * @type Axis
+ */
series[AXIS] = axis;
// mark dirty for redraw
axis.isDirty = true;
}
@@ -17813,13 +18357,44 @@
},
drawLegendSymbol: LegendSymbolMixin.drawLineMarker,
/**
- * Replace the series data with a new set of data
- * @param {Object} data
- * @param {Object} redraw
+ * Apply a new set of data to the series and optionally redraw it. The new
+ * data array is passed by reference (except in case of `updatePoints`), and
+ * may later be mutated when updating the chart data.
+ *
+ * Note the difference in behaviour when setting the same amount of points,
+ * or a different amount of points, as handled by the `updatePoints`
+ * parameter.
+ *
+ * @param {SeriesDataOptions} data
+ * Takes an array of data in the same format as described under
+ * `series<type>data` for the given series type.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the series is altered. If doing
+ * more operations on the chart, it is a good idea to set redraw to
+ * false and call {@link Chart#redraw} after.
+ * @param {AnimationOptions} [animation]
+ * When the updated data is the same length as the existing data,
+ * points will be updated by default, and animation visualizes how
+ * the points are changed. Set false to disable animation, or a
+ * configuration object to set duration or easing.
+ * @param {Boolean} [updatePoints=true]
+ * When the updated data is the same length as the existing data,
+ * points will be updated instead of replaced. This allows updating
+ * with animation and performs better. In this case, the original
+ * array is not passed by reference. Set false to prevent.
+ *
+ * @sample highcharts/members/series-setdata/
+ * Set new data from a button
+ * @sample highcharts/members/series-setdata-pie/
+ * Set data in a pie
+ * @sample stock/members/series-setdata/
+ * Set new data in Highstock
+ * @sample maps/members/series-setdata/
+ * Set new data in Highmaps
*/
setData: function(data, redraw, animation, updatePoints) {
var series = this,
oldData = series.points,
oldDataLength = (oldData && oldData.length) || 0,
@@ -17928,10 +18503,19 @@
// handling CSV or JSON
if (isString(yData[0])) {
H.error(14, true);
}
+ /**
+ * Read only. An array containing the series' data point objects. To
+ * modify the data, use {@link Highcharts.Series#setData} or {@link
+ * Highcharts.Point#update}.
+ *
+ * @name data
+ * @memberOf Highcharts.Series
+ * @type {Array.<Highcharts.Point>}
+ */
series.data = [];
series.options.data = series.userOptions.data = data;
// destroy old points
i = oldDataLength;
@@ -18167,10 +18751,26 @@
} else {
// splat the y data in case of ohlc data array
point = (new PointClass()).init(
series, [processedXData[i]].concat(splat(processedYData[i]))
);
+
+ /**
+ * Highstock only. If a point object is created by data
+ * grouping, it doesn't reflect actual points in the raw data.
+ * In this case, the `dataGroup` property holds information
+ * that points back to the raw data.
+ *
+ * - `dataGroup.start` is the index of the first raw data point
+ * in the group.
+ * - `dataGroup.length` is the amount of points in the group.
+ *
+ * @name dataGroup
+ * @memberOf Point
+ * @type {Object}
+ *
+ */
point.dataGroup = series.groupMap[i];
}
if (point) { // #6279
point.index = cursor; // For faster access in Point.update
points[i] = point;
@@ -20081,10 +20681,12 @@
* @return {Highcharts.Series}
* The newly created series object.
*
* @sample highcharts/members/chart-addseries/
* Add a series from a button
+ * @sample stock/members/chart-addseries/
+ * Add a series in Highstock
*/
addSeries: function(options, redraw, animation) {
var series,
chart = this;
@@ -20142,12 +20744,25 @@
this.redraw(animation);
}
},
/**
- * Dim the chart and show a loading text or symbol
- * @param {String} str An optional text to show in the loading label instead of the default one
+ * Dim the chart and show a loading text or symbol. Options for the loading
+ * screen are defined in {@link
+ * https://api.highcharts.com/highcharts/loading|the loading options}.
+ *
+ * @param {String} str
+ * An optional text to show in the loading label instead of the
+ * default one. The default text is set in {@link
+ * http://api.highcharts.com/highcharts/lang.loading|lang.loading}.
+ *
+ * @sample highcharts/members/chart-hideloading/
+ * Show and hide loading from a button
+ * @sample highcharts/members/chart-showloading/
+ * Apply different text labels
+ * @sample stock/members/chart-show-hide-loading/
+ * Toggle loading in Highstock
*/
showLoading: function(str) {
var chart = this,
options = chart.options,
loadingDiv = chart.loadingDiv,
@@ -20213,10 +20828,12 @@
* Hide the loading layer.
*
* @see Highcharts.Chart#showLoading
* @sample highcharts/members/chart-hideloading/
* Show and hide loading from a button
+ * @sample stock/members/chart-show-hide-loading/
+ * Toggle loading in Highstock
*/
hideLoading: function() {
var options = this.options,
loadingDiv = this.loadingDiv;
@@ -20255,11 +20872,34 @@
'chart.ignoreHiddenSeries', 'chart.type', 'colors', 'plotOptions',
'tooltip'
],
/**
- * Chart.update function that takes the whole options stucture.
+ * A generic function to update any element of the chart. Elements can be
+ * enabled and disabled, moved, re-styled, re-formatted etc.
+ *
+ * A special case is configuration objects that take arrays, for example
+ * {@link https://api.highcharts.com/highcharts/xAxis|xAxis},
+ * {@link https://api.highcharts.com/highcharts/yAxis|yAxis} or
+ * {@link https://api.highcharts.com/highcharts/series|series}. For these
+ * collections, an `id` option is used to map the new option set to an
+ * existing object. If an existing object of the same id is not found, the
+ * corresponding item is updated. So for example, running `chart.update`
+ * with a series item without an id, will cause the existing chart's series
+ * with the same index in the series array to be updated.
+ *
+ * See also the {@link https://api.highcharts.com/highcharts/responsive|
+ * responsive option set}. Switching between `responsive.rules` basically
+ * runs `chart.update` under the hood.
+ *
+ * @param {Options} options
+ * A configuration object for the new chart options.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart.
+ *
+ * @sample highcharts/members/chart-update/
+ * Update chart geometry
*/
update: function(options, redraw) {
var chart = this,
adders = {
credits: 'addCredits',
@@ -20413,18 +21053,36 @@
});
// extend the Point prototype for dynamic methods
- extend(Point.prototype, /** @lends Point.prototype */ {
+ extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {
/**
- * Point.update with new options (typically x/y data) and optionally redraw the series.
+ * Update point with new options (typically x/y data) and optionally redraw
+ * the series.
*
- * @param {Object} options Point options as defined in the series.data array
- * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
- * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
- * configuration
+ * @param {Object} options
+ * The point options. Point options are handled as described under
+ * the `series<type>.data` item for each series type. For example
+ * for a line series, if options is a single number, the point will
+ * be given that number as the main y value. If it is an array, it
+ * will be interpreted as x and y values respectively. If it is an
+ * object, advanced options are applied.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the point is updated. If doing
+ * more operations on the chart, it is best practice to set
+ * `redraw` to false and call `chart.redraw()` after.
+ * @param {AnimationOptions} [animation=true]
+ * Whether to apply animation, and optionally animation
+ * configuration.
+ *
+ * @sample highcharts/members/point-update-column/
+ * Update column value
+ * @sample highcharts/members/point-update-pie/
+ * Update pie slice
+ * @sample maps/members/point-update/
+ * Update map area value in Highmaps
*/
update: function(options, redraw, animation, runEvent) {
var point = this,
series = point.series,
graphic = point.graphic,
@@ -20492,29 +21150,71 @@
}
},
/**
* Remove a point and optionally redraw the series and if necessary the axes
- * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
- * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
- * configuration
+ * @param {Boolean} redraw
+ * Whether to redraw the chart or wait for an explicit call. When
+ * doing more operations on the chart, for example running
+ * `point.remove()` in a loop, it is best practice to set `redraw`
+ * to false and call `chart.redraw()` after.
+ * @param {AnimationOptions} [animation=false]
+ * Whether to apply animation, and optionally animation
+ * configuration.
+ *
+ * @sample highcharts/plotoptions/series-point-events-remove/
+ * Remove point and confirm
+ * @sample highcharts/members/point-remove/
+ * Remove pie slice
+ * @sample maps/members/point-remove/
+ * Remove selected points in Highmaps
*/
remove: function(redraw, animation) {
this.series.removePoint(inArray(this, this.series.data), redraw, animation);
}
});
// Extend the series prototype for dynamic methods
extend(Series.prototype, /** @lends Series.prototype */ {
/**
- * Add a point dynamically after chart load time
- * @param {Object} options Point options as given in series.data
- * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
- * @param {Boolean} shift If shift is true, a point is shifted off the start
- * of the series as one is appended to the end.
- * @param {Boolean|AnimationOptions} animation Whether to apply animation, and optionally animation
- * configuration
+ * Add a point to the series after render time. The point can be added at
+ * the end, or by giving it an X value, to the start or in the middle of the
+ * series.
+ *
+ * @param {Number|Array|Object} options
+ * The point options. If options is a single number, a point with
+ * that y value is appended to the series.If it is an array, it will
+ * be interpreted as x and y values respectively. If it is an
+ * object, advanced options as outlined under `series.data` are
+ * applied.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the point is added. When adding
+ * more than one point, it is highly recommended that the redraw
+ * option be set to false, and instead {@link Chart#redraw}
+ * is explicitly called after the adding of points is finished.
+ * Otherwise, the chart will redraw after adding each point.
+ * @param {Boolean} [shift=false]
+ * If true, a point is shifted off the start of the series as one is
+ * appended to the end.
+ * @param {AnimationOptions} [animation]
+ * Whether to apply animation, and optionally animation
+ * configuration.
+ *
+ * @sample highcharts/members/series-addpoint-append/
+ * Append point
+ * @sample highcharts/members/series-addpoint-append-and-shift/
+ * Append and shift
+ * @sample highcharts/members/series-addpoint-x-and-y/
+ * Both X and Y values given
+ * @sample highcharts/members/series-addpoint-pie/
+ * Append pie slice
+ * @sample stock/members/series-addpoint/
+ * Append 100 points in Highstock
+ * @sample stock/members/series-addpoint-shift/
+ * Append and shift in Highstock
+ * @sample maps/members/series-addpoint/
+ * Add a point in Highmaps
*/
addPoint: function(options, redraw, shift, animation) {
var series = this,
seriesOptions = series.options,
data = series.data,
@@ -20586,11 +21286,28 @@
chart.redraw(animation); // Animation is set anyway on redraw, #5665
}
},
/**
- * Remove a point (rendered or not), by index
+ * Remove a point from the series. Unlike the {@link Highcharts.Point#remove}
+ * method, this can also be done on a point that is not instanciated because
+ * it is outside the view or subject to Highstock data grouping.
+ *
+ * @param {Number} i
+ * The index of the point in the {@link Highcharts.Series.data|data}
+ * array.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the point is added. When
+ * removing more than one point, it is highly recommended that the
+ * `redraw` option be set to `false`, and instead {@link
+ * Highcharts.Chart#redraw} is explicitly called after the adding of
+ * points is finished.
+ * @param {AnimationOptions} [animation]
+ * Whether and optionally how the series should be animated.
+ *
+ * @sample highcharts/members/series-removepoint/
+ * Remove cropped point
*/
removePoint: function(i, redraw, animation) {
var series = this,
data = series.data,
@@ -20630,15 +21347,23 @@
remove();
}
},
/**
- * Remove a series and optionally redraw the chart
+ * Remove a series and optionally redraw the chart.
*
- * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
- * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
- * configuration
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart or wait for an explicit call to
+ * {@link Highcharts.Chart#redraw}.
+ * @param {AnimationOptions} [animation]
+ * Whether to apply animation, and optionally animation
+ * configuration
+ * @param {Boolean} [withEvent=true]
+ * Used internally, whether to fire the series `remove` event.
+ *
+ * @sample highcharts/members/series-remove/
+ * Remove first series from a button
*/
remove: function(redraw, animation, withEvent) {
var series = this,
chart = series.chart;
@@ -20663,11 +21388,28 @@
remove();
}
},
/**
- * Series.update with a new set of options
+ * Update the series with a new set of options. For a clean and precise
+ * handling of new options, all methods and elements from the series are
+ * removed, and it is initiated from scratch. Therefore, this method is more
+ * performance expensive than some other utility methods like {@link
+ * Series#setData} or {@link Series#setVisible}.
+ *
+ * @param {SeriesOptions} options
+ * New options that will be merged with the series' existing
+ * options.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the series is altered. If doing
+ * more operations on the chart, it is a good idea to set redraw to
+ * false and call {@link Chart#redraw} after.
+ *
+ * @sample highcharts/members/series-update/
+ * Updating series options
+ * @sample maps/members/series-update/
+ * Update series options in Highmaps
*/
update: function(newOptions, redraw) {
var series = this,
chart = series.chart,
// must use user options when changing type because series.options
@@ -20677,10 +21419,18 @@
newType = newOptions.type || oldOptions.type || chart.options.chart.type,
proto = seriesTypes[oldType].prototype,
preserve = ['group', 'markerGroup', 'dataLabelsGroup'],
n;
+ // Running Series.update to update the data only is an intuitive usage,
+ // so we want to make sure that when used like this, we run the
+ // cheaper setData function and allow animation instead of completely
+ // recreating the series instance.
+ if (Object.keys && Object.keys(newOptions).toString() === 'data') {
+ return this.setData(newOptions.data, redraw);
+ }
+
// If we're changing type or zIndex, create new groups (#3380, #3404)
if ((newType && newType !== oldType) || newOptions.zIndex !== undefined) {
preserve.length = 0;
}
@@ -21439,12 +22189,19 @@
} else {
each(series.chart.series, function(otherSeries) {
var otherOptions = otherSeries.options,
otherYAxis = otherSeries.yAxis,
columnIndex;
- if (otherSeries.type === series.type && otherSeries.visible &&
- yAxis.len === otherYAxis.len && yAxis.pos === otherYAxis.pos) { // #642, #2086
+ if (
+ otherSeries.type === series.type &&
+ (
+ otherSeries.visible ||
+ !series.chart.options.chart.ignoreHiddenSeries
+ ) &&
+ yAxis.len === otherYAxis.len &&
+ yAxis.pos === otherYAxis.pos
+ ) { // #642, #2086
if (otherOptions.stacking) {
stackKey = otherSeries.stackKey;
if (stackGroups[stackKey] === undefined) {
stackGroups[stackKey] = columnCount++;
}
@@ -22541,11 +23298,11 @@
pointOptions,
generalOptions,
hasRendered = series.hasRendered || 0,
str,
dataLabelsGroup,
- defer = pick(options.defer, true),
+ defer = pick(options.defer, !!seriesOptions.animation),
renderer = series.chart.renderer;
if (options.enabled || series._hasPointLabels) {
// Process default alignment of data labels for columns
@@ -23053,45 +23810,43 @@
labelPos.x = x;
labelPos.y = y;
// Detect overflowing data labels
- if (series.options.size === null) {
- dataLabelWidth = dataLabel.getBBox().width;
+ dataLabelWidth = dataLabel.getBBox().width;
- sideOverflow = null;
- // Overflow left
- if (x - dataLabelWidth < connectorPadding) {
- sideOverflow = Math.round(
- dataLabelWidth - x + connectorPadding
- );
- overflow[3] = Math.max(sideOverflow, overflow[3]);
+ sideOverflow = null;
+ // Overflow left
+ if (x - dataLabelWidth < connectorPadding) {
+ sideOverflow = Math.round(
+ dataLabelWidth - x + connectorPadding
+ );
+ overflow[3] = Math.max(sideOverflow, overflow[3]);
- // Overflow right
- } else if (x + dataLabelWidth > plotWidth - connectorPadding) {
- sideOverflow = Math.round(
- x + dataLabelWidth - plotWidth + connectorPadding
- );
- overflow[1] = Math.max(sideOverflow, overflow[1]);
- }
+ // Overflow right
+ } else if (x + dataLabelWidth > plotWidth - connectorPadding) {
+ sideOverflow = Math.round(
+ x + dataLabelWidth - plotWidth + connectorPadding
+ );
+ overflow[1] = Math.max(sideOverflow, overflow[1]);
+ }
- // Overflow top
- if (y - labelHeight / 2 < 0) {
- overflow[0] = Math.max(
- Math.round(-y + labelHeight / 2),
- overflow[0]
- );
+ // Overflow top
+ if (y - labelHeight / 2 < 0) {
+ overflow[0] = Math.max(
+ Math.round(-y + labelHeight / 2),
+ overflow[0]
+ );
- // Overflow left
- } else if (y + labelHeight / 2 > plotHeight) {
- overflow[2] = Math.max(
- Math.round(y + labelHeight / 2 - plotHeight),
- overflow[2]
- );
- }
- dataLabel.sideOverflow = sideOverflow;
+ // Overflow left
+ } else if (y + labelHeight / 2 > plotHeight) {
+ overflow[2] = Math.max(
+ Math.round(y + labelHeight / 2 - plotHeight),
+ overflow[2]
+ );
}
+ dataLabel.sideOverflow = sideOverflow;
} // for each point
}); // for each half
// Do not apply the final placement and draw the connectors until we have verified
// that labels are not spilling over.
@@ -23217,51 +23972,66 @@
var center = this.center,
options = this.options,
centerOption = options.center,
minSize = options.minSize || 80,
newSize = minSize,
- ret;
+ // If a size is set, return true and don't try to shrink the pie
+ // to fit the labels.
+ ret = options.size !== null;
- // Handle horizontal size and center
- if (centerOption[0] !== null) { // Fixed center
- newSize = Math.max(center[2] - Math.max(overflow[1], overflow[3]), minSize);
+ if (!ret) {
+ // Handle horizontal size and center
+ if (centerOption[0] !== null) { // Fixed center
+ newSize = Math.max(center[2] -
+ Math.max(overflow[1], overflow[3]), minSize);
- } else { // Auto center
- newSize = Math.max(
- center[2] - overflow[1] - overflow[3], // horizontal overflow
- minSize
- );
- center[0] += (overflow[3] - overflow[1]) / 2; // horizontal center
- }
+ } else { // Auto center
+ newSize = Math.max(
+ // horizontal overflow
+ center[2] - overflow[1] - overflow[3],
+ minSize
+ );
+ // horizontal center
+ center[0] += (overflow[3] - overflow[1]) / 2;
+ }
- // Handle vertical size and center
- if (centerOption[1] !== null) { // Fixed center
- newSize = Math.max(Math.min(newSize, center[2] - Math.max(overflow[0], overflow[2])), minSize);
+ // Handle vertical size and center
+ if (centerOption[1] !== null) { // Fixed center
+ newSize = Math.max(Math.min(newSize, center[2] -
+ Math.max(overflow[0], overflow[2])), minSize);
- } else { // Auto center
- newSize = Math.max(
- Math.min(
- newSize,
- center[2] - overflow[0] - overflow[2] // vertical overflow
- ),
- minSize
- );
- center[1] += (overflow[0] - overflow[2]) / 2; // vertical center
- }
+ } else { // Auto center
+ newSize = Math.max(
+ Math.min(
+ newSize,
+ // vertical overflow
+ center[2] - overflow[0] - overflow[2]
+ ),
+ minSize
+ );
+ // vertical center
+ center[1] += (overflow[0] - overflow[2]) / 2;
+ }
- // If the size must be decreased, we need to run translate and drawDataLabels again
- if (newSize < center[2]) {
- center[2] = newSize;
- center[3] = Math.min(relativeLength(options.innerSize || 0, newSize), newSize); // #3632
- this.translate(center);
+ // If the size must be decreased, we need to run translate and
+ // drawDataLabels again
+ if (newSize < center[2]) {
+ center[2] = newSize;
+ center[3] = Math.min( // #3632
+ relativeLength(options.innerSize || 0, newSize),
+ newSize
+ );
+ this.translate(center);
- if (this.drawDataLabels) {
- this.drawDataLabels();
+ if (this.drawDataLabels) {
+ this.drawDataLabels();
+ }
+ // Else, return true to indicate that the pie and its labels is
+ // within the plot area
+ } else {
+ ret = true;
}
- // Else, return true to indicate that the pie and its labels is within the plot area
- } else {
- ret = true;
}
return ret;
};
}
@@ -23548,13 +24318,13 @@
var series = this,
chart = series.chart,
pointer = chart.pointer,
onMouseOver = function(e) {
var point = pointer.getPointFromEvent(e);
-
// undefined on graph in scatterchart
if (point !== undefined) {
+ pointer.isDirectTouch = true;
point.onMouseOver(e);
}
};
// Add reference to the point
@@ -23982,16 +24752,32 @@
});
/*
* Extend the Point object with interaction
*/
- extend(Point.prototype, /** @lends Point.prototype */ {
+ extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {
/**
- * Toggle the selection status of a point
- * @param {Boolean} selected Whether to select or unselect the point.
- * @param {Boolean} accumulate Whether to add to the previous selection. By default,
- * this happens if the control key (Cmd on Mac) was pressed during clicking.
+ * Toggle the selection status of a point.
+ * @param {Boolean} [selected]
+ * When `true`, the point is selected. When `false`, the point is
+ * unselected. When `null` or `undefined`, the selection state is
+ * toggled.
+ * @param {Boolean} [accumulate=false]
+ * When `true`, the selection is added to other selected points.
+ * When `false`, other selected points are deselected. Internally in
+ * Highcharts, when {@link http://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect|allowPointSelect}
+ * is `true`, selected points are accumulated on Control, Shift or
+ * Cmd clicking the point.
+ *
+ * @see Highcharts.Chart#getSelectedPoints
+ *
+ * @sample highcharts/members/point-select/
+ * Select a point from a button
+ * @sample highcharts/chart/events-selection-points/
+ * Select a range of points through a drag selection
+ * @sample maps/series/data-id/
+ * Select a point in Highmaps
*/
select: function(selected, accumulate) {
var point = this,
series = point.series,
chart = series.chart;
@@ -24000,10 +24786,18 @@
// fire the event with the default handler
point.firePointEvent(selected ? 'select' : 'unselect', {
accumulate: accumulate
}, function() {
+
+ /**
+ * Whether the point is selected or not.
+ * @see Highcharts.Point#select
+ * @memberof Highcharts.Point
+ * @name selected
+ * @type {Boolean}
+ */
point.selected = point.options.selected = selected;
series.options.data[inArray(point, series.data)] = point.options;
point.setState(selected && 'select');
@@ -24029,11 +24823,14 @@
onMouseOver: function(e) {
var point = this,
series = point.series,
chart = series.chart,
pointer = chart.pointer;
- point.firePointEvent('mouseOver');
+ e = e ?
+ pointer.normalize(e) :
+ // In cases where onMouseOver is called directly without an event
+ pointer.getChartCoordinatesFromPoint(point, chart.inverted);
pointer.runPointActions(e, point);
},
/**
* Runs on mouse out from the point
@@ -24201,12 +24998,12 @@
// Show me your halo
haloOptions = stateOptions.halo;
if (haloOptions && haloOptions.size) {
if (!halo) {
series.halo = halo = chart.renderer.path()
- // #5818, #5903
- .add(hasMarkers ? series.markerGroup : series.group);
+ // #5818, #5903, #6705
+ .add((point.graphic || stateMarkerGraphic).parentGroup);
}
halo[move ? 'animate' : 'attr']({
d: point.haloPath(haloOptions.size)
});
halo.attr({
@@ -24253,11 +25050,11 @@
/*
* Extend the Series object with interaction
*/
- extend(Series.prototype, /** @lends Series.prototype */ {
+ extend(Series.prototype, /** @lends Highcharts.Series.prototype */ {
/**
* Series mouse over handler
*/
onMouseOver: function() {
var series = this,
@@ -24381,14 +25178,19 @@
}
},
/**
- * Set the visibility of the graph
+ * Show or hide the series.
*
- * @param vis {Boolean} True to show the series, false to hide. If undefined,
- * the visibility is toggled.
+ * @param {Boolean} [visible]
+ * True to show the series, false to hide. If undefined, the
+ * visibility is toggled.
+ * @param {Boolean} [redraw=true]
+ * Whether to redraw the chart after the series is altered. If doing
+ * more operations on the chart, it is a good idea to set redraw to
+ * false and call {@link Chart#redraw|chart.redraw()} after.
*/
setVisible: function(vis, redraw) {
var series = this,
chart = series.chart,
legendItem = series.legendItem,
@@ -24444,33 +25246,51 @@
fireEvent(series, showOrHide);
},
/**
- * Show the graph
+ * Show the series if hidden.
+ *
+ * @sample highcharts/members/series-hide/
+ * Toggle visibility from a button
*/
show: function() {
this.setVisible(true);
},
/**
- * Hide the graph
+ * Hide the series if visible. If the {@link
+ * https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries|
+ * chart.ignoreHiddenSeries} option is true, the chart is redrawn without
+ * this series.
+ *
+ * @sample highcharts/members/series-hide/
+ * Toggle visibility from a button
*/
hide: function() {
this.setVisible(false);
},
/**
- * Set the selected state of the graph
+ * Select or unselect the series. This means its {@link
+ * Highcharts.Series.selected|selected} property is set, the checkbox in the
+ * legend is toggled and when selected, the series is returned by the
+ * {@link Highcharts.Chart#getSelectedSeries} function.
*
- * @param selected {Boolean} True to select the series, false to unselect. If
- * undefined, the selection state is toggled.
+ * @param {Boolean} [selected]
+ * True to select the series, false to unselect. If undefined, the
+ * selection state is toggled.
+ *
+ * @sample highcharts/members/series-select/
+ * Select a series from a button
*/
select: function(selected) {
var series = this;
- // if called without an argument, toggle
- series.selected = selected = (selected === undefined) ? !series.selected : selected;
+
+ series.selected = selected = (selected === undefined) ?
+ !series.selected :
+ selected;
if (series.checkbox) {
series.checkbox.checked = selected;
}