javascriptgwtvisibilitychange

How to implement browser tab visibility in gwt


Motivation: I have a periodic call to server to supply fresh data to user. But my program can be run in multiply tabs. I want to decrease the load on the server by detecting which tab is active. If I can reach the state direcly or put the state of visibility of the tab to a variable, my periodic code can check that variable and decide not to call server.

Javascript code: I have found relevant code on javascipt at here

document.addEventListener("visibilitychange", () => {
  var tabIsVisible = !document.hidden;
  console.log("tabIsVisible: " + tabIsVisible);   
});

In GWT I can rewrite the code as this

public static native void addEventListener_visibilityChange(){
    $doc.addEventListener("visibilitychange", () => {
      var tabIsVisible = !document.hidden;
      console.log("tabIsVisible: " + tabIsVisible);
    });
}

But it gives compile error

Compiling module com.tugalsan.app.table.App
   Tracing compile failure path for type 'com.tugalsan.api.gui.client.browser.TGC_BrowserTabUtils'
      [ERROR] Errors in 'jar:file:/C:/Users/me/.m2/repository/com/tugalsan/com.tugalsan.api.gui/1.0-SNAPSHOT/com.tugalsan.api.gui-1.0-SNAPSHOT.jar!/com/tugalsan/api/gui/client/browser/TGC_BrowserTabUtils.java'
         [ERROR] Line 8: syntax error
>         $doc.addEventListener("visibilitychange", () => {

And, how can I even reach the tabIsVisible variable?


Solution

  • The => arrow syntax is not supported in JSNI. That said, JSNI is discouraged for the last 10 or so years, prefer JsInterop instead.

    Javascript event handling like this translates pretty easily to JsInterop with Java 8+ syntax. I'm also going to assume you have elemental2-dom in your project, a set of bindings to DOM apis that the browser provides. With one import for elemental2.dom.DomGlobal we can now write

    DomGlobal.document.addEventListener("visibilitychange", event -> {
      // most coding styles prefer boolean over var:
      var tabIsVisible = !DomGlobal.document.hidden;
      DomGlobal.console.log("tabIsVisible: " + tabIsVisible);   
    });
    

    The only differences are:

    Technically you can keep var and not use boolean, but many coding styles prefer being more specific in simple cases like this. I like to stick with var for the first pass of translating from JS to Java, but will usually replace with types before committing any code.