From b6686f00f4670a03ed242db13a80a0d6f9399af2 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sat, 9 Jul 2016 11:22:25 -0400 Subject: [PATCH] Non numeric y (#2849) * Category scale can now read from the xLabels and yLabels properties. * Update docs with section regarding the data object. * Add sample file with non numeric Y and fix animations --- docs/01-Chart-Configuration.md | 11 ++++ docs/02-Scales.md | 2 +- samples/line-non-numeric-y.html | 92 +++++++++++++++++++++++++++++++++ src/scales/scale.category.js | 32 +++++++++--- test/scale.category.tests.js | 57 +++++++++++++++++++- 5 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 samples/line-non-numeric-y.html diff --git a/docs/01-Chart-Configuration.md b/docs/01-Chart-Configuration.md index 929fa5540..57c06284d 100644 --- a/docs/01-Chart-Configuration.md +++ b/docs/01-Chart-Configuration.md @@ -5,6 +5,17 @@ anchor: chart-configuration Chart.js provides a number of options for changing the behaviour of created charts. These configuration options can be changed on a per chart basis by passing in an options object when creating the chart. Alternatively, the global configuration can be changed which will be used by all charts created after that point. +### Chart Data + +To display data, the chart must be passed a data object that contains all of the information needed by the chart. The data object can contain the following parameters + +Name | Type | Description +--- | --- | ---- +datasets | Array[object] | Contains data for each dataset. See the documentation for each chart type to determine the valid options that can be attached to the dataset +labels | Array[string] | Optional parameter that is used with the [category axis](#scales-category-scale). +xLabels | Array[string] | Optional parameter that is used with the category axis and is used if the axis is horizontal +yLabels | Array[string] | Optional parameter that is used with the category axis and is used if the axis is vertical + ### Creating a Chart with Options To create a chart with configuration options, simply pass an object containing your configuration to the constructor. In the example below, a line chart is created and configured to not be responsive. diff --git a/docs/02-Scales.md b/docs/02-Scales.md index 5597b4c1a..a57b9a3c5 100644 --- a/docs/02-Scales.md +++ b/docs/02-Scales.md @@ -115,7 +115,7 @@ var chartInstance = new Chart(ctx, { ### Category Scale -The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data. +The category scale will be familiar to those who have used v1.0. Labels are drawn from one of the label arrays included in the chart data. If only `data.labels` is defined, this will be used. If `data.xLabels` is defined and the axis is horizontal, this will be used. Similarly, if `data.yLabels` is defined and the axis is vertical, this property will be used. Using both `xLabels` and `yLabels` together can create a chart that uses strings for both the X and Y axes. #### Configuration Options diff --git a/samples/line-non-numeric-y.html b/samples/line-non-numeric-y.html new file mode 100644 index 000000000..c0b74a150 --- /dev/null +++ b/samples/line-non-numeric-y.html @@ -0,0 +1,92 @@ + + + + + Line Chart + + + + + + +
+ +
+ + + + diff --git a/src/scales/scale.category.js b/src/scales/scale.category.js index fe18a3100..bc1582202 100644 --- a/src/scales/scale.category.js +++ b/src/scales/scale.category.js @@ -9,33 +9,44 @@ module.exports = function(Chart) { }; var DatasetScale = Chart.Scale.extend({ + /** + * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use tose + * else fall back to data.labels + * @private + */ + getLabels: function() { + var data = this.chart.data; + return (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; + }, // Implement this so that determineDataLimits: function() { var me = this; + var labels = me.getLabels(); me.minIndex = 0; - me.maxIndex = me.chart.data.labels.length - 1; + me.maxIndex = labels.length - 1; var findIndex; if (me.options.ticks.min !== undefined) { // user specified min value - findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.min); + findIndex = helpers.indexOf(labels, me.options.ticks.min); me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; } if (me.options.ticks.max !== undefined) { // user specified max value - findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.max); + findIndex = helpers.indexOf(labels, me.options.ticks.max); me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; } - me.min = me.chart.data.labels[me.minIndex]; - me.max = me.chart.data.labels[me.maxIndex]; + me.min = labels[me.minIndex]; + me.max = labels[me.maxIndex]; }, buildTicks: function() { var me = this; + var labels = me.getLabels(); // If we are viewing some subset of labels, slice the original array - me.ticks = (me.minIndex === 0 && me.maxIndex === me.chart.data.labels.length - 1) ? me.chart.data.labels : me.chart.data.labels.slice(me.minIndex, me.maxIndex + 1); + me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); }, getLabelForIndex: function(index) { @@ -48,6 +59,12 @@ module.exports = function(Chart) { // 1 is added because we need the length but we have the indexes var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); + if (value !== undefined) { + var labels = me.getLabels(); + var idx = labels.indexOf(value); + index = idx !== -1 ? idx : index; + } + if (me.isHorizontal()) { var innerWidth = me.width - (me.paddingLeft + me.paddingRight); var valueWidth = innerWidth / offsetAmt; @@ -95,6 +112,9 @@ module.exports = function(Chart) { } return value; + }, + getBasePixel: function() { + return this.bottom; } }); diff --git a/test/scale.category.tests.js b/test/scale.category.tests.js index 3b6ebc3d7..721c22a05 100644 --- a/test/scale.category.tests.js +++ b/test/scale.category.tests.js @@ -48,7 +48,7 @@ describe('Category scale tests', function() { expect(defaultConfig.ticks.callback).toEqual(jasmine.any(Function)); }); - it('Should generate ticks from the data labales', function() { + it('Should generate ticks from the data labels', function() { var scaleID = 'myScale'; var mockData = { @@ -75,6 +75,61 @@ describe('Category scale tests', function() { expect(scale.ticks).toEqual(mockData.labels); }); + it('Should generate ticks from the data xLabels', function() { + var scaleID = 'myScale'; + + var mockData = { + datasets: [{ + yAxisID: scaleID, + data: [10, 5, 0, 25, 78] + }], + xLabels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + + var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category')); + var Constructor = Chart.scaleService.getScaleConstructor('category'); + var scale = new Constructor({ + ctx: {}, + options: config, + chart: { + data: mockData + }, + id: scaleID + }); + + scale.determineDataLimits(); + scale.buildTicks(); + expect(scale.ticks).toEqual(mockData.xLabels); + }); + + it('Should generate ticks from the data xLabels', function() { + var scaleID = 'myScale'; + + var mockData = { + datasets: [{ + yAxisID: scaleID, + data: [10, 5, 0, 25, 78] + }], + yLabels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + + var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category')); + config.position = 'left'; // y axis + var Constructor = Chart.scaleService.getScaleConstructor('category'); + var scale = new Constructor({ + ctx: {}, + options: config, + chart: { + data: mockData + }, + id: scaleID + }); + + scale.determineDataLimits(); + scale.buildTicks(); + expect(scale.ticks).toEqual(mockData.yLabels); + }); + it ('should get the correct label for the index', function() { var scaleID = 'myScale'; -- 2.47.3