12

I have an app that is basically just a wrapper for an internal company website. The idea is to easily load the website in its own window on my Chromebook, that way it won't unload when RAM gets low.

I have a very simple app with a single WebView that consumes an entire app window. The problem is, whenever I switch away from the window and come back, the webview has lost focus. This is particularly annoying because it's a chat app, and I'd like to start talking immediately upon alt-tabbing back to the window.

I've looked into focusing the webview each time the window receives focus, but the disconnect between Window (from chrome.windows) and AppWindow (from chrome.app.window) makes this nontrivial. The event that I need only exists for Window objects, but I can only definitively obtain the current AppWindow. I could theoretically get the currently active Window when the app first launches, but that seems hackish and unreliable.

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Chat App</title>
    <link rel="stylesheet" href="styles.css">
  </head>

  <body>
    <webview src="https://example.com/" id="chat"></webview>
  </body>
</html>

background.js

chrome.app.runtime.onLaunched.addListener(function(launchData) {
  chrome.app.window.create(
    'index.html',
    {
      id: 'chat'
    }
  );
});

styles.css

Making the webview consume the entire window was a bit tricky; I had to use some redundant CSS properties to get it to work properly.

html, body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#chat {
  border: 0 none;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
Zenexer
  • 18,788
  • 9
  • 71
  • 77
  • Is there only one text input field on the page? If so, you might try setting the focus whenever the input receives `blur` event. – Ed Ballot Jul 06 '15 at 00:55
  • Maybe this could be of use to you. http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active – Mark Verkiel Jul 07 '15 at 12:31

1 Answers1

5

You can achieve this simply with the Page Visibility API. You can use it to add an event listener and check the document.hidden state to return focus to the chat box. You can also do other things, like play an audio alert when you receive chat messages when the tab is not visible.

In this example, I've also added an event listener to the first chat box so if focus is lost, it tries to get it again. This is a rather heavy-handed approach, but you can adjust your logic to suit requirements.

JSFiddle

function handleVisibilityChange() {
    console.log(document.hidden);
    if (!document.hidden) {
        chatFocus();
    }
}

function chatFocus() {
    document.getElementById("ChatBox1").focus();
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);
document.getElementById("ChatBox1").addEventListener("blur", chatFocus, true);
<input type="text" id="ChatBox1" placeholder="ChatBox1">
<input type="text" id="ChatBox2" placeholder="ChatBox2">

Testing this on Chrome, you'll find that if you switch to another tab, or minimize the window, the visibilitychange event will be fired. If you just switch to another window, though, it won't consider the page to be hidden. You can also make use of window.onblur to listen for when the page loses focus in general.

PS. About your 'tricky' redundant CSS: specifying left: 0 and width: 100% should be all you need (right: 0 shouldn't be necessary), but in addition to that, text fields tend to have border and padding etc. so in order to ensure the field doesn't end up wider than its container, you need to set box-sizing: border-box so that padding and borders are included when determining its size. It's a trick that solves many problems in CSS.

BoffinBrain
  • 6,337
  • 6
  • 33
  • 59
  • Thanks; I'll give it a test tomorrow. This API seems to be a bit finicky in Chrome, but hopefully it'll work properly for an app window. – Zenexer Jul 14 '15 at 22:18
  • Let me know if you manage to find any specific cases where using the above events doesn't work. – BoffinBrain Jul 15 '15 at 19:17