From 6b6f1a4c51a79b4d293f7433a54d5ca743b0921d Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Wed, 23 Oct 2019 02:14:54 +0300 Subject: [PATCH] Implement `dataset.order` (#6268) Allow sorting datasets based on the `order` property --- docs/charts/bar.md | 2 + docs/charts/bubble.md | 10 +- docs/charts/line.md | 2 + docs/charts/mixed.md | 26 +++ docs/charts/polar.md | 1 + docs/charts/radar.md | 3 + docs/charts/scatter.md | 1 + src/controllers/controller.bar.js | 36 ++-- src/controllers/controller.line.js | 24 ++- src/core/core.controller.js | 61 ++++-- src/core/core.interaction.js | 29 ++- src/core/core.scale.js | 13 ++ src/core/core.tooltip.js | 3 + src/plugins/plugin.filler.js | 6 +- src/plugins/plugin.legend.js | 9 +- src/scales/scale.linear.js | 175 +++++++++--------- .../stacking/order-default.json | 42 +++++ .../controller.bar/stacking/order-default.png | Bin 0 -> 3671 bytes .../stacking/order-specified.json | 45 +++++ .../stacking/order-specified.png | Bin 0 -> 3576 bytes .../controller.line/fill/order-default.js | 45 +++++ .../controller.line/fill/order-default.png | Bin 0 -> 12627 bytes test/fixtures/controller.line/fill/order.js | 45 +++++ test/fixtures/controller.line/fill/order.png | Bin 0 -> 11272 bytes .../controller.line/stacking/order-default.js | 45 +++++ .../stacking/order-default.png | Bin 0 -> 10694 bytes .../stacking/order-specified.js | 47 +++++ .../stacking/order-specified.png | Bin 0 -> 10066 bytes test/specs/core.tooltip.tests.js | 159 ++++++++++++++++ test/specs/plugin.legend.tests.js | 75 ++++++++ 30 files changed, 748 insertions(+), 156 deletions(-) create mode 100644 test/fixtures/controller.bar/stacking/order-default.json create mode 100644 test/fixtures/controller.bar/stacking/order-default.png create mode 100644 test/fixtures/controller.bar/stacking/order-specified.json create mode 100644 test/fixtures/controller.bar/stacking/order-specified.png create mode 100644 test/fixtures/controller.line/fill/order-default.js create mode 100644 test/fixtures/controller.line/fill/order-default.png create mode 100644 test/fixtures/controller.line/fill/order.js create mode 100644 test/fixtures/controller.line/fill/order.png create mode 100644 test/fixtures/controller.line/stacking/order-default.js create mode 100644 test/fixtures/controller.line/stacking/order-default.png create mode 100644 test/fixtures/controller.line/stacking/order-specified.js create mode 100644 test/fixtures/controller.line/stacking/order-specified.png diff --git a/docs/charts/bar.md b/docs/charts/bar.md index 328b1df0e..a4e54915a 100644 --- a/docs/charts/bar.md +++ b/docs/charts/bar.md @@ -77,6 +77,7 @@ the color of the bars is generally set this way. | [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined` | [`hoverBorderWidth`](#interactions) | `number` | - | Yes | `1` | [`label`](#general) | `string` | - | - | `''` +| [`order`](#general) | `number` | - | - | `0` | [`xAxisID`](#general) | `string` | - | - | first x axis | [`yAxisID`](#general) | `string` | - | - | first y axis @@ -85,6 +86,7 @@ the color of the bars is generally set this way. | Name | Description | ---- | ---- | `label` | The label for the dataset which appears in the legend and tooltips. +| `order` | The drawing order of dataset. Also affects order for stacking, tooltip, and legend. | `xAxisID` | The ID of the x axis to plot this dataset on. | `yAxisID` | The ID of the y axis to plot this dataset on. diff --git a/docs/charts/bubble.md b/docs/charts/bubble.md index b94c98c17..6536395c2 100644 --- a/docs/charts/bubble.md +++ b/docs/charts/bubble.md @@ -49,14 +49,18 @@ The bubble chart allows a number of properties to be specified for each dataset. | [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `1` | [`hoverRadius`](#interactions) | `number` | Yes | Yes | `4` | [`hitRadius`](#interactions) | `number` | Yes | Yes | `1` -| [`label`](#labeling) | `string` | - | - | `undefined` +| [`label`](#general) | `string` | - | - | `undefined` +| [`order`](#general) | `number` | - | - | `0` | [`pointStyle`](#styling) | `string` | Yes | Yes | `'circle'` | [`rotation`](#styling) | `number` | Yes | Yes | `0` | [`radius`](#styling) | `number` | Yes | Yes | `3` -### Labeling +### General -`label` defines the text associated to the dataset and which appears in the legend and tooltips. +| Name | Description +| ---- | ---- +| `label` | The label for the dataset which appears in the legend and tooltips. +| `order` | The drawing order of dataset. ### Styling diff --git a/docs/charts/line.md b/docs/charts/line.md index bd2a24c98..0ad877301 100644 --- a/docs/charts/line.md +++ b/docs/charts/line.md @@ -54,6 +54,7 @@ The line chart allows a number of properties to be specified for each dataset. T | [`fill`](#line-styling) | boolean|string | Yes | - | `true` | [`label`](#general) | `string` | - | - | `''` | [`lineTension`](#line-styling) | `number` | - | - | `0.4` +| [`order`](#general) | `number` | - | - | `0` | [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` | [`pointBorderColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` | [`pointBorderWidth`](#point-styling) | `number` | Yes | Yes | `1` @@ -76,6 +77,7 @@ The line chart allows a number of properties to be specified for each dataset. T | Name | Description | ---- | ---- | `label` | The label for the dataset which appears in the legend and tooltips. +| `order` | The drawing order of dataset. Also affects order for stacking, tooltip, and legend. | `xAxisID` | The ID of the x axis to plot this dataset on. | `yAxisID` | The ID of the y axis to plot this dataset on. diff --git a/docs/charts/mixed.md b/docs/charts/mixed.md index 9f83f2ea6..5ead1fb34 100644 --- a/docs/charts/mixed.md +++ b/docs/charts/mixed.md @@ -70,3 +70,29 @@ At this point we have a chart rendering how we'd like. It's important to note th } } {% endchartjs %} + +## Drawing order + + By default, datasets are drawn so that first one is top-most. This can be altered by specifying `order` option to datasets. `order` defaults to `0`. + + ```javascript +var mixedChart = new Chart(ctx, { + type: 'bar', + data: { + datasets: [{ + label: 'Bar Dataset', + data: [10, 20, 30, 40], + // this dataset is drawn below + order: 1 + }, { + label: 'Line Dataset', + data: [10, 10, 10, 10], + type: 'line', + // this dataset is drawn on top + order: 2 + }], + labels: ['January', 'February', 'March', 'April'] + }, + options: options +}); +``` diff --git a/docs/charts/polar.md b/docs/charts/polar.md index 8403a3872..84275dd93 100644 --- a/docs/charts/polar.md +++ b/docs/charts/polar.md @@ -70,6 +70,7 @@ All these values, if `undefined`, fallback to the associated [`elements.arc.*`]( ### Border Alignment The following values are supported for `borderAlign`. + * `'center'` (default) * `'inner'` diff --git a/docs/charts/radar.md b/docs/charts/radar.md index e5f3b3137..942425ed8 100644 --- a/docs/charts/radar.md +++ b/docs/charts/radar.md @@ -52,6 +52,7 @@ They are often useful for comparing the points of two or more different data set {% endchartjs %} ## Example Usage + ```javascript var myRadarChart = new Chart(ctx, { type: 'radar', @@ -75,6 +76,7 @@ The radar chart allows a number of properties to be specified for each dataset. | [`borderWidth`](#line-styling) | `number` | Yes | - | `3` | [`fill`](#line-styling) | boolean|string | Yes | - | `true` | [`label`](#general) | `string` | - | - | `''` +| [`order`](#general) | `number` | - | - | `0` | [`lineTension`](#line-styling) | `number` | - | - | `0` | [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` | [`pointBorderColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` @@ -94,6 +96,7 @@ The radar chart allows a number of properties to be specified for each dataset. | Name | Description | ---- | ---- | `label` | The label for the dataset which appears in the legend and tooltips. +| `order` | The drawing order of dataset. ### Point Styling diff --git a/docs/charts/scatter.md b/docs/charts/scatter.md index 0107fd4c2..8fc7726d3 100644 --- a/docs/charts/scatter.md +++ b/docs/charts/scatter.md @@ -32,6 +32,7 @@ var scatterChart = new Chart(ctx, { ``` ## Dataset Properties + The scatter chart supports all of the same properties as the [line chart](./line.md#dataset-properties). ## Data Structure diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index cd07fdbc1..4fa3f4290 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -207,21 +207,27 @@ module.exports = DatasetController.extend({ */ _getStacks: function(last) { var me = this; - var chart = me.chart; var scale = me._getIndexScale(); + var metasets = scale._getMatchingVisibleMetas(me._type); var stacked = scale.options.stacked; - var ilen = last === undefined ? chart.data.datasets.length : last + 1; + var ilen = metasets.length; var stacks = []; var i, meta; for (i = 0; i < ilen; ++i) { - meta = chart.getDatasetMeta(i); - if (meta.bar && chart.isDatasetVisible(i) && - (stacked === false || - (stacked === true && stacks.indexOf(meta.stack) === -1) || - (stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) { + meta = metasets[i]; + // stacked | meta.stack + // | found | not found | undefined + // false | x | x | x + // true | | x | + // undefined | | x | x + if (stacked === false || stacks.indexOf(meta.stack) === -1 || + (stacked === undefined && meta.stack === undefined)) { stacks.push(meta.stack); } + if (meta.index === last) { + break; + } } return stacks; @@ -290,24 +296,26 @@ module.exports = DatasetController.extend({ var scale = me._getValueScale(); var isHorizontal = scale.isHorizontal(); var datasets = chart.data.datasets; + var metasets = scale._getMatchingVisibleMetas(me._type); var value = scale._parseValue(datasets[datasetIndex].data[index]); var minBarLength = scale.options.minBarLength; var stacked = scale.options.stacked; var stack = me.getMeta().stack; var start = value.start === undefined ? 0 : value.max >= 0 && value.min >= 0 ? value.min : value.max; var length = value.start === undefined ? value.end : value.max >= 0 && value.min >= 0 ? value.max - value.min : value.min - value.max; + var ilen = metasets.length; var i, imeta, ivalue, base, head, size, stackLength; if (stacked || (stacked === undefined && stack !== undefined)) { - for (i = 0; i < datasetIndex; ++i) { - imeta = chart.getDatasetMeta(i); + for (i = 0; i < ilen; ++i) { + imeta = metasets[i]; - if (imeta.bar && - imeta.stack === stack && - imeta.controller._getValueScaleId() === scale.id && - chart.isDatasetVisible(i)) { + if (imeta.index === datasetIndex) { + break; + } - stackLength = scale._parseValue(datasets[i].data[index]); + if (imeta.stack === stack) { + stackLength = scale._parseValue(datasets[imeta.index].data[index]); ivalue = stackLength.start === undefined ? stackLength.end : stackLength.min >= 0 && stackLength.max >= 0 ? stackLength.max : stackLength.min; if ((value.min < 0 && ivalue < 0) || (value.max >= 0 && ivalue > 0)) { diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index c2d67549b..dc1fc689b 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -183,14 +183,21 @@ module.exports = DatasetController.extend({ var yScale = me._yScale; var sumPos = 0; var sumNeg = 0; - var i, ds, dsMeta; + var rightValue = +yScale.getRightValue(value); + var metasets = chart._getSortedVisibleDatasetMetas(); + var ilen = metasets.length; + var i, ds, dsMeta, stackedRightValue; if (yScale.options.stacked) { - for (i = 0; i < datasetIndex; i++) { - ds = chart.data.datasets[i]; - dsMeta = chart.getDatasetMeta(i); - if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { - var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); + for (i = 0; i < ilen; ++i) { + dsMeta = metasets[i]; + if (dsMeta.index === datasetIndex) { + break; + } + + ds = chart.data.datasets[dsMeta.index]; + if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id) { + stackedRightValue = +yScale.getRightValue(ds.data[index]); if (stackedRightValue < 0) { sumNeg += stackedRightValue || 0; } else { @@ -199,14 +206,11 @@ module.exports = DatasetController.extend({ } } - var rightValue = Number(yScale.getRightValue(value)); if (rightValue < 0) { return yScale.getPixelForValue(sumNeg + rightValue); } - return yScale.getPixelForValue(sumPos + rightValue); } - - return yScale.getPixelForValue(value); + return yScale.getPixelForValue(sumPos + rightValue); }, updateBezierControlPoints: function() { diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 694e77646..04d86a3d9 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -154,6 +154,14 @@ function positionIsHorizontal(position) { return position === 'top' || position === 'bottom'; } +function compare2Level(l1, l2) { + return function(a, b) { + return a[l1] === b[l1] + ? a[l2] - b[l2] + : a[l1] - b[l1]; + }; +} + var Chart = function(item, config) { this.construct(item, config); return this; @@ -422,6 +430,8 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { meta = me.getDatasetMeta(datasetIndex); } meta.type = type; + meta.order = dataset.order || 0; + meta.index = datasetIndex; if (meta.controller) { meta.controller.updateIndex(datasetIndex); @@ -513,11 +523,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { // Do this before render so that any plugins that need final scale updates can use it plugins.notify(me, 'afterUpdate'); - me._layers.sort(function(a, b) { - return a.z === b.z - ? a._idx - b._idx - : a.z - b.z; - }); + me._layers.sort(compare2Level('z', '_idx')); if (me._bufferedRender) { me._bufferedRequest = { @@ -717,6 +723,33 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { me.tooltip.transition(easingValue); }, + /** + * @private + */ + _getSortedDatasetMetas: function(filterVisible) { + var me = this; + var datasets = me.data.datasets || []; + var result = []; + var i, ilen; + + for (i = 0, ilen = datasets.length; i < ilen; ++i) { + if (!filterVisible || me.isDatasetVisible(i)) { + result.push(me.getDatasetMeta(i)); + } + } + + result.sort(compare2Level('order', 'index')); + + return result; + }, + + /** + * @private + */ + _getSortedVisibleDatasetMetas: function() { + return this._getSortedDatasetMetas(true); + }, + /** * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` * hook, in which case, plugins will not be called on `afterDatasetsDraw`. @@ -724,16 +757,15 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { */ drawDatasets: function(easingValue) { var me = this; + var metasets, i; if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { return; } - // Draw datasets reversed to support proper line stacking - for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) { - if (me.isDatasetVisible(i)) { - me.drawDataset(i, easingValue); - } + metasets = me._getSortedVisibleDatasetMetas(); + for (i = metasets.length - 1; i >= 0; --i) { + me.drawDataset(metasets[i], easingValue); } plugins.notify(me, 'afterDatasetsDraw', [easingValue]); @@ -744,12 +776,11 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { * hook, in which case, plugins will not be called on `afterDatasetDraw`. * @private */ - drawDataset: function(index, easingValue) { + drawDataset: function(meta, easingValue) { var me = this; - var meta = me.getDatasetMeta(index); var args = { meta: meta, - index: index, + index: meta.index, easingValue: easingValue }; @@ -829,7 +860,9 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { controller: null, hidden: null, // See isDatasetVisible() comment xAxisID: null, - yAxisID: null + yAxisID: null, + order: dataset.order || 0, + index: datasetIndex }; } diff --git a/src/core/core.interaction.js b/src/core/core.interaction.js index e163f1182..f5051fbff 100644 --- a/src/core/core.interaction.js +++ b/src/core/core.interaction.js @@ -25,17 +25,13 @@ function getRelativePosition(e, chart) { * @param {function} handler - the callback to execute for each visible item */ function parseVisibleItems(chart, handler) { - var datasets = chart.data.datasets; - var meta, i, j, ilen, jlen; + var metasets = chart._getSortedVisibleDatasetMetas(); + var metadata, i, j, ilen, jlen, element; - for (i = 0, ilen = datasets.length; i < ilen; ++i) { - if (!chart.isDatasetVisible(i)) { - continue; - } - - meta = chart.getDatasetMeta(i); - for (j = 0, jlen = meta.data.length; j < jlen; ++j) { - var element = meta.data[j]; + for (i = 0, ilen = metasets.length; i < ilen; ++i) { + metadata = metasets[i].data; + for (j = 0, jlen = metadata.length; j < jlen; ++j) { + element = metadata[j]; if (!element._view.skip) { handler(element); } @@ -120,15 +116,12 @@ function indexMode(chart, e, options) { return []; } - chart.data.datasets.forEach(function(dataset, datasetIndex) { - if (chart.isDatasetVisible(datasetIndex)) { - var meta = chart.getDatasetMeta(datasetIndex); - var element = meta.data[items[0]._index]; + chart._getSortedVisibleDatasetMetas().forEach(function(meta) { + var element = meta.data[items[0]._index]; - // don't count items that are skipped (null data) - if (element && !element._view.skip) { - elements.push(element); - } + // don't count items that are skipped (null data) + if (element && !element._view.skip) { + elements.push(element); } }); diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 6a5f7bf01..29134180c 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -1416,6 +1416,19 @@ var Scale = Element.extend({ me._drawLabels.apply(me, arguments); } }]; + }, + + /** + * @private + */ + _getMatchingVisibleMetas: function(type) { + var me = this; + var isHorizontal = me.isHorizontal(); + return me.chart._getSortedVisibleDatasetMetas() + .filter(function(meta) { + return (!type || meta.type === type) + && (isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id); + }); } }); diff --git a/src/core/core.tooltip.js b/src/core/core.tooltip.js index 97f7f16df..f42ede285 100644 --- a/src/core/core.tooltip.js +++ b/src/core/core.tooltip.js @@ -995,6 +995,9 @@ var exports = Element.extend({ me._active = []; } else { me._active = me._chart.getElementsAtEventForMode(e, options.mode, options); + if (options.reverse) { + me._active.reverse(); + } } // Remember Last Actives diff --git a/src/plugins/plugin.filler.js b/src/plugins/plugin.filler.js index 8acbc4074..8fed6d905 100644 --- a/src/plugins/plugin.filler.js +++ b/src/plugins/plugin.filler.js @@ -354,12 +354,12 @@ module.exports = { }, beforeDatasetsDraw: function(chart) { - var count = (chart.data.datasets || []).length - 1; + var metasets = chart._getSortedVisibleDatasetMetas(); var ctx = chart.ctx; var meta, i, el, view, points, mapper, color; - for (i = count; i >= 0; --i) { - meta = chart.getDatasetMeta(i).$filler; + for (i = metasets.length - 1; i >= 0; --i) { + meta = metasets[i].$filler; if (!meta || !meta.visible) { continue; diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 78a5efe70..c358ff680 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -49,16 +49,15 @@ defaults._set('global', { // lineJoin : // lineWidth : generateLabels: function(chart) { - var data = chart.data; + var datasets = chart.data.datasets; var options = chart.options.legend || {}; var usePointStyle = options.labels && options.labels.usePointStyle; - return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { - var meta = chart.getDatasetMeta(i); + return chart._getSortedDatasetMetas().map(function(meta, i) { var style = meta.controller.getStyle(usePointStyle ? 0 : undefined); return { - text: dataset.label, + text: datasets[meta.index].label, fillStyle: style.backgroundColor, hidden: !chart.isDatasetVisible(i), lineCap: style.borderCapStyle, @@ -73,7 +72,7 @@ defaults._set('global', { // Below is extra data used for toggling the datasets datasetIndex: i }; - }, this) : []; + }, this); } } }, diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index 004b7d8e6..1c3da726d 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -11,116 +11,113 @@ var defaultConfig = { } }; +var DEFAULT_MIN = 0; +var DEFAULT_MAX = 1; + +function getOrCreateStack(stacks, stacked, meta) { + var key = [ + meta.type, + // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined + stacked === undefined && meta.stack === undefined ? meta.index : '', + meta.stack + ].join('.'); + + if (stacks[key] === undefined) { + stacks[key] = { + pos: [], + neg: [] + }; + } + + return stacks[key]; +} + +function stackData(scale, stacks, meta, data) { + var opts = scale.options; + var stacked = opts.stacked; + var stack = getOrCreateStack(stacks, stacked, meta); + var pos = stack.pos; + var neg = stack.neg; + var ilen = data.length; + var i, value; + + for (i = 0; i < ilen; ++i) { + value = scale._parseValue(data[i]); + if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) { + continue; + } + + pos[i] = pos[i] || 0; + neg[i] = neg[i] || 0; + + if (opts.relativePoints) { + pos[i] = 100; + } else if (value.min < 0 || value.max < 0) { + neg[i] += value.min; + } else { + pos[i] += value.max; + } + } +} + +function updateMinMax(scale, meta, data) { + var ilen = data.length; + var i, value; + + for (i = 0; i < ilen; ++i) { + value = scale._parseValue(data[i]); + if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) { + continue; + } + + scale.min = Math.min(scale.min, value.min); + scale.max = Math.max(scale.max, value.max); + } +} + module.exports = LinearScaleBase.extend({ determineDataLimits: function() { var me = this; var opts = me.options; var chart = me.chart; var datasets = chart.data.datasets; - var isHorizontal = me.isHorizontal(); - var DEFAULT_MIN = 0; - var DEFAULT_MAX = 1; - var datasetIndex, meta, value, data, i, ilen; - - function IDMatches(datasetMeta) { - return isHorizontal ? datasetMeta.xAxisID === me.id : datasetMeta.yAxisID === me.id; - } + var metasets = me._getMatchingVisibleMetas(); + var hasStacks = opts.stacked; + var stacks = {}; + var ilen = metasets.length; + var i, meta, data, values; - // First Calculate the range me.min = Number.POSITIVE_INFINITY; me.max = Number.NEGATIVE_INFINITY; - var hasStacks = opts.stacked; if (hasStacks === undefined) { - for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) { - meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && meta.stack !== undefined) { - hasStacks = true; - break; - } + for (i = 0; !hasStacks && i < ilen; ++i) { + meta = metasets[i]; + hasStacks = meta.stack !== undefined; } } - if (opts.stacked || hasStacks) { - var valuesPerStack = {}; - - for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) { - meta = chart.getDatasetMeta(datasetIndex); - var key = [ - meta.type, - // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined - ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), - meta.stack - ].join('.'); - - if (valuesPerStack[key] === undefined) { - valuesPerStack[key] = { - positiveValues: [], - negativeValues: [] - }; - } - - // Store these per type - var positiveValues = valuesPerStack[key].positiveValues; - var negativeValues = valuesPerStack[key].negativeValues; - - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - data = datasets[datasetIndex].data; - for (i = 0, ilen = data.length; i < ilen; i++) { - value = me._parseValue(data[i]); - - if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) { - continue; - } - - positiveValues[i] = positiveValues[i] || 0; - negativeValues[i] = negativeValues[i] || 0; - - if (value.min === 0 && !opts.ticks.beginAtZero) { - value.min = value.max; - } - - if (opts.relativePoints) { - positiveValues[i] = 100; - } else if (value.min < 0 || value.max < 0) { - negativeValues[i] += value.min; - } else { - positiveValues[i] += value.max; - } - } - } - } - - helpers.each(valuesPerStack, function(valuesForType) { - var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); - me.min = Math.min(me.min, helpers.min(values)); - me.max = Math.max(me.max, helpers.max(values)); - }); - - } else { - for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) { - meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - data = datasets[datasetIndex].data; - for (i = 0, ilen = data.length; i < ilen; i++) { - value = me._parseValue(data[i]); - - if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) { - continue; - } - - me.min = Math.min(value.min, me.min); - me.max = Math.max(value.max, me.max); - } - } + for (i = 0; i < ilen; ++i) { + meta = metasets[i]; + data = datasets[meta.index].data; + if (hasStacks) { + stackData(me, stacks, meta, data); + } else { + updateMinMax(me, meta, data); } } + helpers.each(stacks, function(stackValues) { + values = stackValues.pos.concat(stackValues.neg); + me.min = Math.min(me.min, helpers.min(values)); + me.max = Math.max(me.max, helpers.max(values)); + }); + me.min = helpers.isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN; me.max = helpers.isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX; // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero - this.handleTickRangeOptions(); + me.handleTickRangeOptions(); }, // Returns the maximum number of ticks based on the scale dimension diff --git a/test/fixtures/controller.bar/stacking/order-default.json b/test/fixtures/controller.bar/stacking/order-default.json new file mode 100644 index 000000000..53f25a937 --- /dev/null +++ b/test/fixtures/controller.bar/stacking/order-default.json @@ -0,0 +1,42 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }, { + "backgroundColor": "#36A2EB", + "data": [5, 4, 3, null, 1] + }, { + "backgroundColor": "#FFCE56", + "data": [3, 5, 2, null, 4] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "display": false, + "stacked": true + }], + "yAxes": [{ + "display": false, + "stacked": true, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/stacking/order-default.png b/test/fixtures/controller.bar/stacking/order-default.png new file mode 100644 index 0000000000000000000000000000000000000000..59e10242bb89b7e07baca5387fe506438a7767a9 GIT binary patch literal 3671 zc-rk&ZA?>F7=EsI6s9d@nNcVRWO3Pd*NqOkR6a&n5M#tlH)1Bx5mJ~#RtO4Kq&J3* zsZ)q%0j3o8Wfq;_bW%ZqBHPqZ6vk8v7HBq-vQkRJH>K^)?MnT%WWTnIaR1!rocH5- z-kiMWJx8{0OXRHeiTscSODPc%*P$`xhTve4;e|8K1o8j_*4nE;#z^+ATiUs($@OGQ#^Y zUfSeLEy)r$y^yaqPq>PWN~+ARm{SOaI-M>Fy|q7`c4^$21^{xEv7zFxAyHMzX8Zjd6VenOvSFAPHVx{cazU zMz$9ofz3xfd z??h4Yym;cFB{V(8U>DvG@g_S;F&Df->H^UxSTU`b{wvc}2Q_iOBYDW)6XtSOtA`AU z<@J^Wl}}>pzy=h?EG!z|ZY!T2FP@t3Xt8E=84gXE`pHhB=|Wj;tHz#}*5Vp#KR@f* z_sitL5l4fA%5Ib*_n~TL>fF#xWz=}=q_0-UerX3>W^;-oCiJT;yNd#|i|wbw6tkCR z-e)1{C=o91g~$yf*{i;hhqEjs;@hEZq_kod>Jd)rh(whe2IDar103|SkTk9gvH{2h zEX+Xw7dgS$%EDz&CT+=^T^OBdIh7VjZZfY6w8oXiKVA$3Lp3+q&}Kg!>u@$GOTwHZ zg|Yfc;rjIujXn=W^YpRGWKGHZ*|cuHwdDtMDw(<`1_yD~)}9j8uu#qK@lBtn1ID&M zVXx89VYU*@U{e!uBj-jAB^wo7++gPt8Am+`4?-zBYDhDFNyWViKVP;<1xTQoOa%Co zX+u0e;ovsHL)h>=2;ku)6(?cC?;%`(jWnZR!-=ODn>jGD;meaK1y5pyJ)Z;3gF&9}s?XN4~@Ut)zXF=x8NJtf|9hkHt_a0~a8 jNG6JS`4TzqVvawx@!d^df7W+`+|WpRb6Y}vyzKCwp|D2N literal 0 Hc-jL100001 diff --git a/test/fixtures/controller.bar/stacking/order-specified.json b/test/fixtures/controller.bar/stacking/order-specified.json new file mode 100644 index 000000000..d4f497b02 --- /dev/null +++ b/test/fixtures/controller.bar/stacking/order-specified.json @@ -0,0 +1,45 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5], + "order": 20 + }, { + "backgroundColor": "#36A2EB", + "data": [5, 4, 3, null, 1], + "order": 25 + }, { + "backgroundColor": "#FFCE56", + "data": [3, 5, 2, null, 4], + "order": 10 + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "display": false, + "stacked": true + }], + "yAxes": [{ + "display": false, + "stacked": true, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/stacking/order-specified.png b/test/fixtures/controller.bar/stacking/order-specified.png new file mode 100644 index 0000000000000000000000000000000000000000..b927f337ac9148756ef071f157a06aabd5802e66 GIT binary patch literal 3576 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 G3j03_eGMT1 literal 0 Hc-jL100001 diff --git a/test/fixtures/controller.line/fill/order.js b/test/fixtures/controller.line/fill/order.js new file mode 100644 index 000000000..7d76cf432 --- /dev/null +++ b/test/fixtures/controller.line/fill/order.js @@ -0,0 +1,45 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: [0, 1, 2, 3, 4, 5], + datasets: [ + { + data: [3, 1, 2, 0, 8, 1], + backgroundColor: '#ff0000', + order: 2 + }, + { + data: [0, 4, 2, 6, 4, 8], + backgroundColor: '#00ff00', + order: 1 + } + ] + }, + options: { + legend: false, + title: false, + elements: { + line: { + fill: true + }, + point: { + radius: 0 + } + }, + layout: { + padding: 32 + }, + scales: { + xAxes: [{display: false}], + yAxes: [{display: false}] + } + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.line/fill/order.png b/test/fixtures/controller.line/fill/order.png new file mode 100644 index 0000000000000000000000000000000000000000..6ff1a054fe59285a41978cecb6b9d2327198a3b0 GIT binary patch literal 11272 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 literal 0 Hc-jL100001 diff --git a/test/fixtures/controller.line/stacking/order-default.js b/test/fixtures/controller.line/stacking/order-default.js new file mode 100644 index 000000000..d8b292e95 --- /dev/null +++ b/test/fixtures/controller.line/stacking/order-default.js @@ -0,0 +1,45 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: [0, 1, 2, 3, 4, 5], + datasets: [ + { + // option in dataset + data: [3, 1, 2, 0, 8, 1], + backgroundColor: '#ff0000' + }, + { + // option in element (fallback) + data: [0, 4, 2, 6, 4, 8], + backgroundColor: '#00ff00' + } + ] + }, + options: { + legend: false, + title: false, + elements: { + line: { + fill: true + }, + point: { + radius: 0 + } + }, + layout: { + padding: 32 + }, + scales: { + xAxes: [{stacked: true, display: false}], + yAxes: [{stacked: true, display: false}] + } + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.line/stacking/order-default.png b/test/fixtures/controller.line/stacking/order-default.png new file mode 100644 index 0000000000000000000000000000000000000000..3355da629235094ec460b10b7ca579aaac678661 GIT binary patch literal 10694 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 literal 0 Hc-jL100001 diff --git a/test/specs/core.tooltip.tests.js b/test/specs/core.tooltip.tests.js index 29c449a8b..89898677a 100755 --- a/test/specs/core.tooltip.tests.js +++ b/test/specs/core.tooltip.tests.js @@ -581,6 +581,165 @@ describe('Core.Tooltip', function() { expect(tooltip._view.y).toBeCloseToPixel(155); }); + it('Should allow reversing items', function() { + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + label: 'Dataset 1', + data: [10, 20, 30], + pointHoverBorderColor: 'rgb(255, 0, 0)', + pointHoverBackgroundColor: 'rgb(0, 255, 0)' + }, { + label: 'Dataset 2', + data: [40, 40, 40], + pointHoverBorderColor: 'rgb(0, 0, 255)', + pointHoverBackgroundColor: 'rgb(0, 255, 255)' + }], + labels: ['Point 1', 'Point 2', 'Point 3'] + }, + options: { + tooltips: { + mode: 'label', + reverse: true + } + } + }); + + // Trigger an event over top of the + var meta0 = chart.getDatasetMeta(0); + var point0 = meta0.data[1]; + + var node = chart.canvas; + var rect = node.getBoundingClientRect(); + + var evt = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + clientX: rect.left + point0._model.x, + clientY: rect.top + point0._model.y + }); + + // Manually trigger rather than having an async test + node.dispatchEvent(evt); + + // Check and see if tooltip was displayed + var tooltip = chart.tooltip; + var globalDefaults = Chart.defaults.global; + + expect(tooltip._view).toEqual(jasmine.objectContaining({ + // Positioning + xAlign: 'left', + yAlign: 'center', + + // Text + title: ['Point 2'], + beforeBody: [], + body: [{ + before: [], + lines: ['Dataset 2: 40'], + after: [] + }, { + before: [], + lines: ['Dataset 1: 20'], + after: [] + }], + afterBody: [], + footer: [], + labelColors: [{ + borderColor: globalDefaults.defaultColor, + backgroundColor: globalDefaults.defaultColor + }, { + borderColor: globalDefaults.defaultColor, + backgroundColor: globalDefaults.defaultColor + }] + })); + + expect(tooltip._view.x).toBeCloseToPixel(267); + expect(tooltip._view.y).toBeCloseToPixel(155); + }); + + it('Should follow dataset order', function() { + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + label: 'Dataset 1', + data: [10, 20, 30], + pointHoverBorderColor: 'rgb(255, 0, 0)', + pointHoverBackgroundColor: 'rgb(0, 255, 0)', + order: 10 + }, { + label: 'Dataset 2', + data: [40, 40, 40], + pointHoverBorderColor: 'rgb(0, 0, 255)', + pointHoverBackgroundColor: 'rgb(0, 255, 255)', + order: 5 + }], + labels: ['Point 1', 'Point 2', 'Point 3'] + }, + options: { + tooltips: { + mode: 'label' + } + } + }); + + // Trigger an event over top of the + var meta0 = chart.getDatasetMeta(0); + var point0 = meta0.data[1]; + + var node = chart.canvas; + var rect = node.getBoundingClientRect(); + + var evt = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + clientX: rect.left + point0._model.x, + clientY: rect.top + point0._model.y + }); + + // Manually trigger rather than having an async test + node.dispatchEvent(evt); + + // Check and see if tooltip was displayed + var tooltip = chart.tooltip; + var globalDefaults = Chart.defaults.global; + + expect(tooltip._view).toEqual(jasmine.objectContaining({ + // Positioning + xAlign: 'left', + yAlign: 'center', + + // Text + title: ['Point 2'], + beforeBody: [], + body: [{ + before: [], + lines: ['Dataset 2: 40'], + after: [] + }, { + before: [], + lines: ['Dataset 1: 20'], + after: [] + }], + afterBody: [], + footer: [], + labelColors: [{ + borderColor: globalDefaults.defaultColor, + backgroundColor: globalDefaults.defaultColor + }, { + borderColor: globalDefaults.defaultColor, + backgroundColor: globalDefaults.defaultColor + }] + })); + + expect(tooltip._view.x).toBeCloseToPixel(267); + expect(tooltip._view.y).toBeCloseToPixel(155); + }); + it('should filter items from the tooltip using the callback', function() { var chart = window.acquireChart({ type: 'line', diff --git a/test/specs/plugin.legend.tests.js b/test/specs/plugin.legend.tests.js index 06c8b2cf4..1fd4821bb 100644 --- a/test/specs/plugin.legend.tests.js +++ b/test/specs/plugin.legend.tests.js @@ -163,6 +163,81 @@ describe('Legend block tests', function() { }]); }); + it('should reverse correctly', function() { + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + label: 'dataset1', + backgroundColor: '#f31', + borderCapStyle: 'round', + borderDash: [2, 2], + borderDashOffset: 5.5, + data: [] + }, { + label: 'dataset2', + hidden: true, + borderJoinStyle: 'round', + data: [] + }, { + label: 'dataset3', + borderWidth: 10, + borderColor: 'green', + pointStyle: 'crossRot', + fill: false, + data: [] + }], + labels: [] + }, + options: { + legend: { + reverse: true + } + } + }); + + expect(chart.legend.legendItems).toEqual([{ + text: 'dataset3', + fillStyle: 'rgba(0,0,0,0)', + hidden: false, + lineCap: 'butt', + lineDash: [], + lineDashOffset: 0, + lineJoin: 'miter', + lineWidth: 10, + strokeStyle: 'green', + pointStyle: undefined, + rotation: undefined, + datasetIndex: 2 + }, { + text: 'dataset2', + fillStyle: 'rgba(0,0,0,0.1)', + hidden: true, + lineCap: 'butt', + lineDash: [], + lineDashOffset: 0, + lineJoin: 'round', + lineWidth: 3, + strokeStyle: 'rgba(0,0,0,0.1)', + pointStyle: undefined, + rotation: undefined, + datasetIndex: 1 + }, { + text: 'dataset1', + fillStyle: '#f31', + hidden: false, + lineCap: 'round', + lineDash: [2, 2], + lineDashOffset: 5.5, + lineJoin: 'miter', + lineWidth: 3, + strokeStyle: 'rgba(0,0,0,0.1)', + pointStyle: undefined, + rotation: undefined, + datasetIndex: 0 + }]); + }); + it('should filter items', function() { var chart = window.acquireChart({ type: 'bar', -- 2.47.3