[MCSD 70-480] HTML5 API

Skoro zapowiedziałem ostatnie zmiany to pora też wrócić z cyklem o HTMLu i Java Scriptcie 🙂 dzisiaj kilka słów na temat HTMLowych API, które swego czasu szumnie były opisywane, a dzisiaj już widać, że nie do końca się to wszystko sprawdziło i z trzech które dzisiaj opiszę właściwie tylko jedno jest regularnie przez programistów używane.

Storage API

Lokalny kontener na podręczne dane użytkownika. Miał być killerem ciastek, bo nie wędruje w te i we wte pomiędzy przyglądarka, a serwerem. Ostatecznie traktowany bardziej jako ciekawostka o której wszyscy słyszeli, ale mało kto używał.

Kontenery mamy dwa. Jeden to localStorage, który potrafi zapamiętać dane do momentu kiedy ich nie usuniemy (przez kod albo przez wyczyszczenie przeglądarki), a drugi to sessionStorage, który pamięta zapisane wartości do momentu zamknięcia przeglądarki.

Do obu mamy dokładnie taki sam dostęp i takie same rzeczy możemy w nim przechowywać, czyli stringi w postaci klucz wartość. Jednak czy to nas ogranicza w jakiś sposób? Oczywiście, absolutnie nie. No może oprócz tego, że pojemność tych kontenerów to tylko (albo aż, bo to przecież tylko stringi) 10 MB. Piszę, że stringi nas nie ogarniczają, bo mamy JSONy (jak to mawiał mój kolega ‚Dżonsony’ 🙂 ) i do takiego typu sobie przekształcamy każdy obiekt i sprawa załatwiona.

A co do samego dostępu to mamy 5 głównych metod, których w tym przypadku używamy.

Metoda Opis
setItem Dodaje parę klucz/wartość do kontenera. Jeżeli nie ma wartości o takim kluczu to para zostaje dodana, jeżeli istnieje to zostaje nadpisana.
getItem Zwraca parę klucz/wartość na podstawie zadanego klucza bądź indeksu.
clear Czyści cały kontener.
key Zwraca klucz zapisany pod zadanym indeksem.
removeItem Usuwa z kontenera parę klucz/wartość

Jak widać nazwy metod same w sobie są całkiem intuicyjne, także nie będę się zbytnio nad nimi rozwodził. Dla porządku krótki kod prezentujący zastosowanie wszystkich metod. Zadanie do domu: przekleić do edytora teksu, zapisać jako html i się pobawić. Jak coś będzie niejasne to dawać znać, będziemy tłumaczyć.

AppCache API

Kolejne API, którego zamysł był całkiem niezły, ale do wykorzystania pewnie kilka lat temu. Przeczytałem o AppCache, że powstało po to żeby trzymać część strony internetowej w wersji offlinowej co miało być pomocne szczególnie na urządzeniach mobilnych. Oj to musiała być stara książka/artykuł. Jak tak sobie myślę to mój telefon ma w tej chwili bardziej niezawodny Internet niż mój laptop podłączony do domowej sieci WiFi. No ale co tak. Kilka lat temu jeszcze nie było tak kolorowo z zasięgiem i czasami faktycznie mogło to się przydać. W tej chwili może w przypadku jakiś gier napisanych w JS na telefony? Nie wiem. To jedyne co mi przychodzi do głowy. No ale do rzeczy.

AppCache jak już wspomniałem jest API służącym do zapisywania plików strony (od htmli po jpgi) na urządzeniu po to aby strona taka była dostępna nawet kiedy nie jesteśmy w sieci.

Zaczynamy od tego, że musimy na samym początku powiedzieć naszej przeglądarce, że chcemy skorzystać z takiej możliwości. Dlatego juz w samym tagu html definiujemy coś takiego:

<html manifest="webApp.appcache">
...
</html>

Jedna uwaga! Rozszerzenie .appcache nie jest wymagane. Może to być i .dupa, ale przyjęło się to pierwsze i żeby użyć drugiego to trzeba w serwerze webowym pogrzebać i pozmieniać akceptowalne rozszerzenia.

Skoro to już mamy to przydałoby się stworzyć sam plik z manifestem. Plik taki MUSI zawierać nagłówek w postaci CACHE MANIFEST i może zawierać sekcje CACHE, NETWORK i FALLBACK.

Przykładowy plik może wyglądać tak:

CACHE MANIFEST
CACHE
/pages/page1.html
/pages/page2.html
NETWORK:
login.html
FALLBACK:
login.html fallback-login.html

I teraz co oznaczają poszczególne sekcje?

CACHE jest najbardziej oczywisty. Wszystkie strony, obrazki, cssy itp. są oznaczane do ściągnięcia tak aby były dostępne w razie rozłączenia z siecią.

NETWORK jest sekcją w której definiujemy, które strony absolutnie wymagają podłączenia do internetu. Jeżeli coś jest tutaj wymienione nie może być wymienione w CACHU i jeżeli użytkownik będzie próbował się dostać na tę stronę to bez względu na wszystko przeglądarka będzie próbowała uzyskać połączenie z Internetem.

FALLBACK jest sekcją w której możemy zdefiniować co się stanie jeżeli użytkownik będzie chciał się dostać na stronę która nie została ściągnięta. W przykładzie powyżej jeżeli użytkownik będzie chciał się zalogować to zostanie przekierowany na stronę, która zapewne powie mu, że jest to w tej chwili niemożliwe zamiast wyświetlać błąd o braku połączenia. Możemy też napisać coś w stylu

/resources /picture.jpg

co oznacza, że jeżeli nie możemy dostać się do jakiegokolwiek obrazka znajdujące się w folderze recources to zostanie wyświetlony obrazek zastępczy. Ważna uwaga! Elementy zastępcze nie muszą być definiowane w sekcji CACHE. Zostaną one automatycznie zaciągnięte.

No i jak mamy manifest to zaczyna się w końcu drobne kodowanie. W JSie mamy zdefiniowany globalny obiekt window.applicationCache. W obiekcie to co dla nas najważniejsze to właściwość status, która może przybierać następujące wartości:

Status Opis
Uncached Aplikacja nie jest skojarzona z żadnym manifestem
Idle Proces cachowania jest bezczynny. Używana jest ostatnia ściągnięta kopia cache.
Checking Wartości z manifestu są w trakcie sprawdzania, czy nie istnieje nowsza wersja
Downloading Wartości z manifestu są w trakcie ściągania
UpdateReady Wartości z manifestu zostały ściągnięte i są gotowe do zastąpienia starszej wersji
Obsolete Manifest jest niedostępny, więc cache zostaje usunięty

Oprócz statusu mamy również dwie metody:

Metoda Opis
swapCache Aplikacja nie jest skojarzona z żadnym manifestem
update Proces cachowania jest bezczynny. Używana jest ostatnia ściągnięta kopia cache.

No i co? No i przy wejściu na stronę robimy update, a jak już się ściągnie to robimy swapCache i już mamy po swojej stronie wszystko czego potrzebujemy. Żeby wiedzieć kiedy zrobić podmiankę mamy event onupdateready. Proste nie?

window.onload = function () {
    var appCache = window.applicationCache;
    appCache.oncached = function (e) { alert("cache successfully downloaded."); };
    appCache.onupdateready = function (e) { appCache.swapCache(); };
}

Oczywiście eventów mamy więcej:

Event Opis
onchecking Przeglądarka jest w trakcie sprawdzania czy istnieje nowsza wersja manifestu, bądź jest cachowana po raz pierwszy
onnoupdate Manifest nie ma żadnych dostępnych aktualizacji
ondownloading Przeglądarka jest w trakcie ściągania manifestu
onprogress Pliki z manifestu są zapisywane.
oncached Ściąganie cachu zostało zakończone
onupdateready Pliki z manifestu zostały ściągnięte i metoda swapCache może zostać wywołana
onobsolete Manifest nie jest już dostępny
onerror Proces zgłosił błąd.

Także w razie potrzeby możemy przygotować bardziej zaawansowane scenariusze.

Geolocation API

No i w końcu last but not least API do lokalizacji.

Chyba wszyscy korzystający z Internetu od pewnego czasu (heh w sumie od paru lat 🙂 ) zauważyli, że czasem przeglądarka daje znać, że chce poznać naszą lokalizację. Objawia się to mniej więcej takim komunikatem:

Oznacza to z całkiem dużym prawdopodobieństwem, że autorzy strony korzystają z Geolocation API. API to korzysta między innymi z GPSa w naszych urządzeniach, ale też z lokalizacji routera sieci w której się znajdujemy czy za pomocą sieci telefonicznej.

W przypadku tego API znowu mamy globalny obiekt JS window.navigator.geolocation. Obiekt ten posiada przede wszystkim dwie metody, które będą nas interesowały:

Metoda Opis
getCurrentPosition Metoda, która pobiera 1 raz aktualną lokalizację urządzenia.
watchPosition Metoda, która pobiera w sposób ciągły lokalizację urządzenia za każdym razem kiedy ta się zmieni.

Obie metody przyjmują trzy takie same parametry:

Parametry
positionCallback
positionErrorCallback
positionOptions

Pierwszy z nich jest wymagany i jest to metoda, która jest wywoływana jeśli z sukcesem uda się pobrać aktualną pozycję. Druga i trzecia są opcjonalne i są to odpowiednio: metoda wywoływana w przypadku błędu i obiekt z dodatkowymi opcjami.

Może zacznę od końca, czyli od opcji właśnie. Nie ma ich zbyt dużo, bo tylko 3 i są to:

Opcje pozycji Opis
enableHighAccuracy Jeśli ustawione na true metoda zżera więcej zasobów, ale stara się zlokalizować urządzenie najdokładniej jak to możliwe. Standardowo ustawione na false.
timeout Wartość wyrażona w milisekundach decydująca o tym jak długo metoda ma próbować pobrać lokalizację. 0 wskazuje na czas nieskończony.
maximumAge Jeżeli ta wartość (wyrażona w milisekundach) jest ustawiona to lokalizacja jest cachowana i jest używana przez wyrażony czas.

No to chyba pora na prosty przykład zwykłego pobrania lokalizacji:

window.onload = function () {
    var geoLocator = window.navigator.geolocation;
    var posOptions = {enableHighAccuracy: true,timeout: 45000};
    geoLocator.getCurrentPosition(successPosition, errorPosition,
        posOptions);
}
function successPosition(pos) {
    var sp = document.createElement("p");
    sp.innerText = "Latitude: " + pos.coords.latitude +
        " Longitude: " + pos.coords.longitude;
    document.getElementById("geoResults").appendChild(sp);
}
function errorPosition(err) {
    var sp = document.createElement("p");
    sp.innerText = "error: " + err.message; + " code: " + err.code;
    document.getElementById("geoResults").appendChild(sp);
}

Jak to mówią as simple as that.

Nieco ciekawiej wygląda sprawa w przypadku śledzenia. Tak jak wspomniałem parametry się nie zmieniają, tylko wywołanie tak zwanych callbacków się różni. Watcher wywołuje callback za każdym razem kiedy wykryje zmianę pozycji. Teraz już wiadomo jak napisać proste Endomondo 🙂

Tylko jak to cholerstwo teraz zatrzymać? Nic prostszego.

Na początku kiedy wywołamy watchPosition to metoda zwraca nam obiekt Watcher, który musimy sobie przypisać do zmiennej. Kiedy już chcemy przestać śledzić użytkownika wywołujemy:

geoLocator.clearWatch(watcher);

Aha no i jeszcze na koniec. Geolocation jest fajne bo zwraca nam nie tylko długość i szerokość geograficzną ale też wysokość na jakiej się znajdujemy i kierunek w którym się przemieszczamy.

Polecam się tym pobawić, a na dzisiaj to by było na tyle 🙂

Related posts