Can I control two browser windows with one HTML5 app?
Asked Answered
M

2

15

I'd like my HTML5 app to draw onto two different screens. This (I think) means that I need have two distinct browser windows, one on each screen. Is this possible? It seems that I'd really have to load the same app into two windows, and somehow have the windows communicate to each other. I couldn't find an example of how to accomplish this. How can I make it happen?

For extra wonderfulness: There may not be a server involved, just an app served locally from the filesystem.

Margherita answered 11/3, 2011 at 19:35 Comment(1)
Possible duplicate of Communication between tabs or windowsBryon
R
19

There's no need for a messy polling infrastructure using local storage or (shudder) cookies. Assuming the two pages are served from the same domain, it is trivial to implement cross-window communication so long as the second window is opened by the first.

In your main window: (click here for JSFiddle demo and here for the secondary page's code)

var win2;
function openSecondaryWindow() {
   return win2 = window.open('win2.html','secondary','width=300,height=100');
}

$(function() {

    if (!openSecondaryWindow()) // Try to open the window.  This will likely be blocked by a popup blocker (unless you disable it).
        $(document.body) // If it is blocked, clicking a link usually allows the popup to be spawned.
        .prepend('<a href="#">Popup blocked.  Click here to open the secondary window.</a>')
        .click(function() { openSecondaryWindow(); return false; });

    $('#somelink').click(function() {
        if (win2) win2.doSomething(); // Obviously, you'll need to define doSomething in the second page
        else alert('The secondary window is not open.');
        return false;
    });
});

Once the secondary window has been opened by your main window, win2 will refer to the window object of the second page – in other words, the page's global scope. You'll have access to all of the functions and variables you've defined in the second page.

Thus, you can pass data through function calls.

win2.update({ key: 'value', ... });

From your secondary window, you can call back to functions in the main window through the opener property, which will refer to the window object of your main window. (This is demonstrated in the JSFiddle demo.)


Update: Intercom is a library that uses local storage to implement broadcast messaging between windows. Local storage fires an event (onstorage) when data changes, so polling is not actually necessary. Intercom allows all pages on a domain to communicate, regardless of how they were opened.

Roup answered 11/3, 2011 at 21:32 Comment(1)
I was trying to think about maintaining state between opening and closing windows etc, but yours is a much better solution for the requirements Ned presented in his post. Good stuff.Harbot
H
0

This is probably something that you could use websockets for, have each window send its info back to the app and then have them updated, but those are not supported across all browsers and in fact I believe are currently removed from most builds due to security issues with the spec.

For offline apps if they were on the same domain, which I'm assuming they would be locally, you could use local storage or even cookies and then have the apps poll for changes to the storage api?

I have been doing some experiments with offline local storage myself recently and I'm able to maintain state between windows with Chrome locally, in firefox this does not work, but I believe it is fixed in the FF4 RC

Edit 2:

Slapped together a quick and dirty proof of concept in two files:

Index 1:

<body>

<div id="result">x</div>

</body>
<script type="text/javascript">
var i = 0;

function update(){  
    setTimeout(function(){
        localStorage.setItem("bar", i);
        document.getElementById('result').innerHTML = "localstorage set to " + localStorage.getItem("bar");
        i++;
        console.log(i);
        update();          
    }, 2000);
}

update();

</script>

Index 2:

<body>

<div id="result">s</div>

</body>
<script type="text/javascript">

function update(){  
    setTimeout(function(){
        document.getElementById('result').innerHTML = localStorage.getItem("bar");    
        update();
    }, 1000);
}

update();

</script>

Opening them both up in different windows in Chrome locally, the second one will display the state that is set by the loop in the first window. Still not working in FireFox 4 I found (a Mozilla Dev swore to me yesterday that offline local storage works now, oh well). You can probably getting it working in IE via http://www.modernizr.com/ but I have yet to test that.

Harbot answered 11/3, 2011 at 19:53 Comment(2)
This is an interesting idea. I may not have a server involved (I updated the question), though.Margherita
It's an interesting problem, I updated my answer with some more thoughts, perhaps using local storage or even cookies would be the way to go?Harbot

© 2022 - 2024 — McMap. All rights reserved.