/** * @license Highcharts JS v5.0.3 (2016-11-18) * X-range series * * (c) 2010-2016 Torstein Honsi, Lars A. V. Cabrera * * --- WORK IN PROGRESS --- * * License: www.highcharts.com/license */ (function(factory) { if (typeof module === 'object' && module.exports) { module.exports = factory; } else { factory(Highcharts); } }(function(Highcharts) { (function(H) { /** * (c) 2014-2016 Highsoft AS * Authors: Torstein Honsi, Lars A. V. Cabrera * * License: www.highcharts.com/license */ 'use strict'; var defaultPlotOptions = H.getOptions().plotOptions, color = H.Color, columnType = H.seriesTypes.column, each = H.each, extendClass = H.extendClass, isNumber = H.isNumber, isObject = H.isObject, merge = H.merge, pick = H.pick, seriesTypes = H.seriesTypes, stop = H.stop, wrap = H.wrap, Axis = H.Axis, Point = H.Point, Series = H.Series, pointFormat = '' + '\u25CF' + ' {series.name}: {point.yCategory}
', xrange = 'xrange'; defaultPlotOptions.xrange = merge(defaultPlotOptions.column, { tooltip: { pointFormat: pointFormat } }); seriesTypes.xrange = extendClass(columnType, { pointClass: extendClass(Point, { // Add x2 and yCategory to the available properties for tooltip formats getLabelConfig: function() { var cfg = Point.prototype.getLabelConfig.call(this); cfg.x2 = this.x2; cfg.yCategory = this.yCategory = this.series.yAxis.categories && this.series.yAxis.categories[this.y]; return cfg; } }), type: xrange, forceDL: true, parallelArrays: ['x', 'x2', 'y'], requireSorting: false, animate: seriesTypes.line.prototype.animate, /** * Borrow the column series metrics, but with swapped axes. This gives free access * to features like groupPadding, grouping, pointWidth etc. */ getColumnMetrics: function() { var metrics, chart = this.chart; function swapAxes() { each(chart.series, function(s) { var xAxis = s.xAxis; s.xAxis = s.yAxis; s.yAxis = xAxis; }); } swapAxes(); this.yAxis.closestPointRange = 1; metrics = columnType.prototype.getColumnMetrics.call(this); swapAxes(); return metrics; }, /** * Override cropData to show a point where x is outside visible range * but x2 is outside. */ cropData: function(xData, yData, min, max) { // Replace xData with x2Data to find the appropriate cropStart var cropData = Series.prototype.cropData, crop = cropData.call(this, this.x2Data, yData, min, max); // Re-insert the cropped xData crop.xData = xData.slice(crop.start, crop.end); return crop; }, translate: function() { columnType.prototype.translate.apply(this, arguments); var series = this, xAxis = series.xAxis, metrics = series.columnMetrics, minPointLength = series.options.minPointLength || 0; each(series.points, function(point) { var plotX = point.plotX, posX = pick(point.x2, point.x + (point.len || 0)), plotX2 = xAxis.toPixels(posX, true), width = plotX2 - plotX, widthDifference, shapeArgs, partialFill; if (minPointLength) { widthDifference = minPointLength - width; if (widthDifference < 0) { widthDifference = 0; } plotX -= widthDifference / 2; plotX2 += widthDifference / 2; } plotX = Math.max(plotX, -10); plotX2 = Math.min(Math.max(plotX2, -10), xAxis.len + 10); point.shapeArgs = { x: plotX, y: point.plotY + metrics.offset, width: plotX2 - plotX, height: metrics.width }; point.tooltipPos[0] += width / 2; point.tooltipPos[1] -= metrics.width / 2; // Add a partShapeArgs to the point, based on the shapeArgs property partialFill = point.partialFill; if (partialFill) { // Get the partial fill amount if (isObject(partialFill)) { partialFill = partialFill.amount; } // If it was not a number, assume 0 if (!isNumber(partialFill)) { partialFill = 0; } shapeArgs = point.shapeArgs; point.partShapeArgs = { x: shapeArgs.x, y: shapeArgs.y + 1, width: shapeArgs.width * partialFill, height: shapeArgs.height - 2 }; } }); }, drawPoints: function() { var series = this, chart = this.chart, options = series.options, renderer = chart.renderer, animationLimit = options.animationLimit || 250, verb = chart.pointCount < animationLimit ? 'animate' : 'attr'; // draw the columns each(series.points, function(point) { var plotY = point.plotY, graphic = point.graphic, type = point.shapeType, shapeArgs = point.shapeArgs, partShapeArgs = point.partShapeArgs, seriesOpts = series.options, pfOptions = point.partialFill, fill, state = point.selected && 'select', cutOff = options.stacking && !options.borderRadius; if (isNumber(plotY) && point.y !== null) { if (graphic) { // update stop(graphic); point.graphicOriginal[verb]( merge(shapeArgs) ); if (partShapeArgs) { point.graphicOverlay[verb]( merge(partShapeArgs) ); } } else { point.graphic = graphic = renderer.g('point') .attr({ 'class': point.getClassName() }) .add(point.group || series.group); point.graphicOriginal = renderer[type](shapeArgs) .addClass('highcharts-partfill-original') .add(graphic); if (partShapeArgs) { point.graphicOverlay = renderer[type](partShapeArgs) .addClass('highcharts-partfill-overlay') .add(graphic); } } // Presentational point.graphicOriginal .attr(series.pointAttribs(point, state)) .shadow(options.shadow, null, cutOff); if (partShapeArgs) { // Ensure pfOptions is an object if (!isObject(pfOptions)) { pfOptions = {}; } if (isObject(seriesOpts.partialFill)) { pfOptions = merge(pfOptions, seriesOpts.partialFill); } fill = pfOptions.fill || color(series.color).brighten(-0.3).get('rgb'); point.graphicOverlay .attr(series.pointAttribs(point, state)) .attr('fill', fill) .attr('stroke-width', 0) .shadow(options.shadow, null, cutOff); } } else if (graphic) { point.graphic = graphic.destroy(); // #1269 } }); } }); /** * Max x2 should be considered in xAxis extremes */ wrap(Axis.prototype, 'getSeriesExtremes', function(proceed) { var axis = this, series = axis.series, dataMax, modMax; proceed.call(this); if (axis.isXAxis && series.type === xrange) { dataMax = pick(axis.dataMax, Number.MIN_VALUE); each(this.series, function(series) { each(series.x2Data || [], function(val) { if (val > dataMax) { dataMax = val; modMax = true; } }); }); if (modMax) { axis.dataMax = dataMax; } } }); }(Highcharts)); }));