title: How to detect when iOS app goes the background using HTML and JavaScript
body: <p>I need to know when my GWT web application goes to the background on an iPad.  The application is not a native iOS app, but rather has a "wrapper" around it allowing it to run as an app.  The wrapper is written in Swift and uses the UIWebView.</p>
  
  <p>The application needs to know when the home button is pressed in order to trigger some logic that if a user goes outside of the app then the app should display a warning screen upon returning to the app (i.e., receives focus).  This logic should be true no matter how the app loses focus, unless they explicitly exit the app.  I cannot explain why that functionality is necessary due to security purposes, but suffice to say this isn't a general audience type of application; there are specific scenarios under which this app is used.</p>
  
  <p>I've tried using document.hasFocus(), but it always returns true, even though this same logic works on chromebooks, Windows machines, and macbooks.</p>
  
  <p>I added visibilityChange listener, but the visibilityState is always visible.  I also added event listeners for pageshow and pagehide.  A debug console statement prints out for the pageshow eventlistener, but never for the pagehide eventlistener.  Lastly, I added an event listener for the unload event, but I never see my console statement print out for it.</p>
  
  <p>Based on various searches and articles I've read, it seems mobile Safari ignores most, if not all of these listeners, and the only option I haven't seem to have tried is using timers which I'd prefer to avoid.  Also, I need an HTML/Javascript solution as I can only modify my application and cannnot modify the "wrapper" app.  I'm using an iPad Pro with iOS 11.4.</p>
  
  <p>Here's just one of the many articles that I referenced:
  <a href="https://stackoverflow.com/questions/4656387/how-to-detect-in-ios-webapp-when-switching-back-to-safari-from-background">How to detect in iOS webapp when switching back to Safari from background?
  </a></p>
  
  <p>The relevant code from the application is below.  Any thoughts or suggestions are greatly appreciated!</p>
  
  <pre><code>/*************************** page visibility ***************************/
  var hidden, visibilityChange;
      if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
      hidden = "hidden";
      visibilityChange = "visibilitychange";
  } else if (typeof document.msHidden !== "undefined") {
      hidden = "msHidden";
      visibilityChange = "msvisibilitychange";
  } else if (typeof document.webkitHidden !== "undefined") {
      hidden = "webkitHidden";
      visibilityChange = "webkitvisibilitychange";
  }
  
  console.log("debug - common.js - customBlur - visibilityChange : " + visibilityChange + " | hidden: " + hidden);
  
  
  if (typeof document.addEventListener === "undefined" || hidden === undefined) {
      console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
  } else {
  // Handle page visibility change
      document.addEventListener(visibilityChange, handleVisibilityChange, false);
  }
  
  var forceBlur = false;
  function handleVisibilityChange() {
  if (document.visibilityState == 'hidden') {
      console.log("debug - common.js - handleVisibilityChange - calling delayBlur");
      forceBlur = true;
  } else console.log("debug - common.js - handleVisibilityChange - document not hidden");
  }
  
  /*************************** pageshow and pagehide ***************************/
  var forcePhBlur = false;
  window.addEventListener("pageshow", function(evt){
      console.log("debug - common.js - pageshow - showing the page");
  }, false);
  window.addEventListener("pagehide", function(evt){
      console.log("debug - common.js - pagehide - hiding the page");
      forcePhBlur = true;
  }, false);
  
  /*************************** unload ***************************/
  var forceUlBlur = false;
  window.addEventListener("unload", function(evt){
      console.log("debug - common.js - unload - unloading the page");
      window.onblur = true;
      forceUlBlur = true;
  }, false);
  
  /*************************** custom blur logic ***************************/
  function delayCheck() {
      console.log("debug - common.js - delayCheck - document.hasFocus(): " +             
      document.hasFocus());
      console.log("debug - common.js - delayCheck - document.hidden: " +        document.hidden);
      if (!document.hasFocus() || document.hidden || forceBlur) {
          delayBlur();  //implemented in the java code
      }
  }
  
  var delayVar;
  
  function customBlur() {
  console.log("debug - common.js - customBlur - document.hasFocus(): " + document.hasFocus());
  console.log("debug - common.js - customBlur - document.hidden: " + document.hidden);
  console.log("debug - common.js - customBlur - Document.visibilityState : " + document.visibilityState);
  console.log("debug - common.js - customBlur - forceBlur : " + forceBlur);
  console.log("debug - common.js - customBlur - forcePhBlur : " + forcePhBlur);
  console.log("debug - common.js - customBlur - forceUlBlur : " + forceUlBlur);
  
  if (!document.hasFocus() || document.hidden || forceBlur) {
      console.log("debug - common.js - customBlur - calling delayCheck to blur");
      delayVar = window.setTimeout(delayCheck, 200);
  }
  </code></pre>