Používáme PageVisibility API

Když je vaše aplikace viditelná uživateli? Jak na to může reagovat? Ukážeme vám možnosti W3C specifikace s názvem PageVisibility API.

Tento text je zkráceným překladem článku Using the PageVisibility API, jehož autorem je Joe Marini a je zde zveřejněn pod licencí CC-BY-3.0.

Úvod

Technologie, kterou si dnes představíme, není tak revoluční jako třeba WebGL nebo WebAudio, ale může zlepšit user experience vašich aplikací. Page Visibility API nabízí jednoduchou, ale užitečnou funkci – vaše aplikace bude vědět, kdy je pro uživatele viditelná. Ukažme si několik možností využití:

  • Webová stránka, která opakovaně získává informace ze serveru, může prodloužit interval aktualizací, když si ji nikdo zrovna nezobrazuje.
  • Stránka zobrazující rotující carousel s obrázky nebo video může animace zastavit, dokud si ji uživatel opět nezobrazí.
  • Aplikace může chtít uživateli zobrazit upozornění jen v případě, že není zrovna viditelná.

Představení Page Visilibility API jste si mohli na Zdrojáku před časem přečíst v článku Page Visibility API: Kouká na mě vůbec někdo? V dnešním textu najdete další možnosti jeho použití.

Význam tohoto API poroste s rozšiřováním mobilních zařízení a potřebou šetřit uživatelovu baterii. V době psaní tohoto textu je specifikace ve stádiu Candidate Recommendation a nabízí jak vlastnosti pro detekci viditelnosti dokumentu, tak událost pro reagování na změnu viditelnosti dokumentu.

Vlastnosti viditelnosti dokumentu

Aktuální verze specifikace PageVisibilityAPI definuje dvě vlastnosti objektu document:  logickouhidden a výčtovou visibilityState . Vlastnost visibilityState může nabývat jedné ze čtyř hodnot: „hidden“, „visible“, „prerender“ a „unloaded“.

Pozn.: tyto vlastnosti jsou zatím implementované s vendor prefixy, musíte tedy použít prefixované verze, např. „webkitHidden“ a „webkitVisibilityState“ dokud se specifikace nestane oficiální a prohlížeče nenaimplementují neprefixované verze.

Jak asi čekáte, vlastnost hidden vrací true, když není dokument vůbec vidět, obvykle když je minimalizován, v neaktivním panelu prohlížeče, uživatel zamkl obrazovku apod. Vlastnost má hodnotu false, pokud je alespoň část dokumentu viditelná alespoň na jednom zobrazovacím zařízení.

Jak na vendor prefixy

Abychom se mohli soustředit na vlastní kód místo na práci s prefixy, připravil jsem pomocnou funkci.

function getHiddenProp(){
    var prefixes = ['webkit','moz','ms','o'];

    // pokud je podporován 'hidden' vrať ho
    if ('hidden' in document) return 'hidden';

    // jinak projdi známé vendor prefixy
    for (var i = 0; i < prefixes.length; i++){
        if ((prefixes[i] + 'Hidden') in document)
            return prefixes[i] + 'Hidden';
    }

    // jinak není podporován
    return null;
}

Nyní můžeme napsat funkci isHidden() fungující napříč prohlížeči.

function isHidden() {
    var prop = getHiddenProp();
    if (!prop) return false;

    return document[prop];
}

Pro detailnější rozlišení viditelnosti dokumentu můžete použít vlastnost visibilityState. Může obsahovat jednu ze čtyř hodnot:

  • "hidden": dokument není vůbec vidět
  • "visible": dokument je alespoň částečně viditelný na alespoň jednom zobrazovacím zařízení
  • "prerender": dokument je nahrán mimo obrazovku a není viditelný (tato vlastnost je volitelná; ne všechny prohlížeče ji musí podporovat)
  • "unloaded": dokument bude odstraněn z paměti (tato vlastnost je volitelná; ne všechny prohlížeče ji musí podporovat)

Událost VisibilityChange

Událost visibilitychange je vyvolána, kdykoliv se změní stav viditelnosti dokumentu.

// použij název vlasnosti pro vygenerování prefixovaného názvu události
var visProp = getHiddenProp();
if (visProp) {
  var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
  document.addEventListener(evtname, visChange);
}

function visChange() {
   var txtFld = document.getElementById('visChangeText');

   if (txtFld) {
      if (isHidden())
         txtFld.value += "Tab je skrytý!n";
      else
         txtFld.value += "Tab je viditelný!n";
   }
}

Praktické příklady

Zobraz upozornění, jen když je panel prohlížeče skrytý

API W3C Notifications umožňuje zobrazovat uživateli upozornění. Ale to může být pěkně otravné, pokud se uživatel na stránku již dívá. Pomocí PageVisibility API mu je zobrazíme jen, když je panel s aplikací skrytý.

window.addEventListener("load", function notifyDemo() {
   var propName = "";
   var oNotify=null;
   var visProp = getHiddenProp();

   document.getElementById("notify-demo").addEventListener("click", function() {
      oNotify = null;
      if (window.webkitNotifications) {
         setTimeout(showNotification, 5000);

         if (window.webkitNotifications.checkPermission() == 0) { // 0 = PERMISSION_ALLOWED
            oNotify = window.webkitNotifications.createNotification("", "Notification", "Tohle je upozornění!");
         }
      }
   });

   document.getElementById("notify-enable").addEventListener("click", function() {
      window.webkitNotifications.requestPermission();
   });

   function showNotification() {
      if (document[visProp] && window.webkitNotifications && oNotify) {
         oNotify.show();
      }
      else {
         alert("Tohle je upozornění!");
      }
   }
});

Odkládáme započtení přístupu v Google Analytics, když je stránka před-renderována

Některé prohlížeče, např. Google Chrome, můžou stránky před-renderovávat (pokud vás to zajímá, přečtěte si podrobný popis). V takovém případě jsou staženy všechny zdroje, které stránka používá, včetně všech skriptů. Řada stránek používá k měření návštěvnosti Google Analytics, ovšem jeho údaje mohou být zkresleny, pokud je stránka před-renderována, ale nikdy už není uživatelem doopravdy zobrazena.

To můžeme napravit za pomocí PageVisibility API. Obvyklý kód Google Analytics vypadá takto:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);

V takovém případě je událost _trackPageview vždy započtena, i když si uživatel stránku vůbec nezobrazil. Upravený skript vypadá takto:

var bHavePV = getHiddenProp();
var bInitialShow = false;
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);

if (bHavePV) {
   document.addEventListener("visibilityChange", handleVisEvt);
}
else {
   _gaq.push(['_trackPageview']); // prohlížeč nepodporuje PageVisibility, započti stránku normálně
}

function handleVisEvt() {
   if (document.visibilityState == "prerender") {
      _trackEvent("pagedata", "prerender"); // někoho můžou zajímat čísla o pre-renderování stránek
   }
   if (document.visibilityState == "visible" && !bInitialShow) {
      bInitialShow = true; // podruhé už tento kód nespouštěj
      _gaq.push(['_trackPageview']);
   }
}

Závěr

Page Visibility API je chybějícím kouskem skládanky pro tvorbu skvělých aplikací, které rozumně zachází s uživatelovými zdroji. 

Další odkazy

Vystudoval jsem biochemii. Vymyslel a založil Zdroják. Aktuálně ho vedu. Nejsem váš hodný tatínek, který vás bude brát za ručičku, ale zlý moderátor diskusí. Smiřte se s tím!

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 5

Přehled komentářů

Oxymoron Vendor prefixy
Martin Hassman Re: Vendor prefixy
tom reklamy
sachy Bezpečnost
ooo google analytics patří do adblocku
Zdroj: https://www.zdrojak.cz/?p=3749