123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /**
- * @license Highcharts JS v9.1.1 (2021-06-04)
- *
- * Support for parallel coordinates in Highcharts
- *
- * (c) 2010-2021 Pawel Fus
- *
- * License: www.highcharts.com/license
- */
- 'use strict';
- (function (factory) {
- if (typeof module === 'object' && module.exports) {
- factory['default'] = factory;
- module.exports = factory;
- } else if (typeof define === 'function' && define.amd) {
- define('highcharts/modules/parallel-coordinates', ['highcharts'], function (Highcharts) {
- factory(Highcharts);
- factory.Highcharts = Highcharts;
- return factory;
- });
- } else {
- factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
- }
- }(function (Highcharts) {
- var _modules = Highcharts ? Highcharts._modules : {};
- function _registerModule(obj, path, args, fn) {
- if (!obj.hasOwnProperty(path)) {
- obj[path] = fn.apply(null, args);
- }
- }
- _registerModule(_modules, 'Extensions/ParallelCoordinates.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/FormatUtilities.js'], _modules['Core/Globals.js'], _modules['Core/DefaultOptions.js'], _modules['Core/Series/Series.js'], _modules['Core/Utilities.js']], function (Axis, Chart, F, H, D, Series, U) {
- /* *
- *
- * Parallel coordinates module
- *
- * (c) 2010-2021 Pawel Fus
- *
- * License: www.highcharts.com/license
- *
- * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
- *
- * */
- var format = F.format;
- var setOptions = D.setOptions;
- var addEvent = U.addEvent,
- arrayMax = U.arrayMax,
- arrayMin = U.arrayMin,
- defined = U.defined,
- erase = U.erase,
- extend = U.extend,
- merge = U.merge,
- pick = U.pick,
- splat = U.splat,
- wrap = U.wrap;
- /* *
- *
- * Constants
- *
- * */
- // Extensions for parallel coordinates plot.
- var ChartProto = Chart.prototype;
- var defaultXAxisOptions = {
- lineWidth: 0,
- tickLength: 0,
- opposite: true,
- type: 'category'
- };
- /* eslint-disable valid-jsdoc */
- /**
- * @optionparent chart
- */
- var defaultParallelOptions = {
- /**
- * Flag to render charts as a parallel coordinates plot. In a parallel
- * coordinates plot (||-coords) by default all required yAxes are generated
- * and the legend is disabled. This feature requires
- * `modules/parallel-coordinates.js`.
- *
- * @sample {highcharts} /highcharts/demo/parallel-coordinates/
- * Parallel coordinates demo
- * @sample {highcharts} highcharts/parallel-coordinates/polar/
- * Star plot,
- multivariate data in a polar chart
- *
- * @since 6.0.0
- * @product highcharts
- * @requires modules/parallel-coordinates
- */
- parallelCoordinates: false,
- /**
- * Common options for all yAxes rendered in a parallel coordinates plot.
- * This feature requires `modules/parallel-coordinates.js`.
- *
- * The default options are:
- * ```js
- * parallelAxes: {
- * lineWidth: 1, // classic mode only
- * gridlinesWidth: 0, // classic mode only
- * title: {
- * text: '',
- * reserveSpace: false
- * },
- * labels: {
- * x: 0,
- * y: 0,
- * align: 'center',
- * reserveSpace: false
- * },
- * offset: 0
- * }
- * ```
- *
- * @sample {highcharts} highcharts/parallel-coordinates/parallelaxes/
- * Set the same tickAmount for all yAxes
- *
- * @extends yAxis
- * @since 6.0.0
- * @product highcharts
- * @excluding alternateGridColor,
- breaks,
- id,
- gridLineColor,
- * gridLineDashStyle,
- gridLineWidth,
- minorGridLineColor,
- * minorGridLineDashStyle,
- minorGridLineWidth,
- plotBands,
- * plotLines,
- angle,
- gridLineInterpolation,
- maxColor,
- maxZoom,
- * minColor,
- scrollbar,
- stackLabels,
- stops
- * @requires modules/parallel-coordinates
- */
- parallelAxes: {
- lineWidth: 1,
- /**
- * Titles for yAxes are taken from
- * [xAxis.categories](#xAxis.categories). All options for `xAxis.labels`
- * applies to parallel coordinates titles. For example,
- to style
- * categories,
- use [xAxis.labels.style](#xAxis.labels.style).
- *
- * @excluding align,
- enabled,
- margin,
- offset,
- position3d,
- reserveSpace,
- * rotation,
- skew3d,
- style,
- text,
- useHTML,
- x,
- y
- */
- title: {
- text: '',
- reserveSpace: false
- },
- labels: {
- x: 0,
- y: 4,
- align: 'center',
- reserveSpace: false
- },
- offset: 0
- }
- };
- setOptions({
- chart: defaultParallelOptions
- });
- /* eslint-disable no-invalid-this */
- // Initialize parallelCoordinates
- addEvent(Chart, 'init', function (e) {
- var options = e.args[0],
- defaultYAxis = splat(options.yAxis || {}),
- newYAxes = [];
- var yAxisLength = defaultYAxis.length;
- /**
- * Flag used in parallel coordinates plot to check if chart has ||-coords
- * (parallel coords).
- *
- * @requires module:modules/parallel-coordinates
- *
- * @name Highcharts.Chart#hasParallelCoordinates
- * @type {boolean}
- */
- this.hasParallelCoordinates = options.chart &&
- options.chart.parallelCoordinates;
- if (this.hasParallelCoordinates) {
- this.setParallelInfo(options);
- // Push empty yAxes in case user did not define them:
- for (; yAxisLength <= this.parallelInfo.counter; yAxisLength++) {
- newYAxes.push({});
- }
- if (!options.legend) {
- options.legend = {};
- }
- if (typeof options.legend.enabled === 'undefined') {
- options.legend.enabled = false;
- }
- merge(true, options,
- // Disable boost
- {
- boost: {
- seriesThreshold: Number.MAX_VALUE
- },
- plotOptions: {
- series: {
- boostThreshold: Number.MAX_VALUE
- }
- }
- });
- options.yAxis = defaultYAxis.concat(newYAxes);
- options.xAxis = merge(defaultXAxisOptions, // docs
- splat(options.xAxis || {})[0]);
- }
- });
- // Initialize parallelCoordinates
- addEvent(Chart, 'update', function (e) {
- var options = e.options;
- if (options.chart) {
- if (defined(options.chart.parallelCoordinates)) {
- this.hasParallelCoordinates = options.chart.parallelCoordinates;
- }
- this.options.chart.parallelAxes = merge(this.options.chart.parallelAxes, options.chart.parallelAxes);
- }
- if (this.hasParallelCoordinates) {
- // (#10081)
- if (options.series) {
- this.setParallelInfo(options);
- }
- this.yAxis.forEach(function (axis) {
- axis.update({}, false);
- });
- }
- });
- /* eslint-disable valid-jsdoc */
- extend(ChartProto, /** @lends Highcharts.Chart.prototype */ {
- /**
- * Define how many parellel axes we have according to the longest dataset.
- * This is quite heavy - loop over all series and check series.data.length
- * Consider:
- *
- * - make this an option, so user needs to set this to get better
- * performance
- *
- * - check only first series for number of points and assume the rest is the
- * same
- *
- * @private
- * @function Highcharts.Chart#setParallelInfo
- * @param {Highcharts.Options} options
- * User options
- * @return {void}
- * @requires modules/parallel-coordinates
- */
- setParallelInfo: function (options) {
- var chart = this,
- seriesOptions = options.series;
- chart.parallelInfo = {
- counter: 0
- };
- seriesOptions.forEach(function (series) {
- if (series.data) {
- chart.parallelInfo.counter = Math.max(chart.parallelInfo.counter, series.data.length - 1);
- }
- });
- }
- });
- // Bind each series to each yAxis. yAxis needs a reference to all series to
- // calculate extremes.
- addEvent(Series, 'bindAxes', function (e) {
- if (this.chart.hasParallelCoordinates) {
- var series_1 = this;
- this.chart.axes.forEach(function (axis) {
- series_1.insert(axis.series);
- axis.isDirty = true;
- });
- series_1.xAxis = this.chart.xAxis[0];
- series_1.yAxis = this.chart.yAxis[0];
- e.preventDefault();
- }
- });
- // Translate each point using corresponding yAxis.
- addEvent(Series, 'afterTranslate', function () {
- var series = this,
- chart = this.chart,
- points = series.points,
- dataLength = points && points.length,
- closestPointRangePx = Number.MAX_VALUE,
- lastPlotX,
- point,
- i;
- if (this.chart.hasParallelCoordinates) {
- for (i = 0; i < dataLength; i++) {
- point = points[i];
- if (defined(point.y)) {
- if (chart.polar) {
- point.plotX = chart.yAxis[i].angleRad || 0;
- }
- else if (chart.inverted) {
- point.plotX = (chart.plotHeight -
- chart.yAxis[i].top +
- chart.plotTop);
- }
- else {
- point.plotX = chart.yAxis[i].left - chart.plotLeft;
- }
- point.clientX = point.plotX;
- point.plotY = chart.yAxis[i]
- .translate(point.y, false, true, null, true);
- if (typeof lastPlotX !== 'undefined') {
- closestPointRangePx = Math.min(closestPointRangePx, Math.abs(point.plotX - lastPlotX));
- }
- lastPlotX = point.plotX;
- point.isInside = chart.isInsidePlot(point.plotX, point.plotY, { inverted: chart.inverted });
- }
- else {
- point.isNull = true;
- }
- }
- this.closestPointRangePx = closestPointRangePx;
- }
- }, { order: 1 });
- // On destroy, we need to remove series from each axis.series
- addEvent(Series, 'destroy', function () {
- if (this.chart.hasParallelCoordinates) {
- (this.chart.axes || []).forEach(function (axis) {
- if (axis && axis.series) {
- erase(axis.series, this);
- axis.isDirty = axis.forceRedraw = true;
- }
- }, this);
- }
- });
- /**
- * @private
- */
- function addFormattedValue(proceed) {
- var chart = this.series && this.series.chart,
- config = proceed.apply(this,
- Array.prototype.slice.call(arguments, 1)),
- formattedValue,
- yAxisOptions,
- labelFormat,
- yAxis;
- if (chart &&
- chart.hasParallelCoordinates &&
- !defined(config.formattedValue)) {
- yAxis = chart.yAxis[this.x];
- yAxisOptions = yAxis.options;
- labelFormat = pick(
- /**
- * Parallel coordinates only. Format that will be used for point.y
- * and available in [tooltip.pointFormat](#tooltip.pointFormat) as
- * `{point.formattedValue}`. If not set, `{point.formattedValue}`
- * will use other options, in this order:
- *
- * 1. [yAxis.labels.format](#yAxis.labels.format) will be used if
- * set
- *
- * 2. If yAxis is a category, then category name will be displayed
- *
- * 3. If yAxis is a datetime, then value will use the same format as
- * yAxis labels
- *
- * 4. If yAxis is linear/logarithmic type, then simple value will be
- * used
- *
- * @sample {highcharts}
- * /highcharts/parallel-coordinates/tooltipvalueformat/
- * Different tooltipValueFormats's
- *
- * @type {string}
- * @default undefined
- * @since 6.0.0
- * @product highcharts
- * @requires modules/parallel-coordinates
- * @apioption yAxis.tooltipValueFormat
- */
- yAxisOptions.tooltipValueFormat, yAxisOptions.labels.format);
- if (labelFormat) {
- formattedValue = format(labelFormat, extend(this, { value: this.y }), chart);
- }
- else if (yAxis.dateTime) {
- formattedValue = chart.time.dateFormat(chart.time.resolveDTLFormat(yAxisOptions.dateTimeLabelFormats[yAxis.tickPositions.info.unitName]).main, this.y);
- }
- else if (yAxisOptions.categories) {
- formattedValue = yAxisOptions.categories[this.y];
- }
- else {
- formattedValue = this.y;
- }
- config.formattedValue = config.point.formattedValue = formattedValue;
- }
- return config;
- }
- ['line', 'spline'].forEach(function (seriesName) {
- wrap(H.seriesTypes[seriesName].prototype.pointClass.prototype, 'getLabelConfig', addFormattedValue);
- });
- /**
- * Support for parallel axes.
- * @private
- * @class
- */
- var ParallelAxisAdditions = /** @class */ (function () {
- /* *
- *
- * Constructors
- *
- * */
- function ParallelAxisAdditions(axis) {
- this.axis = axis;
- }
- /* *
- *
- * Functions
- *
- * */
- /**
- * Set predefined left+width and top+height (inverted) for yAxes.
- * This method modifies options param.
- *
- * @private
- *
- * @param {Array<string>} axisPosition
- * ['left', 'width', 'height', 'top'] or ['top', 'height', 'width', 'left']
- * for an inverted chart.
- *
- * @param {Highcharts.AxisOptions} options
- * Axis options.
- */
- ParallelAxisAdditions.prototype.setPosition = function (axisPosition, options) {
- var parallel = this,
- axis = parallel.axis,
- chart = axis.chart,
- fraction = ((parallel.position || 0) + 0.5) / (chart.parallelInfo.counter + 1);
- if (chart.polar) {
- options.angle = 360 * fraction;
- }
- else {
- options[axisPosition[0]] = 100 * fraction + '%';
- axis[axisPosition[1]] = options[axisPosition[1]] = 0;
- // In case of chart.update(inverted), remove old options:
- axis[axisPosition[2]] = options[axisPosition[2]] = null;
- axis[axisPosition[3]] = options[axisPosition[3]] = null;
- }
- };
- return ParallelAxisAdditions;
- }());
- /**
- * Axis with parallel support.
- * @private
- */
- var ParallelAxis;
- (function (ParallelAxis) {
- /**
- * Adds support for parallel axes.
- * @private
- */
- function compose(AxisClass) {
- /* eslint-disable no-invalid-this */
- // On update, keep parallel additions.
- AxisClass.keepProps.push('parallel');
- addEvent(AxisClass, 'init', onInit);
- addEvent(AxisClass, 'afterSetOptions', onAfterSetOptions);
- addEvent(AxisClass, 'getSeriesExtremes', onGetSeriesExtremes);
- }
- ParallelAxis.compose = compose;
- /**
- * Update default options with predefined for a parallel coords.
- * @private
- */
- function onAfterSetOptions(e) {
- var axis = this,
- chart = axis.chart,
- parallelCoordinates = axis.parallelCoordinates;
- var axisPosition = ['left', 'width', 'height', 'top'];
- if (chart.hasParallelCoordinates) {
- if (chart.inverted) {
- axisPosition = axisPosition.reverse();
- }
- if (axis.isXAxis) {
- axis.options = merge(axis.options, defaultXAxisOptions, e.userOptions);
- }
- else {
- var axisIndex = chart.yAxis.indexOf(axis); // #13608
- axis.options = merge(axis.options,
- axis.chart.options.chart.parallelAxes,
- e.userOptions);
- parallelCoordinates.position = pick(parallelCoordinates.position, axisIndex >= 0 ? axisIndex : chart.yAxis.length);
- parallelCoordinates.setPosition(axisPosition, axis.options);
- }
- }
- }
- /**
- * Each axis should gather extremes from points on a particular position in
- * series.data. Not like the default one, which gathers extremes from all
- * series bind to this axis. Consider using series.points instead of
- * series.yData.
- * @private
- */
- function onGetSeriesExtremes(e) {
- var axis = this;
- var chart = axis.chart;
- var parallelCoordinates = axis.parallelCoordinates;
- if (!parallelCoordinates) {
- return;
- }
- if (chart && chart.hasParallelCoordinates && !axis.isXAxis) {
- var index_1 = parallelCoordinates.position,
- currentPoints_1 = [];
- axis.series.forEach(function (series) {
- if (series.visible &&
- defined(series.yData[index_1])) {
- // We need to use push() beacause of null points
- currentPoints_1.push(series.yData[index_1]);
- }
- });
- axis.dataMin = arrayMin(currentPoints_1);
- axis.dataMax = arrayMax(currentPoints_1);
- e.preventDefault();
- }
- }
- /**
- * Add parallel addition
- * @private
- */
- function onInit() {
- var axis = this;
- if (!axis.parallelCoordinates) {
- axis.parallelCoordinates = new ParallelAxisAdditions(axis);
- }
- }
- })(ParallelAxis || (ParallelAxis = {}));
- ParallelAxis.compose(Axis);
- return ParallelAxis;
- });
- _registerModule(_modules, 'masters/modules/parallel-coordinates.src.js', [], function () {
- });
- }));
|