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

Correct wrong element targeting on hover in shadow DOM #5256

Merged
merged 3 commits into from
Jan 5, 2021

Conversation

dbluhm
Copy link
Contributor

@dbluhm dbluhm commented Nov 6, 2020

When using plotly inside of a shadow DOM, the calculations used to determine if the pointer has moved off of the graph would use the wrong element to determine the bounding box. This was resulting in a flicker in the hover text as it would find that the mouse pointer had apparently moved off the graph when it actually hadn't and the next mousemove event would immediately redraw the hover text.

This PR uses the Event.composedPath() method of the Event interface to determine the correct element from which to base bounding box calculations.

In my limited testing, I found that occasionally a mousemove event originating from a shadow DOM would get raised that did not have a properly formed composedPath() -- it would return an empty list. I haven't been able to nail down exactly why but for those rare cases, the early return ensures the hover text doesn't flicker.

I'm pretty new to Plotly but I tried to do my research so hopefully this solution isn't too naive. More than happy to work with maintainers to get this to a point where it can be accepted.

Thanks and excellent work on Plotly!

When using plotly inside of a shadow DOM, the calculations used to
determine if the pointer has moved off of the graph would use the wrong
element to determine the bounding box.
Copy link
Contributor

@archmoj archmoj left a comment

Choose a reason for hiding this comment

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

Thanks very much for the PR.
Is there an open issue related to this problem?
If not, please open an issue including a codepen to illustrate the bug while using the last (not latest) plotly.js version similar to this codepen.

Then you may also reuse that to add a test to lock down the bug here:
https://github.com/plotly/plotly.js/blob/master/test/jasmine/tests/hover_label_test.js

@@ -333,7 +333,12 @@ function _hover(gd, evt, subplot, noHoverEvent) {
return;
}

var dbb = evt.target.getBoundingClientRect();
// Discover event target, traversing open shadow roots.
var target = evt.composedPath && evt.composedPath()[0];
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you also investigated a possible workaround for IE?

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 haven't -- I'll do so and update with my findings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After some investigation, I think the best we can do in the case of IE is simply fallback to the original behavior of directly using the event target.

Suggested change
var target = evt.composedPath && evt.composedPath()[0];
var target = evt.composedPath && evt.composedPath()[0];
if(!target) {
target = evt.target;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. Please commit your suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or simply

var target = (evt.composedPath && evt.composedPath()[0]) || evt.target;

@dbluhm in addition to hover (fx), there are some other places e.g. dragelement, shapes and mapbox which evt.target is used. Could you please investigate if there is a issue that similar fix may help?

Copy link
Contributor

Choose a reason for hiding this comment

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

ping @dbluhm

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I'll take a look! Apologies for the slow response -- working to address this issue just as time arises. Thanks for your patience!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks @dbluhm - this looks like a great solution! My hunch is that in order to generalize this efficiently to all the places we use event.target it will warrant a function like Lib.getTarget(event), perhaps in lib/dom (and note that then this needs to be exposed in lib/index)

@archmoj archmoj added status: reviewable bug something broken community community contribution labels Nov 6, 2020
@dbluhm
Copy link
Contributor Author

dbluhm commented Nov 6, 2020

I don't believe there is an open issue for this currently; I'll be sure to open one and include a codepen. I'll also work on getting a test for it in hover_label_test.js. Thanks for the prompt feedback!

@dbluhm
Copy link
Contributor Author

dbluhm commented Nov 14, 2020

Opened #5277 to track the issue solved by this PR.

@archmoj archmoj added this to the v1.58.0 milestone Nov 22, 2020
@archmoj archmoj requested a review from alexcjohnson November 25, 2020 19:01
@archmoj
Copy link
Contributor

archmoj commented Dec 1, 2020

@dbluhm to avoid conflicts namely with mapbox hover please merge upstream/master into this branch before generalizing this logic to few other places.

@archmoj archmoj removed this from the v1.58.0 milestone Dec 2, 2020
@dbluhm
Copy link
Contributor Author

dbluhm commented Jan 4, 2021

As a brief update, this PR has been moved to my backlog due to some changes in my development priorities associated with an employer change. I'm still hoping to resolve these issues and get this merged but my timeline is less certain now. My primary obstacle at the moment is lack of familiarity with the testing framework (I don't spend too much time in JavaScript) so I've struggled to recreate the conditions needed to exhibit this behavior in tests with my relatively limited time. Still open to feedback and any direction you'd like to give 🙂

@archmoj
Copy link
Contributor

archmoj commented Jan 5, 2021

Thanks @dbluhm for the contribution.
💃

Note: I'll work on the remaining items in a following PR.

@archmoj archmoj merged commit f024f68 into plotly:master Jan 5, 2021
@archmoj archmoj added this to the 1.59.0 milestone Jan 5, 2021
@dbluhm dbluhm deleted the fix/shadow-dom-targeting branch January 29, 2021 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken community community contribution
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants