Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to fix responsive chart size in IE11 when parent container has… #4620

Merged
merged 13 commits into from Apr 22, 2018

Conversation

andi-b
Copy link
Contributor

@andi-b andi-b commented Aug 7, 2017

… padding as percentage

When the chart is responsive to the parent container, the calculations for padding assumes that the figure is in pixels so that 20% is taken to be 20 (pixels), which results in the chart exceeding the parent container.

Issue may be seen in IE11 here:
https://jsfiddle.net/digits/e8g4ux20/

… padding as percentage

When the chart is responsive to the parent container, the calculations for padding assumes that the figure is in pixels so that 20% is taken to be 20 (pixels), which results in the chart exceeding the parent container. This appears to be an IE11 only issue.
@andi-b
Copy link
Contributor Author

andi-b commented Aug 8, 2017

Codeclimate seems to lie :) Click on 'Details' and all appears fine

@benmccann
Copy link
Contributor

benmccann commented Sep 19, 2017

Does this issue happen only on IE11?

@andi-b
Copy link
Contributor Author

andi-b commented Sep 19, 2017

Strangely it does seem to only happen in IE11. Was fine in Firefox as uses computed value and think it was fine in Chrome and Edge.

@benmccann
Copy link
Contributor

Perhaps you could add a helper function to cut down on code duplication:

function calculatePadding(padding, parentDimension) {
	if (padding.indexOf('%') > -1) {
		return parentDimension / parseInt(padding, 10);
	} else {
		return parseInt(padding, 10);
	}
}

Copy link
Member

@etimberg etimberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs some tests written as well

@benmccann
Copy link
Contributor

@andi-b will you be able to respond to the comments on this PR?

@andi-b
Copy link
Contributor Author

andi-b commented Jan 16, 2018

I have made the update locally - just need to test myself before submitting change.

Do I need to write tests and how do I go about doing this?

Thanks

Added calculatePadding function to reduce code duplication
Reduced code further by adding to calculatePadding function
Fixed due to code climate:
Updated to inline if statement for single return
Removed space;
@benmccann
Copy link
Contributor

Yes, please add tests as well. You can add them to the file test/specs/core.helpers.tests.js. You can create a dom node and call the function on it and check if the results are as expected

@benmccann
Copy link
Contributor

@andi-b do you plan on updating this PR?

@andi-b
Copy link
Contributor Author

andi-b commented Feb 6, 2018

@benmccann Sorry, just need to find some time to figure out how to add a test case as this is new to me. I'll hopefully find some time this week.

Update code formatting as per Travis CI
etimberg
etimberg previously approved these changes Feb 7, 2018
@@ -466,14 +466,20 @@ module.exports = function(Chart) {
helpers.getConstraintHeight = function(domNode) {
return getConstraintDimension(domNode, 'max-height', 'clientHeight');
};
helpers.calculatePadding = function(container, padding, parentDimension) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want this method to be part of the public API.

Can you prefix the method with _ and add a private comment:

/**
 * @private
 */
helpers._calculatePadding = function(...

helpers.getMaximumWidth = function(domNode) {
var container = domNode.parentNode;
if (!container) {
return domNode.clientWidth;
}

var paddingLeft = parseInt(helpers.getStyle(container, 'padding-left'), 10);
var paddingRight = parseInt(helpers.getStyle(container, 'padding-right'), 10);
var paddingLeft = helpers.calculatePadding(container, 'padding-left', container.clientWidth);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should cache clientWidth since it's used multiple times:

var clientWidth = container.clientWidth;
var paddingLeft = helpers.calculatePadding(container, 'padding-left', clientWidth );
var paddingRight = helpers.calculatePadding(container, 'padding-right', clientWidth );
var w = clientWidth  - paddingLeft - paddingRight;
// ...

@@ -484,8 +490,9 @@ module.exports = function(Chart) {
return domNode.clientHeight;
}

var paddingTop = parseInt(helpers.getStyle(container, 'padding-top'), 10);
var paddingBottom = parseInt(helpers.getStyle(container, 'padding-bottom'), 10);
var paddingTop = helpers.calculatePadding(container, 'padding-top', container.clientHeight);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here (var clientHeight = container.clientHeight;)

@@ -742,6 +742,41 @@ describe('Core helper tests', function() {
expect(canvas.style.width).toBe('400px');
});

it ('Should get padding of parent as number (pixels) when defined as percent (returns incorrectly in IE11)', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we would need a unit test that doesn't check internals but creates a chart inside a container with percent padding and verify the chart dimensions (something similar to this test)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed call to now private function calculatePadding.
I attempted to write test with chart but require a parent DIV to the wrapper so I can set the width as the padding percentage is taken from this and not from the wrapper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it('**********Should calculate padding of parent container in pixels if as percent (IE11)', function(done) {
	var chart = acquireChart({
		type: 'pie',
		options: {
			responsive: true,
			maintainAspectRatio: true
		}
	}, {
		canvas: {
			style: 'width: 300px; height: 300px; position: relative'
		},
		wrapper: {
			style: 'padding: 10%; width: 300px; height: 300px;'
		}
	});

	expect(chart).toBeChartOfSize({
		dw: 240, dh: 240,
		rw: 240, rh: 240,
	});
});

Added variable for clientWidth and clientHeight;
Made function calculatePadding private
Removed calls to private function calculatePadding
Removed unused variable container
@andi-b
Copy link
Contributor Author

andi-b commented Feb 14, 2018

codeclimate complaining about an existing function - should this be ignored?

@etimberg
Copy link
Member

The code climate stuff about an existing function can be ignored.

@simonbrunel simonbrunel merged commit 73b8cee into chartjs:master Apr 22, 2018
@andi-b andi-b deleted the patch-1 branch April 30, 2018 13:47
@chtheis
Copy link
Contributor

chtheis commented Nov 18, 2018

I think the calculation of padding in % is wrong, it just divides the size by the padding in percent.
Instead line 502 in src/core/core.helpers.js should read:

return padding.indexOf('%') > -1 ? parentDimension * parseInt(padding, 10) / 100 : parseInt(padding, 10);

I have a padding of 2% of the surrounding div, IE (Edge) returns just that value and the old code would return half the width as padding, thus the canvas would have 0 width.

@chtheis
Copy link
Contributor

chtheis commented Nov 18, 2018

And in the test you use 10% as padding. In this case, and only this case, the old code would return a correct result. Maybe use something like 5% as the test case.

@simonbrunel
Copy link
Member

@chtheis you are right, I'm surprised that nobody noticed that error in this PR.

exwm pushed a commit to exwm/Chart.js that referenced this pull request Apr 30, 2021
When the chart is responsive to the parent container, the calculations for padding assumes that the figure is in pixels so that 20% is taken to be 20 (pixels), which results in the chart exceeding the parent container. This appears to be an IE11 only issue.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants