From: Evert Timberg Date: Tue, 13 Oct 2015 15:43:00 +0000 (-0400) Subject: Before labels can rotate, we need the appropriate left, right, top, & bottom attribut... X-Git-Tag: 2.0.0-beta~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e39298db3c2a72dd03abce1364c569c4bdafc377;p=thirdparty%2FChart.js.git Before labels can rotate, we need the appropriate left, right, top, & bottom attributes of the scale set with default values so that tick spacing can be determined. After ensuring that this happens, tests needed to be updated. Added unit testing for the scale service. --- diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 40c73b4f5..3fa0e15b2 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -103,9 +103,16 @@ setDimensions: function() { // Set the unconstrained dimension before label rotation if (this.isHorizontal()) { + // Reset position before calculating rotation this.width = this.maxWidth; + this.left = 0; + this.right = this.width; } else { this.height = this.maxHeight; + + // Reset position before calculating rotation + this.top = 0; + this.bottom = this.height } // Reset padding diff --git a/test/controller.bar.tests.js b/test/controller.bar.tests.js index 028ed368a..b9d4eb4df 100644 --- a/test/controller.bar.tests.js +++ b/test/controller.bar.tests.js @@ -262,13 +262,13 @@ describe('Bar controller tests', function() { expect(bar1._xScale).toBe(chart.scales.firstXScaleID); expect(bar1._yScale).toBe(chart.scales.firstYScaleID); expect(bar1._model).toEqual({ - x: 106.80000000000003, + x: 113.60000000000001, y: 194, label: 'label1', datasetLabel: 'dataset2', base: 194, - width: 12.240000000000002, + width: 13.680000000000001, backgroundColor: 'rgb(255, 0, 0)', borderColor: 'rgb(0, 0, 255)', borderWidth: 2, @@ -279,13 +279,13 @@ describe('Bar controller tests', function() { expect(bar2._xScale).toBe(chart.scales.firstXScaleID); expect(bar2._yScale).toBe(chart.scales.firstYScaleID); expect(bar2._model).toEqual({ - x: 140.8, + x: 151.60000000000002, y: -15, label: 'label2', datasetLabel: 'dataset2', base: 194, - width: 12.240000000000002, + width: 13.680000000000001, backgroundColor: 'rgb(255, 0, 0)', borderColor: 'rgb(0, 0, 255)', borderWidth: 2, diff --git a/test/controller.line.tests.js b/test/controller.line.tests.js index 195ba8aa0..94e069d35 100644 --- a/test/controller.line.tests.js +++ b/test/controller.line.tests.js @@ -270,13 +270,13 @@ describe('Line controller tests', function() { tension: 0.1, // Point - x: 63, + x: 71, y: 62, // Control points - controlPointPreviousX: 63, + controlPointPreviousX: 71, controlPointPreviousY: 62, - controlPointNextX: 67.5, + controlPointNextX: 76, controlPointNextY: 57.3, }); @@ -290,14 +290,14 @@ describe('Line controller tests', function() { tension: 0.1, // Point - x: 108, + x: 121, y: 15, // Control points - controlPointPreviousX: 105.27827106822767, - controlPointPreviousY: 12.125364948465183, - controlPointNextX: 114.17827106822767, - controlPointNextY: 21.52536494846518, + controlPointPreviousX: 117.82889384189087, + controlPointPreviousY: 12.04867347661131, + controlPointNextX: 127.92889384189088, + controlPointNextY: 21.44867347661131, }); expect(chart.data.datasets[0].metaData[2]._model).toEqual({ @@ -310,14 +310,14 @@ describe('Line controller tests', function() { tension: 0.1, // Point - x: 152, + x: 172, y: 156, // Control points - controlPointPreviousX: 145.63719249781943, - controlPointPreviousY: 143.20289277651324, - controlPointNextX: 154.53719249781943, - controlPointNextY: 161.10289277651324, + controlPointPreviousX: 164.8815225337256, + controlPointPreviousY: 143.38408449046415, + controlPointNextX: 174.98152253372558, + controlPointNextY: 161.28408449046415, }); expect(chart.data.datasets[0].metaData[3]._model).toEqual({ @@ -330,13 +330,13 @@ describe('Line controller tests', function() { tension: 0.1, // Point - x: 197, + x: 222, y: 194, // Control points - controlPointPreviousX: 192.5, + controlPointPreviousX: 217, controlPointPreviousY: 190.2, - controlPointNextX: 197, + controlPointNextX: 222, controlPointNextY: 194, }); @@ -390,13 +390,13 @@ describe('Line controller tests', function() { tension: 0.2, // Point - x: 63, + x: 71, y: 62, // Control points - controlPointPreviousX: 63, + controlPointPreviousX: 71, controlPointPreviousY: 62, - controlPointNextX: 72, + controlPointNextX: 81, controlPointNextY: 52.6, }); @@ -410,14 +410,14 @@ describe('Line controller tests', function() { tension: 0.2, // Point - x: 108, + x: 121, y: 15, // Control points - controlPointPreviousX: 102.55654213645535, - controlPointPreviousY: 9.250729896930364, - controlPointNextX: 120.35654213645535, - controlPointNextY: 28.050729896930367, + controlPointPreviousX: 114.65778768378175, + controlPointPreviousY: 9.097346953222619, + controlPointNextX: 134.85778768378177, + controlPointNextY: 27.897346953222623, }); expect(chart.data.datasets[0].metaData[2]._model).toEqual({ @@ -430,14 +430,14 @@ describe('Line controller tests', function() { tension: 0.2, // Point - x: 152, + x: 172, y: 156, // Control points - controlPointPreviousX: 139.27438499563885, - controlPointPreviousY: 130.40578555302648, - controlPointNextX: 157.07438499563887, - controlPointNextY: 166.20578555302646, + controlPointPreviousX: 157.76304506745115, + controlPointPreviousY: 130.76816898092827, + controlPointNextX: 177.96304506745116, + controlPointNextY: 166.56816898092828, }); expect(chart.data.datasets[0].metaData[3]._model).toEqual({ @@ -450,13 +450,13 @@ describe('Line controller tests', function() { tension: 0.2, // Point - x: 197, + x: 222, y: 194, // Control points - controlPointPreviousX: 188, + controlPointPreviousX: 212, controlPointPreviousY: 186.4, - controlPointNextX: 197, + controlPointNextX: 222, controlPointNextY: 194, }); @@ -516,13 +516,13 @@ describe('Line controller tests', function() { tension: 0.15, // Point - x: 63, + x: 71, y: 62, // Control points - controlPointPreviousX: 63, + controlPointPreviousX: 71, controlPointPreviousY: 62, - controlPointNextX: 69.75, + controlPointNextX: 78.5, controlPointNextY: 54.95, }); }); diff --git a/test/core.scaleService.tests.js b/test/core.scaleService.tests.js new file mode 100644 index 000000000..3ea3e8a5b --- /dev/null +++ b/test/core.scaleService.tests.js @@ -0,0 +1,257 @@ +// Tests of the scale service +describe('Test the scale service', function() { + it('should fit a simple chart with 2 scales', function() { + var chartInstance = { + scales: [], + }; + + var xScaleID = 'xScale'; + var yScaleID = 'yScale'; + var mockData = { + datasets: [{ + yAxisID: yScaleID, + data: [10, 5, 0, 25, 78, -10] + }], + labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + var mockContext = window.createMockContext(); + + var xScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category')); + var XConstructor = Chart.scaleService.getScaleConstructor('category'); + var xScale = new XConstructor({ + ctx: mockContext, + options: xScaleConfig, + data: mockData, + id: xScaleID + }); + + var yScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear')); + var YConstructor = Chart.scaleService.getScaleConstructor('linear'); + var yScale = new YConstructor({ + ctx: mockContext, + options: yScaleConfig, + data: mockData, + id: yScaleID + }); + + chartInstance.scales.push(xScale); + chartInstance.scales.push(yScale); + + var canvasWidth = 250; + var canvasHeight = 150; + Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight); + + expect(chartInstance.chartArea).toEqual({ + left: 45, + right: 245, + top: 5, + bottom: 76.0423977855504, + }); + + // Is xScale at the right spot + expect(xScale.left).toBe(45); + expect(xScale.right).toBe(245); + expect(xScale.top).toBe(76.0423977855504); + expect(xScale.bottom).toBe(145); + expect(xScale.labelRotation).toBe(55); + + // Is yScale at the right spot + expect(yScale.left).toBe(5); + expect(yScale.right).toBe(45); + expect(yScale.top).toBe(5); + expect(yScale.bottom).toBe(76.0423977855504); + }); + + it('should fit scales that are in the top and right positions', function() { + var chartInstance = { + scales: [], + }; + + var xScaleID = 'xScale'; + var yScaleID = 'yScale'; + var mockData = { + datasets: [{ + yAxisID: yScaleID, + data: [10, 5, 0, 25, 78, -10] + }], + labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + var mockContext = window.createMockContext(); + + var xScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category')); + xScaleConfig.position = 'top'; + var XConstructor = Chart.scaleService.getScaleConstructor('category'); + var xScale = new XConstructor({ + ctx: mockContext, + options: xScaleConfig, + data: mockData, + id: xScaleID + }); + + var yScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear')); + yScaleConfig.position = 'right'; + var YConstructor = Chart.scaleService.getScaleConstructor('linear'); + var yScale = new YConstructor({ + ctx: mockContext, + options: yScaleConfig, + data: mockData, + id: yScaleID + }); + + chartInstance.scales.push(xScale); + chartInstance.scales.push(yScale); + + var canvasWidth = 250; + var canvasHeight = 150; + Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight); + + expect(chartInstance.chartArea).toEqual({ + left: 5, + right: 205, + top: 73.9576022144496, + bottom: 145, + }); + + // Is xScale at the right spot + expect(xScale.left).toBe(5); + expect(xScale.right).toBe(205); + expect(xScale.top).toBe(5); + expect(xScale.bottom).toBe(73.9576022144496); + expect(xScale.labelRotation).toBe(55); + + // Is yScale at the right spot + expect(yScale.left).toBe(205); + expect(yScale.right).toBe(245); + expect(yScale.top).toBe(73.9576022144496); + expect(yScale.bottom).toBe(145); + }); + + it('should fit multiple axes in the same position', function() { + var chartInstance = { + scales: [], + }; + + var xScaleID = 'xScale'; + var yScaleID1 = 'yScale1'; + var yScaleID2 = 'yScale2'; + var mockData = { + datasets: [{ + yAxisID: yScaleID1, + data: [10, 5, 0, 25, 78, -10] + }, { + yAxisID: yScaleID2, + data: [-19, -20, 0, -99, -50, 0] + }], + labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + var mockContext = window.createMockContext(); + + var xScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category')); + var XConstructor = Chart.scaleService.getScaleConstructor('category'); + var xScale = new XConstructor({ + ctx: mockContext, + options: xScaleConfig, + data: mockData, + id: xScaleID + }); + + var yScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear')); + var YConstructor = Chart.scaleService.getScaleConstructor('linear'); + var yScale1 = new YConstructor({ + ctx: mockContext, + options: yScaleConfig, + data: mockData, + id: yScaleID1 + }); + var yScale2 = new YConstructor({ + ctx: mockContext, + options: yScaleConfig, + data: mockData, + id: yScaleID2 + }); + + chartInstance.scales.push(xScale); + chartInstance.scales.push(yScale1); + chartInstance.scales.push(yScale2); + + var canvasWidth = 250; + var canvasHeight = 150; + Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight); + + expect(chartInstance.chartArea).toEqual({ + left: 95, + right: 245, + top: 5, + bottom: 70.01536896070459, + }); + + // Is xScale at the right spot + expect(xScale.left).toBe(95); + expect(xScale.right).toBe(245); + expect(xScale.top).toBe(70.01536896070459); + expect(xScale.bottom).toBe(145); + + // Are yScales at the right spot + expect(yScale1.left).toBe(5); + expect(yScale1.right).toBe(45); + expect(yScale1.top).toBe(5); + expect(yScale1.bottom).toBe(70.01536896070459); + + expect(yScale2.left).toBe(45); + expect(yScale2.right).toBe(95); + expect(yScale2.top).toBe(5); + expect(yScale2.bottom).toBe(70.01536896070459); + }); + + // This is an oddball case. What happens is, when the scales are fit the first time they must fit within the assigned size. In this case, + // the labels on the xScale need to rotate to fit. However, when the scales are fit again after the width of the left axis is determined, + // the labels do not need to rotate. Previously, the chart was too small because the chartArea did not expand to take up the space freed up + // due to the lack of label rotation + it('should fit scales that overlap the chart area', function() { + var chartInstance = { + scales: [], + }; + + var scaleID = 'scaleID'; + var mockData = { + datasets: [{ + yAxisID: scaleID, + data: [10, 5, 0, 25, 78, -10] + }, { + yAxisID: scaleID, + data: [-19, -20, 0, -99, -50, 0] + }], + labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5'] + }; + var mockContext = window.createMockContext(); + + var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear')); + var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear'); + var scale = new ScaleConstructor({ + ctx: mockContext, + options: scaleConfig, + data: mockData, + id: scaleID + }); + + chartInstance.scales.push(scale); + + var canvasWidth = 300; + var canvasHeight = 350; + Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight); + + expect(chartInstance.chartArea).toEqual({ + left: 5, + right: 295, + top: 5, + bottom: 345, + }); + + expect(scale.left).toBe(5); + expect(scale.right).toBe(295); + expect(scale.top).toBe(5); + expect(scale.bottom).toBe(345); + expect(scale.width).toBe(290); + expect(scale.height).toBe(340) + }); +}); \ No newline at end of file diff --git a/test/scale.category.tests.js b/test/scale.category.tests.js index 799fa550e..d6ec96f96 100644 --- a/test/scale.category.tests.js +++ b/test/scale.category.tests.js @@ -94,9 +94,9 @@ describe('Category scale tests', function() { id: scaleID }); - var minSize = scale.update(200, 100); + var minSize = scale.update(600, 100); - expect(scale.width).toBe(200); + expect(scale.width).toBe(600); expect(scale.height).toBe(28); expect(scale.paddingTop).toBe(0); expect(scale.paddingBottom).toBe(0); @@ -105,28 +105,28 @@ describe('Category scale tests', function() { expect(scale.labelRotation).toBe(0); expect(minSize).toEqual({ - width: 200, + width: 600, height: 28, }); scale.left = 5; scale.top = 5; - scale.right = 205; + scale.right = 605; scale.bottom = 33; expect(scale.getPixelForValue(0, 0, 0, false)).toBe(33); - expect(scale.getPixelForValue(0, 0, 0, true)).toBe(45); + expect(scale.getPixelForValue(0, 0, 0, true)).toBe(85); - expect(scale.getPixelForValue(0, 4, 0, false)).toBe(132); - expect(scale.getPixelForValue(0, 4, 0, true)).toBe(145); + expect(scale.getPixelForValue(0, 4, 0, false)).toBe(452); + expect(scale.getPixelForValue(0, 4, 0, true)).toBe(505); config.gridLines.offsetGridLines = false; expect(scale.getPixelForValue(0, 0, 0, false)).toBe(33); expect(scale.getPixelForValue(0, 0, 0, true)).toBe(33); - expect(scale.getPixelForValue(0, 4, 0, false)).toBe(157); - expect(scale.getPixelForValue(0, 4, 0, true)).toBe(157); + expect(scale.getPixelForValue(0, 4, 0, false)).toBe(557); + expect(scale.getPixelForValue(0, 4, 0, true)).toBe(557); }); it ('should get the correct pixel for a value when vertical', function() { diff --git a/test/scale.linear.tests.js b/test/scale.linear.tests.js index 305c24064..d67564d1e 100644 --- a/test/scale.linear.tests.js +++ b/test/scale.linear.tests.js @@ -578,46 +578,47 @@ describe('Linear Scale', function() { var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear')); config.position = "bottom"; var Constructor = Chart.scaleService.getScaleConstructor('linear'); - var verticalScale = new Constructor({ + var horizontalScale = new Constructor({ ctx: mockContext, options: config, data: mockData, id: scaleID }); - var minSize = verticalScale.update(100, 300); + var minSize = horizontalScale.update(200, 300); expect(minSize).toEqual({ - width: 100, + width: 200, height: 28, }); - expect(verticalScale.width).toBe(100); - expect(verticalScale.height).toBe(28); - expect(verticalScale.paddingTop).toBe(0); - expect(verticalScale.paddingBottom).toBe(0); - expect(verticalScale.paddingLeft).toBe(18); - expect(verticalScale.paddingRight).toBe(13); + expect(horizontalScale.width).toBe(200); + expect(horizontalScale.height).toBe(28); + expect(horizontalScale.paddingTop).toBe(0); + expect(horizontalScale.paddingBottom).toBe(0); + expect(horizontalScale.paddingLeft).toBe(13); + expect(horizontalScale.paddingRight).toBe(8); + expect(horizontalScale.labelRotation).toBe(0); // Refit with margins to see the padding go away - minSize = verticalScale.update(100, 28, { + minSize = horizontalScale.update(200, 28, { left: 10, right: 6, top: 15, bottom: 3 }); expect(minSize).toEqual({ - width: 100, + width: 200, height: 28, }); - expect(verticalScale.paddingTop).toBe(0); - expect(verticalScale.paddingBottom).toBe(0); - expect(verticalScale.paddingLeft).toBe(8); - expect(verticalScale.paddingRight).toBe(7); + expect(horizontalScale.paddingTop).toBe(0); + expect(horizontalScale.paddingBottom).toBe(0); + expect(horizontalScale.paddingLeft).toBe(3); + expect(horizontalScale.paddingRight).toBe(2); // Extra size when scale label showing config.scaleLabel.show = true; - minSize = verticalScale.update(100, 300); + minSize = horizontalScale.update(200, 300); expect(minSize).toEqual({ - width: 100, + width: 200, height: 46, }); }); @@ -644,8 +645,8 @@ describe('Linear Scale', function() { id: scaleID }); - var minSize = horizontalScale.update(100, 300); - minSize = horizontalScale.update(100, 28, { + var minSize = horizontalScale.update(200, 300); + minSize = horizontalScale.update(200, 28, { left: 10, right: 6, top: 15, @@ -654,12 +655,12 @@ describe('Linear Scale', function() { horizontalScale.left = 0; horizontalScale.right = minSize.width; - horizontalScale.top = 0; - horizontalScale.bottom = minSize.height; + horizontalScale.top = 100; + horizontalScale.bottom = 100 + minSize.height; var chartArea = { - top: 100, - bottom: 0, + top: 0, + bottom: 100, left: 0, right: minSize.width }; @@ -680,16 +681,16 @@ describe('Linear Scale', function() { "args": [] }, { "name": "moveTo", - "args": [8.5, 0] + "args": [3.5, 100] }, { "name": "lineTo", - "args": [8.5, 10] + "args": [3.5, 110] }, { "name": "moveTo", - "args": [8.5, 100] + "args": [3.5, 0] }, { "name": "lineTo", - "args": [8.5, 0] + "args": [3.5, 100] }, { "name": "stroke", "args": [] @@ -698,13 +699,13 @@ describe('Linear Scale', function() { "args": [] }, { "name": "translate", - "args": [8, 10] + "args": [3, 110] }, { "name": "rotate", "args": [-0] }, { "name": "fillText", - "args": ["-10", 0, 0] + "args": ["-5", 0, 0] }, { "name": "restore", "args": [] @@ -719,16 +720,16 @@ describe('Linear Scale', function() { "args": [] }, { "name": "moveTo", - "args": [51.5, 0] + "args": [101.5, 100] }, { "name": "lineTo", - "args": [51.5, 10] + "args": [101.5, 110] }, { "name": "moveTo", - "args": [51.5, 100] + "args": [101.5, 0] }, { "name": "lineTo", - "args": [51.5, 0] + "args": [101.5, 100] }, { "name": "stroke", "args": [] @@ -737,7 +738,7 @@ describe('Linear Scale', function() { "args": [] }, { "name": "translate", - "args": [51, 10] + "args": [101, 110] }, { "name": "rotate", "args": [-0] @@ -758,16 +759,16 @@ describe('Linear Scale', function() { "args": [] }, { "name": "moveTo", - "args": [93.5, 0] + "args": [198.5, 100] }, { "name": "lineTo", - "args": [93.5, 10] + "args": [198.5, 110] }, { "name": "moveTo", - "args": [93.5, 100] + "args": [198.5, 0] }, { "name": "lineTo", - "args": [93.5, 0] + "args": [198.5, 100] }, { "name": "stroke", "args": [] @@ -776,13 +777,13 @@ describe('Linear Scale', function() { "args": [] }, { "name": "translate", - "args": [93, 10] + "args": [198, 110] }, { "name": "rotate", "args": [-0] }, { "name": "fillText", - "args": ["10", 0, 0] + "args": ["5", 0, 0] }, { "name": "restore", "args": [] @@ -840,7 +841,7 @@ describe('Linear Scale', function() { "args": [] }, { "name": "fillText", - "args": ["myLabel", 50, 22] + "args": ["myLabel", 100, 122] }]); // Turn off display