I have an iframe of Google Slides which I embedded in my web app.
The iframe implementation is:
<iframe ref={slidesRef} src={src} width='100%' height='100%' allowFullScreen={true}/>
I want to listen to click events on the main web page (while the iframe is not necessarily in focus), then create their corresponding keypress events - and pass them to the iframe, thus making the slideshow iframe to trigger and react to the user key presses.
I tried something like this:
function onButtonClick(e) {
e.stopPropagation();
slidesRef.current.focus();
slidesRef.current.dispatchEvent(new KeyboardEvent('keypress', {
key: 'ArrowRight', which : 39
}));
}
But it doesn't work - it only focuses on the iframe, but doesn't send the arrow key event.
I saw some solutions using the parent document inside the iframe or sending messages with postMessage
, but I can't add any code inside my iframe since its origin is an external link.
Due to restrictions imposed by the Same Origin Policy implemented by all modern browsers, I don't think you'll be able to do what you intend to do - this is not related to React, the browser will just not allow for a script on the parent window to trigger any kind DOM event on the child iframe
programmatically.
That's why you saw references to the postMessage
API when you searched for a solution. That API was introduced to enable cross-origin communication between window objects in a safer, more controlled manner.
The code you've posted would execute any event listener that might appended to the parent window's DOM iframe element, so something like this:
<iframe onkeydown="console.log('keydow')" src="https://google/..." />
Should be triggered by your code. But this is happening on the parent window, the javascript "running" within iframe
(i.e. Google's code responsible for changing the current slide) doesn't have access nor is able to "see" that event.
If both the iframe and your webpage were serviced from the same domain (in other words, if they had the same "origin"), what I think you're trying to achieve would be something more in the lines of:
function onButtonClick(e) {
e.stopPropagation()
// Note that we're retrieving a DOM element from the iframe's window object,
// not the parent's one
const iframeBody = slidesRef.current.contentDocument.body;
// Get an element on the iframe's document which has an event listener attached
// to it that changes the current slide
const sliderEl = iframeBody.querySelector('...')
sliderEl.click()
}
But again this'd only work if both the iframe
and parent
window were considered to have the "same origin" by the browser (which isn't your case).