Skip to content

scrolling legend height not recalculated on resize #348

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

Closed
timelyportfolio opened this issue Mar 22, 2016 · 10 comments
Closed

scrolling legend height not recalculated on resize #348

timelyportfolio opened this issue Mar 22, 2016 · 10 comments
Labels
bug something broken

Comments

@timelyportfolio
Copy link
Contributor

Initially reported in plotly/plotly.R#525, I was able to isolate to a non-R JavaScript only example in codepen. I had hoped v1.7.0 would solve this, but unfortunately I just updated, and the problem persists.

plotly_legend_resize

I am happy to attempt to tackle this if desired. I see on line where it checks for firstRender to draw the legend. I'm wondering if we can handle by just removing this firstRender check.

@etpinard
Copy link
Contributor

@timelyportfolio thanks for the report!

I am happy to attempt to tackle this if desired.

That would be great. Go for it!

@etpinard etpinard added the bug something broken label Mar 22, 2016
@timelyportfolio
Copy link
Contributor Author

So, this became far thornier than I initially expected. We have a scope problem with scrollheight defined in the scrollHandler eventListener callback (see lines) defined on initial draw that does not update on relayout. Also, the pattern data([0]).enter().append(...).... means legend items such as clippath (lines so clippath null in lines on relayout) will not be updated. I have almost convinced myself that the legend should partially or completely redraw each relayout but then we might lose legend selections. @etpinard, any thoughts before I assemble a pull, since this will be my first?

The full brute force method would be to

legend.html("");
...
// and then remove the check for firstRender
// // If scrollbar should be shown.
//    if(gd.firstRender && opts.height - scrollheight > 0 && !gd._context.staticPlot) {
if(opts.height - scrollheight > 0 && !gd._context.staticPlot) {

@etpinard
Copy link
Contributor

Moving block 1 and 2 above the gd.firstRender clause should suffice for this PR.

It is important to attach event listeners to the legend only once per graph (hence that gd.firstRender block), but re-layout calls should reset the clip paths and bounding rectangle dimensions,

@mdtusz Any other insights?

@mdtusz
Copy link
Contributor

mdtusz commented Mar 23, 2016

That should solve the sizing issue.

So long as the existing eventListeners are removed, I see no problem with re-setting them. It may take a bit of fiddling to get the order of operations right and will require a check to see that you aren't adding a listener to a non-existent scroll, but it would ensure the correct value in the scrollHandler.

@etpinard
Copy link
Contributor

For the record, data([0]).enter().append(...).... does not mean that the legend items aren't updated on relayout. It indicates that there will one and only one of these node on the graph at all times.

More thoroughly,

// select all clippath nodes with id 'clipId' => 0 node on first pass, 1 node afterwards
var clipPath = fullLayout._topdefs.selectAll('#' + clipId);
      // bind an array of length 1 to selection 
        .data([0])
      // grabs the enter selection => has 1 node in first pass, 0 node afterwards
      .enter()
     // from enter selection => append <clipPath> with id 'clipId'
    .append('clipPath')
        .attr('id', clipId)
    //  and append a <rect> inside <clipPath>
        .append('rect');

@timelyportfolio
Copy link
Contributor Author

Thanks for the clarification. I understand what you are saying, and I'll attempt to demonstrate what is happening in this instance with a narrow CodePen.

@timelyportfolio
Copy link
Contributor Author

@etpinard, I think this CodePen might explain my statement. Notice how only the second p updates. The same thing is happening with clippath. If we look at the original codepen demo of problem after we push the resize button,

image

and since clipPath === null then the attributes are not changed.

image

@etpinard
Copy link
Contributor

@timelyportfolio nice catch.

This block should be

var clipPath = fullLayout._topdefs.selectAll('#' + clipId)
        .data([0]);

clipPath.enter().append('clipPath')
        .attr('id', clipId)
        .append('rect')

my mistake.

@timelyportfolio
Copy link
Contributor Author

So, I think the only thing left is we need to somehow pass the new scrollheight to scrollHandler. Any suggestions here besides remove and add back the eventListeners or some lazy evaluation of a new scrollheight function? In the screenshot below, we can see that scrollheight still carries the same value on resize.

image

@etpinard
Copy link
Contributor

Any suggestions here besides remove and add back the eventListeners

I don't. I'd would simply remove/add the handlers.

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

No branches or pull requests

3 participants