2

I've implemented a HTML page that wraps some extra functionality around an iframe. The iframe contains a reveal.js presentation. Whenever a key on the keyboard is pressed and the parent frame (not the iframe) is focused, I want to forward the event to the iframe (e.g. rightArrow is pressed (parent focused) --> rightArrow is executed in the iframe, as if it was focused - eventually going to the next slide).

I am in charge of both frames and they will be eventually hosted at the same domain. For developing reasons, I started a browser with disabled security features.

I tried several JQuery based methods, like

$(document).keydown((event) => {
    var e = jQuery.Event( "keydown", { keyCode: event.keyCode } );
    $('#revealPresentation')[0].contentWindow.$('body').trigger(e);
  });

and wasn't able to get them to work. I stepped back to plain JS methods:

$(document).keydown((event) => {
    var newEvent = new KeyboardEvent("keydown", {
      key: event.originalEvent.key, code: event.originalEvent.code, 
      charCode: event.originalEvent.charCode, keyCode: event.originalEvent.keyCode,
      which: event.originalEvent.which
    });
    document.getElementById("revealPresentation")
    .contentWindow.document.dispatchEvent(newEvent);
  });

that also aren't working. I guess I'm dispatching the event against the wrong element, but I don't know what's the right element or if anything else might be wrong. Is anyone able to provide a working example or point me into the right direction? I already found some similar questions, but they mostly deal with custom events and added the appropriate event listener to the iframe code. I don't want to change the iframe in any way.

Solution: According to this post WebKit has a bug that eventually won't fill the keyCode property of a newly created KeyboardEvent. Exactly this property gets evaluated in reveal.js in order to trigger some actions (like next slide). I was able to implement a workaround (code was suggested in the mentioned post):

document.addEventListener('keydown', (e) => {
            let frame = document.getElementById('revealPresentation').contentDocument;
            let newEvent = new Event('keydown', {key: e.key, code: e.code, composed: true, charCode: e.charCode, keyCode: e.keyCode, which: e.which, bubbles: true, cancelable: true, which: e.keyCode});
            newEvent.keyCode = e.keyCode;
            newEvent.which = e.keyCode;
            frame.dispatchEvent(newEvent);
        });
Roy
  • 303
  • 4
  • 13

1 Answers1

3

That's strange, your code seems nothing wrong to me. I also tested it in plain javascript, and everything just worked fine.

Example: https://jsfiddle.net/d7ap1ntz/

listener in parent frame

document.addEventListener('keydown', e => {
  const frame = /*your iframe element*/;

  // dispatch a new event
  frame.contentDocument.dispatchEvent(
    new KeyboardEvent('keydown', {key: e.key})
  );
})

listener in iframe

document.addEventListener('keydown', e => {
  console.log('keydown in iframe: ' + e.key)
})

Could it possibly caused by the listener in your iframe?

Note: Iframe and its listener are manually inserted in the above example, but it also works via normal HTML tags.

Microloft
  • 345
  • 1
  • 7
  • Thank you very much! This pointed me into the right direction. I've added a solution to the question. It was a combination of WebKit bug + reveal.js uses deprecated features. – Roy Aug 07 '17 at 13:26