mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Implement dataset.order (#6268)
Allow sorting datasets based on the `order` property
This commit is contained in:
parent
feaf418d4e
commit
6b6f1a4c51
@ -77,6 +77,7 @@ the color of the bars is generally set this way.
|
|||||||
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined`
|
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined`
|
||||||
| [`hoverBorderWidth`](#interactions) | `number` | - | Yes | `1`
|
| [`hoverBorderWidth`](#interactions) | `number` | - | Yes | `1`
|
||||||
| [`label`](#general) | `string` | - | - | `''`
|
| [`label`](#general) | `string` | - | - | `''`
|
||||||
|
| [`order`](#general) | `number` | - | - | `0`
|
||||||
| [`xAxisID`](#general) | `string` | - | - | first x axis
|
| [`xAxisID`](#general) | `string` | - | - | first x axis
|
||||||
| [`yAxisID`](#general) | `string` | - | - | first y axis
|
| [`yAxisID`](#general) | `string` | - | - | first y axis
|
||||||
|
|
||||||
@ -85,6 +86,7 @@ the color of the bars is generally set this way.
|
|||||||
| Name | Description
|
| Name | Description
|
||||||
| ---- | ----
|
| ---- | ----
|
||||||
| `label` | The label for the dataset which appears in the legend and tooltips.
|
| `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.
|
| `xAxisID` | The ID of the x axis to plot this dataset on.
|
||||||
| `yAxisID` | The ID of the y axis to plot this dataset on.
|
| `yAxisID` | The ID of the y axis to plot this dataset on.
|
||||||
|
|
||||||
|
|||||||
@ -49,14 +49,18 @@ The bubble chart allows a number of properties to be specified for each dataset.
|
|||||||
| [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `1`
|
| [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `1`
|
||||||
| [`hoverRadius`](#interactions) | `number` | Yes | Yes | `4`
|
| [`hoverRadius`](#interactions) | `number` | Yes | Yes | `4`
|
||||||
| [`hitRadius`](#interactions) | `number` | Yes | Yes | `1`
|
| [`hitRadius`](#interactions) | `number` | Yes | Yes | `1`
|
||||||
| [`label`](#labeling) | `string` | - | - | `undefined`
|
| [`label`](#general) | `string` | - | - | `undefined`
|
||||||
|
| [`order`](#general) | `number` | - | - | `0`
|
||||||
| [`pointStyle`](#styling) | `string` | Yes | Yes | `'circle'`
|
| [`pointStyle`](#styling) | `string` | Yes | Yes | `'circle'`
|
||||||
| [`rotation`](#styling) | `number` | Yes | Yes | `0`
|
| [`rotation`](#styling) | `number` | Yes | Yes | `0`
|
||||||
| [`radius`](#styling) | `number` | Yes | Yes | `3`
|
| [`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
|
### Styling
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,7 @@ The line chart allows a number of properties to be specified for each dataset. T
|
|||||||
| [`fill`](#line-styling) | <code>boolean|string</code> | Yes | - | `true`
|
| [`fill`](#line-styling) | <code>boolean|string</code> | Yes | - | `true`
|
||||||
| [`label`](#general) | `string` | - | - | `''`
|
| [`label`](#general) | `string` | - | - | `''`
|
||||||
| [`lineTension`](#line-styling) | `number` | - | - | `0.4`
|
| [`lineTension`](#line-styling) | `number` | - | - | `0.4`
|
||||||
|
| [`order`](#general) | `number` | - | - | `0`
|
||||||
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
|
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
|
||||||
| [`pointBorderColor`](#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`
|
| [`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
|
| Name | Description
|
||||||
| ---- | ----
|
| ---- | ----
|
||||||
| `label` | The label for the dataset which appears in the legend and tooltips.
|
| `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.
|
| `xAxisID` | The ID of the x axis to plot this dataset on.
|
||||||
| `yAxisID` | The ID of the y axis to plot this dataset on.
|
| `yAxisID` | The ID of the y axis to plot this dataset on.
|
||||||
|
|
||||||
|
|||||||
@ -70,3 +70,29 @@ At this point we have a chart rendering how we'd like. It's important to note th
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% endchartjs %}
|
{% 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
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|||||||
@ -70,6 +70,7 @@ All these values, if `undefined`, fallback to the associated [`elements.arc.*`](
|
|||||||
### Border Alignment
|
### Border Alignment
|
||||||
|
|
||||||
The following values are supported for `borderAlign`.
|
The following values are supported for `borderAlign`.
|
||||||
|
|
||||||
* `'center'` (default)
|
* `'center'` (default)
|
||||||
* `'inner'`
|
* `'inner'`
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,7 @@ They are often useful for comparing the points of two or more different data set
|
|||||||
{% endchartjs %}
|
{% endchartjs %}
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var myRadarChart = new Chart(ctx, {
|
var myRadarChart = new Chart(ctx, {
|
||||||
type: 'radar',
|
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`
|
| [`borderWidth`](#line-styling) | `number` | Yes | - | `3`
|
||||||
| [`fill`](#line-styling) | <code>boolean|string</code> | Yes | - | `true`
|
| [`fill`](#line-styling) | <code>boolean|string</code> | Yes | - | `true`
|
||||||
| [`label`](#general) | `string` | - | - | `''`
|
| [`label`](#general) | `string` | - | - | `''`
|
||||||
|
| [`order`](#general) | `number` | - | - | `0`
|
||||||
| [`lineTension`](#line-styling) | `number` | - | - | `0`
|
| [`lineTension`](#line-styling) | `number` | - | - | `0`
|
||||||
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
|
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
|
||||||
| [`pointBorderColor`](#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
|
| Name | Description
|
||||||
| ---- | ----
|
| ---- | ----
|
||||||
| `label` | The label for the dataset which appears in the legend and tooltips.
|
| `label` | The label for the dataset which appears in the legend and tooltips.
|
||||||
|
| `order` | The drawing order of dataset.
|
||||||
|
|
||||||
### Point Styling
|
### Point Styling
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,7 @@ var scatterChart = new Chart(ctx, {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Dataset Properties
|
## Dataset Properties
|
||||||
|
|
||||||
The scatter chart supports all of the same properties as the [line chart](./line.md#dataset-properties).
|
The scatter chart supports all of the same properties as the [line chart](./line.md#dataset-properties).
|
||||||
|
|
||||||
## Data Structure
|
## Data Structure
|
||||||
|
|||||||
@ -207,21 +207,27 @@ module.exports = DatasetController.extend({
|
|||||||
*/
|
*/
|
||||||
_getStacks: function(last) {
|
_getStacks: function(last) {
|
||||||
var me = this;
|
var me = this;
|
||||||
var chart = me.chart;
|
|
||||||
var scale = me._getIndexScale();
|
var scale = me._getIndexScale();
|
||||||
|
var metasets = scale._getMatchingVisibleMetas(me._type);
|
||||||
var stacked = scale.options.stacked;
|
var stacked = scale.options.stacked;
|
||||||
var ilen = last === undefined ? chart.data.datasets.length : last + 1;
|
var ilen = metasets.length;
|
||||||
var stacks = [];
|
var stacks = [];
|
||||||
var i, meta;
|
var i, meta;
|
||||||
|
|
||||||
for (i = 0; i < ilen; ++i) {
|
for (i = 0; i < ilen; ++i) {
|
||||||
meta = chart.getDatasetMeta(i);
|
meta = metasets[i];
|
||||||
if (meta.bar && chart.isDatasetVisible(i) &&
|
// stacked | meta.stack
|
||||||
(stacked === false ||
|
// | found | not found | undefined
|
||||||
(stacked === true && stacks.indexOf(meta.stack) === -1) ||
|
// false | x | x | x
|
||||||
(stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) {
|
// true | | x |
|
||||||
|
// undefined | | x | x
|
||||||
|
if (stacked === false || stacks.indexOf(meta.stack) === -1 ||
|
||||||
|
(stacked === undefined && meta.stack === undefined)) {
|
||||||
stacks.push(meta.stack);
|
stacks.push(meta.stack);
|
||||||
}
|
}
|
||||||
|
if (meta.index === last) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stacks;
|
return stacks;
|
||||||
@ -290,24 +296,26 @@ module.exports = DatasetController.extend({
|
|||||||
var scale = me._getValueScale();
|
var scale = me._getValueScale();
|
||||||
var isHorizontal = scale.isHorizontal();
|
var isHorizontal = scale.isHorizontal();
|
||||||
var datasets = chart.data.datasets;
|
var datasets = chart.data.datasets;
|
||||||
|
var metasets = scale._getMatchingVisibleMetas(me._type);
|
||||||
var value = scale._parseValue(datasets[datasetIndex].data[index]);
|
var value = scale._parseValue(datasets[datasetIndex].data[index]);
|
||||||
var minBarLength = scale.options.minBarLength;
|
var minBarLength = scale.options.minBarLength;
|
||||||
var stacked = scale.options.stacked;
|
var stacked = scale.options.stacked;
|
||||||
var stack = me.getMeta().stack;
|
var stack = me.getMeta().stack;
|
||||||
var start = value.start === undefined ? 0 : value.max >= 0 && value.min >= 0 ? value.min : value.max;
|
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 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;
|
var i, imeta, ivalue, base, head, size, stackLength;
|
||||||
|
|
||||||
if (stacked || (stacked === undefined && stack !== undefined)) {
|
if (stacked || (stacked === undefined && stack !== undefined)) {
|
||||||
for (i = 0; i < datasetIndex; ++i) {
|
for (i = 0; i < ilen; ++i) {
|
||||||
imeta = chart.getDatasetMeta(i);
|
imeta = metasets[i];
|
||||||
|
|
||||||
if (imeta.bar &&
|
if (imeta.index === datasetIndex) {
|
||||||
imeta.stack === stack &&
|
break;
|
||||||
imeta.controller._getValueScaleId() === scale.id &&
|
}
|
||||||
chart.isDatasetVisible(i)) {
|
|
||||||
|
|
||||||
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;
|
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)) {
|
if ((value.min < 0 && ivalue < 0) || (value.max >= 0 && ivalue > 0)) {
|
||||||
|
|||||||
@ -183,14 +183,21 @@ module.exports = DatasetController.extend({
|
|||||||
var yScale = me._yScale;
|
var yScale = me._yScale;
|
||||||
var sumPos = 0;
|
var sumPos = 0;
|
||||||
var sumNeg = 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) {
|
if (yScale.options.stacked) {
|
||||||
for (i = 0; i < datasetIndex; i++) {
|
for (i = 0; i < ilen; ++i) {
|
||||||
ds = chart.data.datasets[i];
|
dsMeta = metasets[i];
|
||||||
dsMeta = chart.getDatasetMeta(i);
|
if (dsMeta.index === datasetIndex) {
|
||||||
if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
|
break;
|
||||||
var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
|
}
|
||||||
|
|
||||||
|
ds = chart.data.datasets[dsMeta.index];
|
||||||
|
if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id) {
|
||||||
|
stackedRightValue = +yScale.getRightValue(ds.data[index]);
|
||||||
if (stackedRightValue < 0) {
|
if (stackedRightValue < 0) {
|
||||||
sumNeg += stackedRightValue || 0;
|
sumNeg += stackedRightValue || 0;
|
||||||
} else {
|
} else {
|
||||||
@ -199,14 +206,11 @@ module.exports = DatasetController.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rightValue = Number(yScale.getRightValue(value));
|
|
||||||
if (rightValue < 0) {
|
if (rightValue < 0) {
|
||||||
return yScale.getPixelForValue(sumNeg + rightValue);
|
return yScale.getPixelForValue(sumNeg + rightValue);
|
||||||
}
|
}
|
||||||
return yScale.getPixelForValue(sumPos + rightValue);
|
|
||||||
}
|
}
|
||||||
|
return yScale.getPixelForValue(sumPos + rightValue);
|
||||||
return yScale.getPixelForValue(value);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateBezierControlPoints: function() {
|
updateBezierControlPoints: function() {
|
||||||
|
|||||||
@ -154,6 +154,14 @@ function positionIsHorizontal(position) {
|
|||||||
return position === 'top' || position === 'bottom';
|
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) {
|
var Chart = function(item, config) {
|
||||||
this.construct(item, config);
|
this.construct(item, config);
|
||||||
return this;
|
return this;
|
||||||
@ -422,6 +430,8 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
|
|||||||
meta = me.getDatasetMeta(datasetIndex);
|
meta = me.getDatasetMeta(datasetIndex);
|
||||||
}
|
}
|
||||||
meta.type = type;
|
meta.type = type;
|
||||||
|
meta.order = dataset.order || 0;
|
||||||
|
meta.index = datasetIndex;
|
||||||
|
|
||||||
if (meta.controller) {
|
if (meta.controller) {
|
||||||
meta.controller.updateIndex(datasetIndex);
|
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
|
// Do this before render so that any plugins that need final scale updates can use it
|
||||||
plugins.notify(me, 'afterUpdate');
|
plugins.notify(me, 'afterUpdate');
|
||||||
|
|
||||||
me._layers.sort(function(a, b) {
|
me._layers.sort(compare2Level('z', '_idx'));
|
||||||
return a.z === b.z
|
|
||||||
? a._idx - b._idx
|
|
||||||
: a.z - b.z;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (me._bufferedRender) {
|
if (me._bufferedRender) {
|
||||||
me._bufferedRequest = {
|
me._bufferedRequest = {
|
||||||
@ -717,6 +723,33 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
|
|||||||
me.tooltip.transition(easingValue);
|
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`
|
* Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`
|
||||||
* hook, in which case, plugins will not be called on `afterDatasetsDraw`.
|
* hook, in which case, plugins will not be called on `afterDatasetsDraw`.
|
||||||
@ -724,16 +757,15 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
|
|||||||
*/
|
*/
|
||||||
drawDatasets: function(easingValue) {
|
drawDatasets: function(easingValue) {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
var metasets, i;
|
||||||
|
|
||||||
if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
|
if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw datasets reversed to support proper line stacking
|
metasets = me._getSortedVisibleDatasetMetas();
|
||||||
for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) {
|
for (i = metasets.length - 1; i >= 0; --i) {
|
||||||
if (me.isDatasetVisible(i)) {
|
me.drawDataset(metasets[i], easingValue);
|
||||||
me.drawDataset(i, easingValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.notify(me, 'afterDatasetsDraw', [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`.
|
* hook, in which case, plugins will not be called on `afterDatasetDraw`.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
drawDataset: function(index, easingValue) {
|
drawDataset: function(meta, easingValue) {
|
||||||
var me = this;
|
var me = this;
|
||||||
var meta = me.getDatasetMeta(index);
|
|
||||||
var args = {
|
var args = {
|
||||||
meta: meta,
|
meta: meta,
|
||||||
index: index,
|
index: meta.index,
|
||||||
easingValue: easingValue
|
easingValue: easingValue
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -829,7 +860,9 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
|
|||||||
controller: null,
|
controller: null,
|
||||||
hidden: null, // See isDatasetVisible() comment
|
hidden: null, // See isDatasetVisible() comment
|
||||||
xAxisID: null,
|
xAxisID: null,
|
||||||
yAxisID: null
|
yAxisID: null,
|
||||||
|
order: dataset.order || 0,
|
||||||
|
index: datasetIndex
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,17 +25,13 @@ function getRelativePosition(e, chart) {
|
|||||||
* @param {function} handler - the callback to execute for each visible item
|
* @param {function} handler - the callback to execute for each visible item
|
||||||
*/
|
*/
|
||||||
function parseVisibleItems(chart, handler) {
|
function parseVisibleItems(chart, handler) {
|
||||||
var datasets = chart.data.datasets;
|
var metasets = chart._getSortedVisibleDatasetMetas();
|
||||||
var meta, i, j, ilen, jlen;
|
var metadata, i, j, ilen, jlen, element;
|
||||||
|
|
||||||
for (i = 0, ilen = datasets.length; i < ilen; ++i) {
|
for (i = 0, ilen = metasets.length; i < ilen; ++i) {
|
||||||
if (!chart.isDatasetVisible(i)) {
|
metadata = metasets[i].data;
|
||||||
continue;
|
for (j = 0, jlen = metadata.length; j < jlen; ++j) {
|
||||||
}
|
element = metadata[j];
|
||||||
|
|
||||||
meta = chart.getDatasetMeta(i);
|
|
||||||
for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
|
|
||||||
var element = meta.data[j];
|
|
||||||
if (!element._view.skip) {
|
if (!element._view.skip) {
|
||||||
handler(element);
|
handler(element);
|
||||||
}
|
}
|
||||||
@ -120,16 +116,13 @@ function indexMode(chart, e, options) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.data.datasets.forEach(function(dataset, datasetIndex) {
|
chart._getSortedVisibleDatasetMetas().forEach(function(meta) {
|
||||||
if (chart.isDatasetVisible(datasetIndex)) {
|
|
||||||
var meta = chart.getDatasetMeta(datasetIndex);
|
|
||||||
var element = meta.data[items[0]._index];
|
var element = meta.data[items[0]._index];
|
||||||
|
|
||||||
// don't count items that are skipped (null data)
|
// don't count items that are skipped (null data)
|
||||||
if (element && !element._view.skip) {
|
if (element && !element._view.skip) {
|
||||||
elements.push(element);
|
elements.push(element);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
|
|||||||
@ -1416,6 +1416,19 @@ var Scale = Element.extend({
|
|||||||
me._drawLabels.apply(me, arguments);
|
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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -995,6 +995,9 @@ var exports = Element.extend({
|
|||||||
me._active = [];
|
me._active = [];
|
||||||
} else {
|
} else {
|
||||||
me._active = me._chart.getElementsAtEventForMode(e, options.mode, options);
|
me._active = me._chart.getElementsAtEventForMode(e, options.mode, options);
|
||||||
|
if (options.reverse) {
|
||||||
|
me._active.reverse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember Last Actives
|
// Remember Last Actives
|
||||||
|
|||||||
@ -354,12 +354,12 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
beforeDatasetsDraw: function(chart) {
|
beforeDatasetsDraw: function(chart) {
|
||||||
var count = (chart.data.datasets || []).length - 1;
|
var metasets = chart._getSortedVisibleDatasetMetas();
|
||||||
var ctx = chart.ctx;
|
var ctx = chart.ctx;
|
||||||
var meta, i, el, view, points, mapper, color;
|
var meta, i, el, view, points, mapper, color;
|
||||||
|
|
||||||
for (i = count; i >= 0; --i) {
|
for (i = metasets.length - 1; i >= 0; --i) {
|
||||||
meta = chart.getDatasetMeta(i).$filler;
|
meta = metasets[i].$filler;
|
||||||
|
|
||||||
if (!meta || !meta.visible) {
|
if (!meta || !meta.visible) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -49,16 +49,15 @@ defaults._set('global', {
|
|||||||
// lineJoin :
|
// lineJoin :
|
||||||
// lineWidth :
|
// lineWidth :
|
||||||
generateLabels: function(chart) {
|
generateLabels: function(chart) {
|
||||||
var data = chart.data;
|
var datasets = chart.data.datasets;
|
||||||
var options = chart.options.legend || {};
|
var options = chart.options.legend || {};
|
||||||
var usePointStyle = options.labels && options.labels.usePointStyle;
|
var usePointStyle = options.labels && options.labels.usePointStyle;
|
||||||
|
|
||||||
return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
|
return chart._getSortedDatasetMetas().map(function(meta, i) {
|
||||||
var meta = chart.getDatasetMeta(i);
|
|
||||||
var style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
|
var style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: dataset.label,
|
text: datasets[meta.index].label,
|
||||||
fillStyle: style.backgroundColor,
|
fillStyle: style.backgroundColor,
|
||||||
hidden: !chart.isDatasetVisible(i),
|
hidden: !chart.isDatasetVisible(i),
|
||||||
lineCap: style.borderCapStyle,
|
lineCap: style.borderCapStyle,
|
||||||
@ -73,7 +72,7 @@ defaults._set('global', {
|
|||||||
// Below is extra data used for toggling the datasets
|
// Below is extra data used for toggling the datasets
|
||||||
datasetIndex: i
|
datasetIndex: i
|
||||||
};
|
};
|
||||||
}, this) : [];
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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({
|
module.exports = LinearScaleBase.extend({
|
||||||
determineDataLimits: function() {
|
determineDataLimits: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
var opts = me.options;
|
var opts = me.options;
|
||||||
var chart = me.chart;
|
var chart = me.chart;
|
||||||
var datasets = chart.data.datasets;
|
var datasets = chart.data.datasets;
|
||||||
var isHorizontal = me.isHorizontal();
|
var metasets = me._getMatchingVisibleMetas();
|
||||||
var DEFAULT_MIN = 0;
|
var hasStacks = opts.stacked;
|
||||||
var DEFAULT_MAX = 1;
|
var stacks = {};
|
||||||
var datasetIndex, meta, value, data, i, ilen;
|
var ilen = metasets.length;
|
||||||
|
var i, meta, data, values;
|
||||||
|
|
||||||
function IDMatches(datasetMeta) {
|
|
||||||
return isHorizontal ? datasetMeta.xAxisID === me.id : datasetMeta.yAxisID === me.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First Calculate the range
|
|
||||||
me.min = Number.POSITIVE_INFINITY;
|
me.min = Number.POSITIVE_INFINITY;
|
||||||
me.max = Number.NEGATIVE_INFINITY;
|
me.max = Number.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
var hasStacks = opts.stacked;
|
|
||||||
if (hasStacks === undefined) {
|
if (hasStacks === undefined) {
|
||||||
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
|
for (i = 0; !hasStacks && i < ilen; ++i) {
|
||||||
meta = chart.getDatasetMeta(datasetIndex);
|
meta = metasets[i];
|
||||||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && meta.stack !== undefined) {
|
hasStacks = meta.stack !== undefined;
|
||||||
hasStacks = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.stacked || hasStacks) {
|
for (i = 0; i < ilen; ++i) {
|
||||||
var valuesPerStack = {};
|
meta = metasets[i];
|
||||||
|
data = datasets[meta.index].data;
|
||||||
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
|
if (hasStacks) {
|
||||||
meta = chart.getDatasetMeta(datasetIndex);
|
stackData(me, stacks, meta, data);
|
||||||
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 {
|
} else {
|
||||||
positiveValues[i] += value.max;
|
updateMinMax(me, meta, data);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
helpers.each(valuesPerStack, function(valuesForType) {
|
helpers.each(stacks, function(stackValues) {
|
||||||
var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
|
values = stackValues.pos.concat(stackValues.neg);
|
||||||
me.min = Math.min(me.min, helpers.min(values));
|
me.min = Math.min(me.min, helpers.min(values));
|
||||||
me.max = Math.max(me.max, helpers.max(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
me.min = helpers.isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
|
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;
|
me.max = helpers.isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
|
||||||
|
|
||||||
// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
|
// 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
|
// Returns the maximum number of ticks based on the scale dimension
|
||||||
|
|||||||
42
test/fixtures/controller.bar/stacking/order-default.json
vendored
Normal file
42
test/fixtures/controller.bar/stacking/order-default.json
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
test/fixtures/controller.bar/stacking/order-default.png
vendored
Normal file
BIN
test/fixtures/controller.bar/stacking/order-default.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
45
test/fixtures/controller.bar/stacking/order-specified.json
vendored
Normal file
45
test/fixtures/controller.bar/stacking/order-specified.json
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
test/fixtures/controller.bar/stacking/order-specified.png
vendored
Normal file
BIN
test/fixtures/controller.bar/stacking/order-specified.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
45
test/fixtures/controller.line/fill/order-default.js
vendored
Normal file
45
test/fixtures/controller.line/fill/order-default.js
vendored
Normal file
@ -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: [{display: false}],
|
||||||
|
yAxes: [{display: false}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
canvas: {
|
||||||
|
height: 256,
|
||||||
|
width: 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
test/fixtures/controller.line/fill/order-default.png
vendored
Normal file
BIN
test/fixtures/controller.line/fill/order-default.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
45
test/fixtures/controller.line/fill/order.js
vendored
Normal file
45
test/fixtures/controller.line/fill/order.js
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
test/fixtures/controller.line/fill/order.png
vendored
Normal file
BIN
test/fixtures/controller.line/fill/order.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
45
test/fixtures/controller.line/stacking/order-default.js
vendored
Normal file
45
test/fixtures/controller.line/stacking/order-default.js
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
test/fixtures/controller.line/stacking/order-default.png
vendored
Normal file
BIN
test/fixtures/controller.line/stacking/order-default.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
47
test/fixtures/controller.line/stacking/order-specified.js
vendored
Normal file
47
test/fixtures/controller.line/stacking/order-specified.js
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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',
|
||||||
|
order: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// option in element (fallback)
|
||||||
|
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: [{stacked: true, display: false}],
|
||||||
|
yAxes: [{stacked: true, display: false}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
canvas: {
|
||||||
|
height: 256,
|
||||||
|
width: 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
test/fixtures/controller.line/stacking/order-specified.png
vendored
Normal file
BIN
test/fixtures/controller.line/stacking/order-specified.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.8 KiB |
@ -581,6 +581,165 @@ describe('Core.Tooltip', function() {
|
|||||||
expect(tooltip._view.y).toBeCloseToPixel(155);
|
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() {
|
it('should filter items from the tooltip using the callback', function() {
|
||||||
var chart = window.acquireChart({
|
var chart = window.acquireChart({
|
||||||
type: 'line',
|
type: 'line',
|
||||||
|
|||||||
@ -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() {
|
it('should filter items', function() {
|
||||||
var chart = window.acquireChart({
|
var chart = window.acquireChart({
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user