2

I have made a JS/HTML5 game which is controlled by keyboard, I like to make it embeddable like flash games, but when I embed it inside an iframe it only capture keyboard events when iframe is focused. If user interact with other element on the page iframe will lose focus and the game will not receive events.

How can I make it always capture keyboard events from inside iframe and avoid defaults like flash games? For example using space for firing instead of scrolling, from inside iframe.

Why down vote?

Ali Shakiba
  • 20,549
  • 18
  • 61
  • 88
  • I have an app which works just fine inside an iframe. It uses arrow keys, escape etc. Just need to have focus on the iframe, otherwise the host page captures the key events. Where exactly is your problem? How are you coding it? Using jQuery? Are you preventing the default (e.preventDefault) ? Definitely need more information. – Abhitalks May 10 '14 at 14:39
  • @abhitalks Using anything would be fine. The problem is it's almost impossible to keep iframe focused. If user interact with another element on the page, iframe will lose focus (and unlike flash games it won't receive events anymore). – Ali Shakiba May 10 '14 at 14:56
  • why in the world would you make this ? you can use fullscreen , or a custom script to automatically focus the iframe , but this is really a wrong question to ask in here. – ProllyGeek May 10 '14 at 15:18
  • @ProllyGeek That's how web games work, they are embedded. Keeping iframe focused stops many other elements on page functioning correctly. – Ali Shakiba May 10 '14 at 15:24
  • @JohnS play the game here , and prove your point : http://www.flatvsrealism.com/ – ProllyGeek May 10 '14 at 15:26
  • @ProllyGeek Which point? You can make your game fullscreen but all major online game publishers/portals (I know) publish games embedded. – Ali Shakiba May 10 '14 at 15:47
  • 3
    _“Keeping iframe focused stops many other elements on page functioning correctly”_ – and you think your iframe capturing all events without being focused would not do so? // I don’t see the real problem here – as long as the user is playing your game, why would they click somewhere else (so that your iframe would lose focus)? And if they do, they obviously want to interact with the surrounding page, so you preventing that would be nonsense. – CBroe May 10 '14 at 16:20
  • Seems like there is a solution using Prototype http://stackoverflow.com/questions/998286/how-to-get-iframe-to-listen-to-same-events-as-parent-and-fire-the-same-handlers it uses a specific observe method created by the prototype library but you could look into it to find out how they pass events around as all you need is for your game to detect if it is embedded and make it listen to the parent events instead. – GillesC May 15 '14 at 14:48
  • you can attach key event listeners to body of host page and pass that events to your iframe – sandyJoshi May 16 '14 at 01:54
  • 1
    Without having control of the page embedding the iframe. The best option is to either allow fullscreen or to pause the game when focus is lost and resume when focus is regained. Possibly with an option for the user to window.open the iframe to put a new window on top - you can get pretty clever with it and use screen offsets to put it in ~ the same place. – technosaurus May 17 '14 at 03:44

3 Answers3

4

This is one way to do it:

function focus()
{
    var iframe = document.getElementById('iframe-element')
    iframe.contentWindow.focus();
}

window.setInterval(focus, 100); 

or jQuery:

$("body").click(function(){
  $('#iframe-element').focus();
});

This needs to be run on the host page of course, because allowing an embedded iframe to steal focus is not in the nature of browser/webpage security.

Good luck.

Ryan Weinstein
  • 7,015
  • 4
  • 17
  • 23
2

This is not normally possible because of a browser security feature called the Same-Origin-Policy. 1

Basically, one page on one domain can not interact with or intercept the events of another page because it would present a security risk. Imagine opening a frame to a user's bank account and then capturing keypresses they did in that frame -- obviously that would be a Very Bad Thing (tm). It works the other way around too, the contents of a frame can not see events on the parent page unless they are on the same domain.

Now browsers do still want to allow you to interact with contents within a frame. So when you start interacting with contents of one frame, the other frame loses any awareness of what's going on.

So, after all this, you're probably still wondering how to address your problem. Here are a few good options.

  1. Instead of loading your game in an iframe, have the user embed it into their current page instead. You could have them do this by either providing them with the code to your game and having them place it in their page, or by providing a script tag that loads code from your own server and places the game into their page.

  2. Use Cross-Document messaging 2, A relatively new browser feature that allows pages to get around the normal Same-Origin-Policy restrictions. Basically, with Cross Document Messaging, you can run javascript on the parent page that sends events into the page within the iframe.

Gdeglin
  • 12,432
  • 5
  • 49
  • 65
  • It seems to me that while the security of prohibiting cross-domain iframe communication is good, it is also useless because the malicious site could just proxy and spoof your site – Nick Sotiros May 17 '14 at 06:59
  • While that's true, this would be worse because the user may already be logged in to the site within the frame and therefore feel safe inputting additional sensitive info, or see a login prompt with a valid "security image" (as some banking sites use). But in any case, the same origin policy is also used to prevent other kinds of cross-domain interaction that could, for instance, be used for xss or session hijacking. – Gdeglin May 19 '14 at 21:26
0

This is not a complete Solution but an Idea....

What about capturing all Keyboard events on the site and then decide (e.g. by checking the value of some invisible input/element within the iframe) if a game is in progress. If it is, preventDefault of the action and trigger some custom event inside the iframe and just make your game listen for the custom events too...

Actually I just found this: Access elements of parent window from iframe That way you could apply my solution from within the Iframe and check for clicks/keys on its parent

Regards

Community
  • 1
  • 1
user3567992
  • 592
  • 5
  • 15