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

Zdroják » Webdesign » Page Visibility API: Kouká na mě vůbec někdo?

Page Visibility API: Kouká na mě vůbec někdo?

Články Webdesign

Možná znáte výrok: „Vesmír existuje, jen když se na něj někdo dívá“. Mottem dnes popisované novinky – Page Visibility API – by mohla být parafráze tohoto výroku, nějak takto: „Stránka pracuje, jen když si ji někdo prohlíží“. Jak to celé funguje a jaký to má praktický význam? Ukážeme si v článku.

Novinka, dostupná zatím v prohlížeči Chrome od verze 13 umožňuje obsloužit programem změny ve viditelnosti stránky. Page Visibility API umožňuje programátorovi zjistit, jestli je stránka právě viditelná nebo ne. K tomu umožňuje na změny viditelnosti reagovat.

Prohlížeče dnes už celkem běžně nabízejí prohlížení v panelech. Jednotlivé otevřené stránky, respektive skripty v nich spuštěné, běží nezávisle na sobě, a především běží nejen na stránce, na kterou se uživatel právě dívá v aktivním panelu, ale i na ostatních. Pokud máte v panelech otevřené stránky, které se pravidelně aktualizují, kde běží nějaké náročné skripty, bujné animace či se přehrává video, představuje to poměrně velkou zátěž, která navíc běží „do zdi“. Zcela zbytečně se zatěžuje procesor, a u mobilních zařízení bude jistě mít nemalý vliv na výdrž baterie.

Implementace v Chrome

Page Visibility API je, jak jsme si už říkali, implementován v Chrome od verze 13 a jeho implementace je „vendor-prefixed“, viz http://code.google.com/chro­me/whitepapers/pagevisibi­lity.html. Funkce si proto popíšeme v podobě, v jaké jsou dostupné v prohlížeči Chrome, tedy s prefixem „webkit“, a mějme, prosím, na paměti, že po jejich rozšíření přijde sjednocení na „neprefixové“ verzi – použijte tedy nějaký „shim“, kterým si tyto funkce zpřístupníte v „normovaném“ tvaru.

Page Visibility API přidává dva atributy objektu document  – atribut hidden a atribut visibilityState. V implementaci Chrome jsou dostupné jako document.webkitHidden a document.webkitVisibilityState.

webkitHidden je boolovská hodnota, která je true v případě, že stránka není vidět – tedy v případech, kdy je prohlížeč minimalizován, kdy je počítač zamknutý, kdy je stránka v panelu, který je na pozadí, dokonce i v případě, kdy je prohlížeč minimalizován a zobrazuje se jen jeho náhled. Hodnotu „False“ bude mít tehdy, když bude stránka zobrazená na popředí.

Na místě je podotknout, že v ostatních prohlížečích bude hodnota „undefined“, která je vyhodnocena jako „false“. Před prací s tímto atributem je rozumné udělat kontrolu pomocí  if (typeof document.webkitHidden === "undefined")

Předchozí atribut určuje, jestli stránku někdo může sledovat (jestli je viditelná), nebo zda je někde skrytá. Další atribut, document.webkitVisibilityState vrací řetězec, který udává přesněji stav, v jakém se stránka nachází:

hidden
Stránka je skrytá, není vidět, nezobrazuje se atd.
visible
Stránka je viditelná
prerender
Stránka byla vykreslena do cache, ještě ale není zobrazená
preview
Stránka se zobrazuje pouze v systémovém náhledu (např. při najetí kurzorem myši na minimalizovaný prohlížeč v panelu / docku) – tuto hodnotu Chrome zatím neimplementuje

Hodnoty „prerender“ a „preview“ nemusí prohlížeče poskytovat. Preferovaný způsob rozhodování, zda je stránka vidět nebo není, je podle atributu hidden (webkitHidden).

Vidí mě někdo?

Informace o viditelnosti samy o sobě nejsou až tak užitečné. Proto Page Visibility API nabízí i novou událost – visibilitychange (v implementaci Chrome jako „ webkitvisibilitychange “). Jak už název napovídá, tato událost je vyvolána ve chvíli, kdy se změní stav viditelnosti. Událost můžeme skriptem odchytit a zareagovat na ni.

Co si s touto informací skript má počít? Můžete např. snížit frekvenci periodického dotazování serveru a načítání novinek – když je stránka s chatem na pozadí nebo minimalizovaná, jistě není zapotřebí ji obnovovat co deset sekund, delší interval postačí. V případě, že se přehrává na stránce video, můžete jej „zapauzovat“ – viz pěkné demo od Sama Duttona. Pusťte si jej (v Chrome 13+, samosebou) a sledujte, co se bude dít, když si přepnete do jiného panelu, když prohlížeč minimalizujete atd.

Pro zajímavost – zdrojový kód výše odkázaného příkladu:

var videoElement = document.getElementById("videoElement");

// if the page is hidden, pause the video
// if the page is shown, play the video
function handleVisibilityChange() {
    if (document.webkitHidden) {
        videoElement.pause();
    } else {
        videoElement.play();
    }
}

// warn if the browser doesn't support document.webkitHidden
if (typeof document.webkitHidden === "undefined") {
    alert("This demo requires a browser such as Google Chrome 13 that supports the Page Visibility API.");
}

// avoid errors from browsers that don't support addEventListener
if (typeof document.addEventListener !== "undefined") {
    // handle page visibility change
    // see https://developer.mozilla.org/en/API/PageVisibility/Page_Visibility_API
    document.addEventListener("webkitvisibilitychange",  handleVisibilityChange, false);

    // revert to existing favicon for site when the page is closed
    // otherwise the favicon will remain as paused.png
    window.addEventListener("unload", function(){
        favicon.change('/favicon.ico');
    }, false);

    // when the video pauses, set the favicon
    videoElement.addEventListener("pause", function(){
        favicon.change('images/paused.png');
    }, false);

    // when the video plays, set the favicon
    videoElement.addEventListener("play", function(){
        favicon.change('images/playing.png');
    }, false);

    // set the document (tab) title from the current video time
    videoElement.addEventListener("timeupdate", function(){
        document.title = Math.floor(videoElement.currentTime) + " second(s)";
    }, false);
}

Využití najde v budoucnu toto API v nejrůznějších webových aplikacích, kde pomůže „snížit odběr“ ve chvílích, kdy budou aplikace minimalizované či „vypnuté“. Určitě naleznete další případy, v nichž má smysl, aby skript ve chvílích, kdy stránku nikdo nesleduje, takříkajíc „ubral plyn“.

Odkazy ke čtení

Komentáře

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

Je někde uveden důvod, proč se příslušné API váže k objektu document, když dle mého prvního odhadu by vedlo na objekt window? (příznávám, jsem líný to hledat ;-))

Martin Soušek

Tak snad uživatel není hlupák, ne?

Třeba jen u videa poslouchám zvuk a u toho pracuju. Nebo přeskakuju nepřetočitelné reklamy a mezitím si něco čtu. Nebo mám nějaký jiný důvod na stránku zrovna nekoukat.

Implementace tohoto nesmyslu povede jen k tomu, že se na onvisibilitychange navěsí reklamní kódy a jakmile přepnu na nějaký tab, tak všechny reklamy začnou skákat a volat „klikni sem“ :)

JakubS

Někteří uživatelé bohužel hlupáci jsou. :-) A naopak někteří programátoři naštěstí nejsou hlupáci.

– Jsem si jistý že tvůrci přehrávačů budou s touto novinkou nakládat velmi citlivě.
– Ad druhá připomínka: ale vždyť to se v určité míře děje/může dít už dnes :-)

Velmi bych ocenil pokud by se automaticky deaktivovaly FLASHové bannery které zrovna nejsou viditelné (šetřilo by to výkon = baterku)

biggringo

Vzpomněl jsem si na ten typ útoků, kdy se stránka po nějaké prodlevě (kdy na ni uživatel už pravděpodobně nekouká) promění ve falešnou přihlašovací stránku třeba na Google.

Tohle API je docela dobrý pomocník, dá se to vůbec nějak ošetřit?

v6ak

Záleží, co myslíte tím ošetřením. Jak je zřejmé, toto API pouze zjednodušuje tvorbu takovýchto stránek, ale i bez něj by si šlo poradit (mousemove, keydown, keyup, blur, focus, …).

Blokovat tato API by bylo zřejmě neefektivní. Uživatel se prostě musí podívat, kam to heslo zadává. Před časem jsem dával na bugzillu Mozilly návrh UI (včetně primitivních kreseb), které by tomu mohlo pomoci, ale nesetkal jsem se s odezvou. Každopádně, cesta IMHO vede tudy.

A může tomu pomoci do jisté míry i App Tab – pokud se o to pokusí neapptabová stránka, uživateli to bude divné, čímž se může okruh stránek s potenciálem útočit zmenšit.

Jakub Vrána

Hodnota undefined se vyhodnocuje jako false. Stejně jako několik dalších hodnot.

Porovnání výsledku typeof s řetězcem "undefined" je třeba jen u běžných proměnných (kde přímý přístup na rozdíl od vlastností objektu vyvolá chybu).

undefined = true/false

Ano mas pravdu, ale v kontexte veci autor asi chcel povedat, ze ked dam test:
if (document.web­kitHidden) {} else {}
napr. v Mozille, tak spusti false vetvu „if“, cize okno je podla tohto prikazu viditelne.

Jakub Vrána

Spustí se větev else. A to je podle mě naprosto v pořádku – když se nemohu spolehnout na to, že je okno skryté, tak se chovám, jako kdyby bylo vidět.

Jakub Vrána

Ve starších prohlížečích se pro podobnou funkci dá použít kombinace událostí window.onblur a window.onfocus. Já to v Admineru používám pro zobrazení ikony, pokud probíhá práce. Někde jsem to také viděl použité pro zastavení časového odpočítávadla – to mi přijde chytré, i když protivné.

v6ak

Přesně to mě taky napadlo, když jsem to četl. Jde asi o nějaké vylepšení těchto dvou událostí, je možné, že některé prohlížeče blurem reagovat třeba u zamčení počítače, ale i tak je to IMHO schopno postihnout zajímavé procento případů. (BTW, pokud nechávám počítač zamknutý a neuspaný, tak mě ta nepatrná úspora energie nebo lepší responsivnes nevytrhne…)

Jakub Vrána

Podle mě onblur nastane i v případě, kdy focus ztratí celé okno (ale je stále vidět). Kdežto visibilitychange jen v případě, kdy stránka skutečně zmizí (nejčastěji asi přepnutím na jiný panel, ale třeba i minimalizací okna).

Ale to jen tak hádám, specifikaci jsem nečetl, ani jsem to nezkoušel – takhle bych to navrhl já.

juraj

Máš pravdu, je to tak. A aby toho nebolo málo, niektoré prehliadače ešte podporujú dvojicu udalostí DOMFocusIn/DOM­FocusOut (ako focus/blur, len prebubláva), iné zasa focusin/focusout (tiež prebubláva, len nefunguje na window).

v6ak

To je fakt. Já mám ve zvyku si okna maximalizovat a nejlépe jim ještě odstranit „dekoraci“ (ty rámečky, tutilek apod.), takže jsem si neuvědomil, že by neaktivní okno mohlo být viditelné.

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.