Přejít k navigační liště

Zdroják » Různé » Používáme PageVisibility API

Používáme PageVisibility API

Články Různé, Webdesign

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

Komentáře

Subscribe
Upozornit na
guest
5 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Oxymoron

Jak to vypadá, tak místo toho, aby vendor prefixy práci usnadňovaly, tak jí spíš komplikují.

tom

Bohužel to bude taky další věc, kterou budou muset obcházet různé AdBlocky a podobně. Je to sice malý, ale přece jen určitý zásah do „soukromí“, a určitě budou snahy ji využít komerčně.

sachy

Aplikace zjistí, že není vidět a provede redirect na podvrhnutý relogin – session timeout… Kdo by odolal, vždyt na tom panelu ta správná aplikace opravdu byla…

ooo

akorát to je smetí

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.

Pocta C64

Za prvopočátek své programátorské kariéry vděčím počítači Commodore 64. Tehdy jsem genialitu návrhu nemohl docenit. Dnes dokážu lehce nahlédnout pod pokličku. Chtěl bych se o to s vámi podělit a vzdát mu hold.