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

XYChart Tooltip not working in Iframe #1838

Open
lapidus opened this issue May 26, 2024 · 5 comments · May be fixed by #1848
Open

XYChart Tooltip not working in Iframe #1838

lapidus opened this issue May 26, 2024 · 5 comments · May be fixed by #1848

Comments

@lapidus
Copy link

lapidus commented May 26, 2024

Here's a minimal example:
CodeSandbox

Appreciated if you could take a quick look @williaster 🙏 Is it possible to workaround?

I'm essentially putting the standard XYChart example inside an iframe, and the tooltip is not firing.

@lapidus
Copy link
Author

lapidus commented May 28, 2024

@hshoff, @williaster, @mtlewis

Sorry for pestering. Anyone of you who could help on a consulting basis on the above and some other things? Or happy to donate to the project or charity for help with this one. 🙏 It's proven a bit of a blocker for us.

@lapidus
Copy link
Author

lapidus commented Jun 1, 2024

I did some more debugging @williaster. The mouseover is firing as expected but the svgPoint = null:

image

This seems to be because the useEventHandlers is not called. Essentially the XYChart is not rerendering.
If I put a log here, it will only be called ca: 10 times and then not rerender on mouseover, even if the event is emitted:

export default function XYChart< .... 

console.log("Is it calling useEventHandlers?")

useEventHandlers({
    dataKey:
      pointerEventsDataKey === "nearest"
        ? POINTER_EVENTS_NEAREST
        : POINTER_EVENTS_ALL,
    onPointerMove,
    onPointerOut,
    onPointerUp,
    onPointerDown,
    allowedSources: allowedEventSources,
  })

What is it that should cause the XYChart to rerender on mousemove fundamentally? Is it that the TooltipProvider changes? Or is there some other effect that is not triggering here?

@lapidus
Copy link
Author

lapidus commented Jun 2, 2024

@williaster

Found the issue!

"event.nativeEvent instanceof Event" is not working as expected within the iframe context:

(event instanceof Event || ('nativeEvent' in event && event.nativeEvent instanceof Event))

AI helped me explain why ...

The instanceof operator checks if an object is an instance of a specific class or constructor function. However, it may not work as expected across different JavaScript contexts, such as different iframes, due to the way JavaScript handles different global environments.

When you use instanceof inside an iframe, the constructor function (e.g., Event) is from the iframe's global context, which is different from the global context of the parent window. Consequently, objects created in one context do not pass the instanceof check for constructor functions in another context.

Here’s why this happens:

Separate Global Objects: Each iframe has its own global object, which includes its own versions of Event, Array, Object, and other built-in constructors. Therefore, window.Event in the main document is different from iframe.contentWindow.Event.

Different References: An event created in the main document will be an instance of window.Event, but not of iframe.contentWindow.Event, even though both refer to the Event constructor.

To check if an object is an instance of Event across different contexts, you can use a combination of techniques:

Duck Typing: Check for properties and methods that are unique to the Event object.
Cross-context Checks: Use the constructor.name property to check the type by name.
Using typeof and Object.prototype.toString.call(): These can sometimes help identify the object type more reliably across different contexts.

When I patch this, the Tooltips show up as expected. But the next issue I'm facing is with: getXAndYFromEvent where these will be need to be offset for the iFrame scenario I believe:

x: event.clientX,
y: event.clientY

I think this is a smaller fix to account for this scenario.

Can I submit a PR that aims to fix both of these? Thank you!

@williaster
Copy link
Collaborator

Hey @lapidus thanks much for digging in here - was initially surprised at this behavior but that makes complete sense.

We would happily review a PR with the 2x fixes mentioned.

@lapidus
Copy link
Author

lapidus commented Jun 3, 2024

Thank you @williaster!

I made some progress on the PR:
#1848

Now the tooltip shows almost correctly.
But I can't get it to position itself adequately. I think it has to do with this part:

// To correctly position itself in a Portal, the tooltip must know its container bounds
// this is done by rendering an invisible node whose ref can be used to find its parentElement

I tried correcting for the iframe offsets here:
https://github.com/airbnb/visx/pull/1848/files#diff-be158cfaccba14687300842e06a1700307de86e6727d08beb2c112eaa49c6813R171

Appreciate if you can take a closer look. Thank you.

@williaster williaster linked a pull request Jun 6, 2024 that will close this 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 a pull request may close this issue.

2 participants