From: Evert Timberg Date: Sat, 21 Nov 2015 15:51:32 +0000 (-0500) Subject: Modify layout service to be able to place horizontal boxes as either full width or... X-Git-Tag: 2.0.0-beta2~25^2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b719e6432baa2c3b6afb3647960cc157bcfeb9e;p=thirdparty%2FChart.js.git Modify layout service to be able to place horizontal boxes as either full width or not full width. Currently the legend is the only full width box we have. Scales were modified so as not to be full width, however Core.Scale can handle boxes that are full width. Updated unit tests to use correct 'boxes' property of chart instance. Tests did not require numerical updates! Added a test to cover placing a full width box. --- diff --git a/src/core/core.layoutService.js b/src/core/core.layoutService.js index 982c42d8a..fed4d0b9b 100644 --- a/src/core/core.layoutService.js +++ b/src/core/core.layoutService.js @@ -113,10 +113,11 @@ var isHorizontal = box.isHorizontal(); if (isHorizontal) { - minSize = box.update(chartWidth, horizontalBoxHeight); + minSize = box.update(box.options.fullWidth ? chartWidth : chartAreaWidth, horizontalBoxHeight); } else { minSize = box.update(verticalBoxWidth, chartAreaHeight); } + minBoxSizes.push({ horizontal: isHorizontal, minSize: minSize, @@ -159,23 +160,25 @@ // Set the Left and Right margins for the horizontal boxes helpers.each(topBoxes.concat(bottomBoxes), fitBox); + // Function to fit a box function fitBox(box) { - var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) { return minBoxSize.box === box; }); - if (box.isHorizontal() && minBoxSize) { - var scaleMargin = { - left: totalLeftBoxesWidth, - right: totalRightBoxesWidth, - top: 0, - bottom: 0, - }; - - box.update(chartWidth, minBoxSize.minSize.height, scaleMargin); - } else { - box.update(minBoxSize.minSize.width, maxChartAreaHeight); + if (minBoxSize) { + if (box.isHorizontal()) { + var scaleMargin = { + left: totalLeftBoxesWidth, + right: totalRightBoxesWidth, + top: 0, + bottom: 0, + }; + + box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, minBoxSize.minSize.height, scaleMargin); + } else { + box.update(minBoxSize.minSize.width, maxChartAreaHeight); + } } } @@ -273,8 +276,8 @@ function placeBox(box) { if (box.isHorizontal()) { - box.left = xPadding; - box.right = width - xPadding; + box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth; + box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth; box.top = top; box.bottom = top + box.height; diff --git a/src/core/core.legend.js b/src/core/core.legend.js index dfc06a77d..b8bf96734 100644 --- a/src/core/core.legend.js +++ b/src/core/core.legend.js @@ -9,6 +9,7 @@ display: true, position: 'top', + fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes) onClick: false, // a callback will override the default behavior of toggling the datasets title: { diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 9bab29c2a..f60d8f09c 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -234,8 +234,8 @@ // Width if (this.isHorizontal()) { - // subtract the margins to line up with the chartArea - this.minSize.width = this.maxWidth - this.margins.left - this.margins.right; + // subtract the margins to line up with the chartArea if we are a full width scale + this.minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth; } else { this.minSize.width = this.options.gridLines.show && this.options.display ? 10 : 0; } @@ -328,6 +328,9 @@ isHorizontal: function() { return this.options.position == "top" || this.options.position == "bottom"; }, + isFullWidth: function() { + return (this.options.fullWidth); + }, // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not getRightValue: function getRightValue(rawValue) { @@ -365,7 +368,10 @@ if (includeOffset) { pixel += tickWidth / 2; } - return this.left + this.margins.left + Math.round(pixel); + + var finalVal = this.left + Math.round(pixel); + finalVal += this.isFullWidth() ? this.margins.left : 0; + return finalVal; } else { var innerHeight = this.height - (this.paddingTop + this.paddingBottom); return this.top + (index * (innerHeight / (this.ticks.length - 1))); @@ -378,7 +384,9 @@ var innerWidth = this.width - (this.paddingLeft + this.paddingRight); var valueOffset = (innerWidth * decimal) + this.paddingLeft; - return this.left + this.margins.left + Math.round(valueOffset); + var finalVal = this.left + Math.round(valueOffset); + finalVal += this.isFullWidth() ? this.margins.left : 0; + return finalVal; } else { return this.top + (decimal * this.height); } diff --git a/src/scales/scale.category.js b/src/scales/scale.category.js index c0fabe407..8d8f709f0 100644 --- a/src/scales/scale.category.js +++ b/src/scales/scale.category.js @@ -30,7 +30,7 @@ widthOffset += (valueWidth / 2); } - return this.left + this.margins.left + Math.round(widthOffset); + return this.left + Math.round(widthOffset); } else { var innerHeight = this.height - (this.paddingTop + this.paddingBottom); var valueHeight = innerHeight / Math.max((this.chart.data.labels.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1); diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index 631d9c129..2cc8254e6 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -219,7 +219,7 @@ if (this.isHorizontal()) { var innerWidth = this.width - (this.paddingLeft + this.paddingRight); - pixel = this.left + this.margins.left + (innerWidth / range * (rightValue - this.start)); + pixel = this.left + (innerWidth / range * (rightValue - this.start)); return Math.round(pixel + this.paddingLeft); } else { var innerHeight = this.height - (this.paddingTop + this.paddingBottom); diff --git a/test/core.layoutService.tests.js b/test/core.layoutService.tests.js index 8210bc525..355986282 100644 --- a/test/core.layoutService.tests.js +++ b/test/core.layoutService.tests.js @@ -2,7 +2,7 @@ describe('Test the layout service', function() { it('should fit a simple chart with 2 scales', function() { var chartInstance = { - scales: [], + boxes: [], }; var xScaleID = 'xScale'; @@ -38,8 +38,8 @@ describe('Test the layout service', function() { id: yScaleID }); - chartInstance.scales.push(xScale); - chartInstance.scales.push(yScale); + chartInstance.boxes.push(xScale); + chartInstance.boxes.push(yScale); var canvasWidth = 250; var canvasHeight = 150; @@ -68,7 +68,7 @@ describe('Test the layout service', function() { it('should fit scales that are in the top and right positions', function() { var chartInstance = { - scales: [], + boxes: [], }; var xScaleID = 'xScale'; @@ -106,8 +106,8 @@ describe('Test the layout service', function() { id: yScaleID }); - chartInstance.scales.push(xScale); - chartInstance.scales.push(yScale); + chartInstance.boxes.push(xScale); + chartInstance.boxes.push(yScale); var canvasWidth = 250; var canvasHeight = 150; @@ -136,7 +136,7 @@ describe('Test the layout service', function() { it('should fit multiple axes in the same position', function() { var chartInstance = { - scales: [], + boxes: [], }; var xScaleID = 'xScale'; @@ -184,9 +184,9 @@ describe('Test the layout service', function() { id: yScaleID2 }); - chartInstance.scales.push(xScale); - chartInstance.scales.push(yScale1); - chartInstance.scales.push(yScale2); + chartInstance.boxes.push(xScale); + chartInstance.boxes.push(yScale1); + chartInstance.boxes.push(yScale2); var canvasWidth = 250; var canvasHeight = 150; @@ -223,7 +223,7 @@ describe('Test the layout service', function() { // due to the lack of label rotation it('should fit scales that overlap the chart area', function() { var chartInstance = { - scales: [], + boxes: [], }; var scaleID = 'scaleID'; @@ -250,7 +250,7 @@ describe('Test the layout service', function() { id: scaleID }); - chartInstance.scales.push(scale); + chartInstance.boxes.push(scale); var canvasWidth = 300; var canvasHeight = 350; @@ -270,4 +270,91 @@ describe('Test the layout service', function() { expect(scale.width).toBe(290); expect(scale.height).toBe(340) }); + + it ('should fix a full width box correctly', function() { + var chartInstance = { + boxes: [], + }; + + var xScaleID1= 'xScale1'; + var xScaleID2 = 'xScale2'; + var yScaleID = 'yScale2'; + + var mockData = { + datasets: [{ + xAxisID: xScaleID1, + data: [10, 5, 0, 25, 78, -10] + }, { + xAxisID: xScaleID2, + 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 xScale1 = new XConstructor({ + ctx: mockContext, + options: xScaleConfig, + chart: { + data: mockData + }, + id: xScaleID1 + }); + var xScale2 = new XConstructor({ + ctx: mockContext, + options: Chart.helpers.extend(Chart.helpers.clone(xScaleConfig), { + position: 'top', + fullWidth: true + }), + chart: { + data: mockData, + }, + id: xScaleID2 + }); + + var yScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear')); + var YConstructor = Chart.scaleService.getScaleConstructor('linear'); + var yScale = new YConstructor({ + ctx: mockContext, + options: yScaleConfig, + chart: { + data: mockData + }, + id: yScaleID + }); + + chartInstance.boxes.push(xScale1); + chartInstance.boxes.push(xScale2); + chartInstance.boxes.push(yScale); + + var canvasWidth = 250; + var canvasHeight = 150; + Chart.layoutService.update(chartInstance, canvasWidth, canvasHeight); + + expect(chartInstance.chartArea).toEqual({ + left: 45, + right: 245, + top: 45, + bottom: 105, + }); + + // Are xScales at the right spot + expect(xScale1.left).toBe(45); + expect(xScale1.right).toBe(245); + expect(xScale1.top).toBe(105); + expect(xScale1.bottom).toBe(145); + + expect(xScale2.left).toBe(5); + expect(xScale2.right).toBe(245); + expect(xScale2.top).toBe(5); + expect(xScale2.bottom).toBe(45); + + // Is yScale at the right spot + expect(yScale.left).toBe(5); + expect(yScale.right).toBe(45); + expect(yScale.top).toBe(45); + expect(yScale.bottom).toBe(105); + }); }); \ No newline at end of file