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

Refactor plot autosize #635

Merged
merged 7 commits into from
Oct 27, 2016
Merged

Refactor plot autosize #635

merged 7 commits into from
Oct 27, 2016

Conversation

etpinard
Copy link
Contributor

@etpinard etpinard commented Jun 13, 2016

fixes #537

This PR sets up a base branch for the in-progress autosize refactor starting out by @n-riesco in #577 patched in #629 and then reverted in #633.

Important comments:

@@ -379,7 +379,9 @@ lib.getPlotDiv = function(el) {

lib.isPlotDiv = function(el) {
var el3 = d3.select(el);
return el3.size() && el3.classed('js-plotly-plot');
return el3.node() instanceof HTMLElement &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Just for my own understanding: when would this not be an HTMLElement?

Copy link
Contributor Author

@etpinard etpinard Jun 14, 2016

Choose a reason for hiding this comment

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

if someone calls Plotly.Plots.supplyDefaults({ data: [], layout: {}}); - which should be allowed.

Copy link
Contributor

Choose a reason for hiding this comment

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

If gd isn't a HTMLElement, el3.classed('js-plotly-plot') throws an exception.

@mdtusz
Copy link
Contributor

mdtusz commented Jun 18, 2016

💃

@etpinard
Copy link
Contributor Author

etpinard commented Sep 7, 2016

dropping this PR from the v1.17.0 milestone because of the numerous merge conflict left to fix ... and let's face it, we're due for a minor bump.

@etpinard etpinard added this to the v1.18.0 milestone Sep 8, 2016
@etpinard etpinard self-assigned this Sep 8, 2016
@fresheneesz
Copy link

@etpinard

I created some logic that finds the maximum size an element can be sized to without exceeding the boundaries of its parent. It takes into account margins, borders, padding, percentage widths, max-height/width, and sibling nodes. You can find it here: http://stackoverflow.com/a/39782139/122422

I think this is something that would help autosizing work better, since currently using autosizing seems to frequently exceed the boundaries of the graph's parent.

@etpinard
Copy link
Contributor Author

etpinard commented Oct 9, 2016

Dropping from the v1.18.0 milestone.

This will be implemented in v1.19.0 together with layout breakpoints.

@etpinard etpinard modified the milestones: v1.18.0, v1.19.0 Oct 9, 2016
@JonDum
Copy link

JonDum commented Oct 24, 2016

I'm super interested in this PR. Is there anything I can contribute?

I am trying to use Plotly in a Flex layout and Plotly is not playing nicely. The major problem is Plotly's use of explicit width/height in pixels. Doing this makes an implicit size on the chart that will then cause the flex layout to never go less than size.

Here's an example pen: http://codepen.io/JonDum/pen/gwEPPA

If you resize horizontally you'll notice that it will grow larger, but never smaller.

If you look at how Chartist.js handles this, they default to setting the <svg> element to a width/height of 100% and they automatically scale to their container's size (which you can see on their demo page)

@etpinard
Copy link
Contributor Author

etpinard commented Oct 26, 2016

@n-riesco I (finally) resurrected your PR 🎉

To preserve backward compatibility, I had to add two commits:

  • 77971f4 adds a hacky block in relayout to make sure this relayout case still passes. It's not pretty, but only a few lines. I hope you don't mind.
  • b6c5610 is a little trickier and very important. This commit ensures that graphs with no set width and height have a default autosize of true. Previously, graphs with no set width and height were given the 'initial' autosize value (see here).

I hope you find these two commits compatible with what you had in mind for this PR.

@n-riesco
Copy link
Contributor

n-riesco commented Oct 26, 2016

Looks like github didn't get my email. Here's a copy:


On 26/10/16 18:50, Étienne Tétreault-Pinard wrote:

I don't understand how this commit works.

If I read it correctly, something like Plotly.relayout(gd, { width: null }) would be equivalent to Plotly.relayout(gd, { width: 'initial' }).

Since 'initial' is an invalid width, this would make gd._fullLayout.width = 700 (i.e. the default width value).

Would the following work instead?

if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
    delete gd._fullLayout._initialAutoSizeIsDone;
}

I can look into this tomorrow.


I think this behaviour is better (and necessary to fix #537)

@etpinard
Copy link
Contributor Author

etpinard commented Oct 26, 2016

Would the following work instead?

if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
delete gd._fullLayout._initialAutoSizeIsDone;
}

Let me try. Thanks!

I think this behaviour is better

By this, you meant behaviour after my last commit (b6c5610) ?

(and necessary to fix #537)

The tests you added to fix #537 are still passing, anything else I should try to confirm that #537 is still fixed?

@etpinard
Copy link
Contributor Author

@n-riesco

Would the following work instead?

if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
delete gd._fullLayout._initialAutoSizeIsDone;
}

Let me try. Thanks!

Replacing 77971f4 with your suggestion makes the aforementioned relayout test case fail.

The reason being:

  • clearing _fullLayout._initialAutoSizeDone leads to a plotAutosize call which (in the default context) reaches this line where the new width/height are taken from the DOM
  • The problem is: those width/height value come from the previous relayout call, so line by line:
        it('sets null values to their default', function(done) {
            var defaultWidth;
            Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }])
                .then(function() {
                    defaultWidth = gd._fullLayout.width;
                    defaultWidth // => 700
                    return Plotly.relayout(gd, { width: defaultWidth - 25});
                })
                .then(function() {
                    gd._fullLayout.width // => 675
                    expect(gd._fullLayout.width).toBe(defaultWidth - 25);
                    return Plotly.relayout(gd, { width: null });
                })
                .then(function() {
                    gd._fullLayout.width // => 675 BUT should 700 !!
                    expect(gd._fullLayout.width).toBe(defaultWidth);
                })
                .then(done);
        });

@etpinard
Copy link
Contributor Author

Now, by setting width: 'initial' in relayout in the hacky block of 77971f4, Plots.supplyDefaults now reaches this line, where newLayout.width isn't reset to its old value as 'initial' is truthy. Instead, newLayout.width is set back to its default value of 700.

@etpinard
Copy link
Contributor Author

Perhaps a better solution would be to cache the initial graph div width / height computed styles and use them in relayout.

@etpinard
Copy link
Contributor Author

@n-riesco here's a less hacky (I think) fix: 8396018

Let me know what you think.

@etpinard
Copy link
Contributor Author

@n-riesco commit 08069a4 implements an even less hacky solution (I think we now have the correct answer to what relayout should do).

Let me know what you think.

- so that relayout(gd, 'width', null) reset the
  graph to its initial width
@etpinard
Copy link
Contributor Author

@n-riesco I took your 👍 reaction on #635 (comment) as a sign of approval. Commit 5fb7cd1 implement the cache-initial-autosize solution.

@etpinard etpinard merged commit e01cb00 into master Oct 27, 2016
@etpinard etpinard deleted the autosize-refactor branch October 27, 2016 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken
Projects
None yet
Development

Successfully merging this pull request may close these issues.

newPlot doesn't respect layout.height unless layout.autosize is explicitly true
5 participants