?

Cześć!

(naciśnij spację, żeby kontynuować)

Niewielkie wymagania na początek

Tym razem, wyjątkowo, do pełnego przetestowania omawianych zagadnień będą nam potrzebne konkretne narzędzia*:

* Narzędzia te nie są absolutnie wymagane, jednak niektórych ćwiczeń nie uda się bez nich dziś zrobić.

Dziś zapraszamy na ciasteczka
z lokalnego pudełeczka

Autorem zdjęcia jest MICHELE - Grafika na licencji Creative Commons CC BY-SA 2.0

Po co ktoś miał by zapisywać dane w mojej przeglądarce?
Nie stać ich na twarde dyski?

  • statystyki odwiedzin
  • zakupy internetowe bez zakładania konta
  • automatyczny login
  • przechowywanie informacji w formularzu, żeby nie zniknęły po odświeżeniu strony
  • wyświetlanie informacji o ciasteczkach
  • przyspieszenie uruchamiania aplikacji / strony
  • śledzenie naszych zachowań w sieci / profilowanie treści

Dlaczego informuje się o używaniu ciastek?

Jednym z zastosowań ciastek jest śledzenie naszych poczynań w sieci

UE uznała, że jeżeli będzie wymagana zgoda użytkownika na zapisanie ciastka, to problem będzie rozwiązany

Dyrektywa 2009/136/EC Rady Europy nakłada na dostawców treści internetowych, którzy chcą zapisywać dane w przeglądarce (nie tylko przez cookie, ale też przez inne mechanizmy, jak localStorage) obowiązek uzyskania zgody na taką czynność

I co z tego wynikło?

W praktyce nic się nie zmieniło. Czy ktoś, kiedyś nie zgodził się na zapisanie ciastka?

Ale za to musimy wiedzieć, jak zrobić informację o cookies

Jak można zapisać dane w przeglądarce?

  • HTTP Cookies
  • Web Storage
  • IndexedDB (o tym nie dzisiaj)

Co w ciastku siedzi?

Autorem zdjęcia jest Robert Couse-Baker - Grafika na licencji Creative Commons CC BY 2.0

Ciastko (profesjonalnie nazywa się "HTTP Cookie") to po prostu fragment danych, które są zapisywane przez stronę internetową w przeglądarce i które mogą być odczytane przez serwer, który tę stronę wygenerował.

Jest to jeden z najstarszych i najbardziej rozpowszechnionych sposobów zapisywania danych w przeglądarce.

Do działania nie wymaga JavaScript.

Obejrzyjmy nasze ciastka

Przypomnienie: narzędzia programisty w Chrome włączamy przez F12 (Command+Option+I na macOS)

Anatomia ciastka

  • Każde ciastko składa się przynajmniej z nazwy i wartości.
  • Nazwa i wartość to napisy
  • Dodatkowo przeglądarka zapamiętuje, do której domeny należy dane ciastko, żeby wiedzieć, któremu serwerowi może je udostępnić
  • Serwer widzi tylko nazwę i wartość ciastka
  • Pozostałe atrybuty są widoczne tylko dla przeglądarki i służą zarządzaniu ciastkami
  • Spośród tych atrybutów tym razem najbardziej interesuje nas nie liczba kalorii, ale data ważności

Ciasteczka w Twojej przeglądarce

Do manipulacji ciasteczkami służy document.cookie

Odczytanie wszystkich ciasteczek

var allCookies = document.cookie;
// np. => 'nazwa1=wartość1; nazwa2=wartość2; nazwa3=wartość3'
        

Zapisanie ciasteczka*

document.cookie = 'nazwa=wartosc; max-age=3600';

* document.cookie działa bardziej jak wpłatomat, niż normalna zmienna - zapisanie ciasteczka nie nadpisuje innych ciasteczek.

Web Storage

Wprowadzony w ramach standardu HTML5, a więc stosunkowo młoda technologia (IE8+)

Widoczny tylko dla przeglądarki (ciastka są widoczne także dla serwera)

Można w nim przechować więcej danych, ok. 1000 razy więcej niż w ciastkach

Duuuużo łatwiejszy w użyciu

Do działania wymaga JavaScript

Web Storage w Twojej przeglądarce

sessionStorage
Oddzielna przestrzeń na dane dla każdego źródła dokumentów*, dostępna podczas sesji przeglądarki (tak długo jak przeglądarka jest otwarta, wliczając przeładowania strony i odtwarzanie stron po zamknięciu przeglądarki).
localStorage
Robi to samo, ale dane przechowywane są nawet po zamknięciu przeglądarki.

* protokół://domena:port (np: https://www.mojadomena.pl:6666)

Podstawowe użycie local storage

Zapisywanie danych do local storage

localStorage.setItem('nazwa', 'wartość');

Odczyt z local storage i zapisanie do zmiennej

var zmienna = localStorage.getItem('nazwa');

Usuwanie danych z local storage

localStorage.removeItem('nazwa');

Usuwanie całej zawartości local storage

localStorage.clear();

Do maszyn!

Zdjęcie w domenie publicznej. Autorem jest Tech. Sgt. Keith Brown

Przygotujmy miejsce do pracy

Źródła

Stąd pobierzesz paczkę z kodem źródłowym

Po wypakowaniu znajdziesz w głównym folderze kilka plików. Nas w tej chwili interesuje webstorage.html.

Nasz własny serwer 1/2

Jeśli używasz narzędzi zaproponowanych na początku, otwórz przeglądarkę Chrome i wybierz zakładkę Apps

Następnie wybierz aplikację Web Server

Nasz własny serwer 2/2

Otworzy się nowe okienko, a w nim wybieramy katalog, w którym mamy rozpakowane pliki z kodami źródłowymi.

Przy domyślnych ustawieniach wystarczy w nowej zakładce otworzyć stronę o adresie http://127.0.0.1:8887

Bez serwera

Przejdź do katalogu, w którym mamy rozpakowane pliki z kodami źródłowymi.

Otwórz w przeglądarce plik webstorage.html

Na razie bez zaglądania do kodu

Otwarta strona webstorage.html zawiera prosty formularz, za pomocą którego możemy zmieniać kolor tła i tekstu.

Sprawdźmy przez chwilę, jak to działa.

Są tu również dwa przyciski, które nic nie robią (na razie)

Otwórzmy plik webstorage.html w swoim ulubionym edytorze i popatrzmy przez chwilę na kod.

Pierwsze zadanie

Celem naszego pierwszego zadania będzie zapisanie po naciśnięciu przycisku Save aktualnie ustawionych kolorów w localStorage i sessionStorage

  • kolor tła zapiszmy w localStorage
  • kolor tekstu zapiszmy w sessionStorage

Jak się do tego zabrać?

Może tak:

  1. Pobierz aktualny kolor tła
  2. Zapisz wartość w lokalStorage
  3. Pobierz aktualny kolor tekstu
  4. Zapisz wartość w sessionStorage

To nie było trudne, tylko skąd wziąć aktualne wartości kolorów?

Spróbujmy napisać funkcję saveColors, która realizuje pierwsze zadanie!

Czy możemy wykorzystać istniejący już kod?

Gotowe?

Wyszło nam pewnie coś takiego:

function saveColors() {
  localStorage.setItem(
    'backgroundColor',
    document.body.style.backgroundColor
  );
  sessionStorage.setItem('color', document.body.style.color);
}

Kto pamięta co zrobić, żeby kliknięcie w przycisk uruchomiło naszą funkcję? Ręka do góry!

document
  .querySelector('#save')
  .addEventListener('click', saveColors);

Dodajmy ten kod poniżej naszej funkcji i sprawdźmy...

No dobrze, ale jak właściwie sprawdzić, czy coś się wydarzyło?

Otwórzmy narzędzia programisty i zajrzyjmy do zakładki Aplikacja

Drugie zadanie

Skoro potrafimy już zapisać dane, to nic nas nie jest w stanie powstrzymać przed ich odczytaniem!

Celem naszego drugiego zadania będzie odczytanie po naciśnięciu przycisku Restore kolorów zapisanych w localStorage i sessionStorage oraz ustawienie ich jako aktualnych na stronie.

Znowu potrzebny jest plan!

  1. Odczytaj wartość zapisaną w lokalStorage
  2. Ustaw ją jako aktualny kolor tła
  3. Odczytaj wartość zapisaną w sessionStorage
  4. Ustaw ją jako aktualny kolor tekstu

Spróbujmy napisać funkcję restoreColors, która realizuje drugie zadanie!

Czy możemy wykorzystać istniejący już kod?

Gotowe?

Wyszło nam pewnie coś takiego:

function restoreColors() {
  const bgColor = localStorage.getItem('backgroundColor');
  const fgColor = sessionStorage.getItem('color');

  setBackground(bgColor);
  setForeground(fgColor);
}

Prawda, że łatwo się pisze, jak możemy wykorzystać istniejący kod?!

Pozostało nam tylko połączenie funkcji restoreColors ze zdarzeniem kliknięcia na przycisk Restore

document
  .querySelector('#restore')
  .addEventListener('click', restoreColors);

Dodajmy ten kod poniżej naszej funkcji i sprawdźmy działanie strony.

Udało się!

Sprawdźmy w praktyce jak działa Web Storage

Test #1

  1. Ustaw nowe kolory tła i tekstu
  2. Zapisz je w Web Storage naciskając Save
  3. Otwórz w nowej zakładce drugą kopię strony webstorage.html
  4. Odtwórz kolory w otwartym przed chwilą dokumencie naciskając Restore.

Co zaobserwowałaś?

Test #2

  1. Ustaw nowe kolory tła i tekstu w drugiej zakładce
  2. Zapisz je w Web Storage naciskając Save
  3. Otwórz pierwszą zakładkę ze stronę webstorage.html
  4. Naciśnij przycisk Restore

Co zaobserwowałaś?

Zdarzenia Web Storage

(tylko jeśli mamy działający nasz serwer)

Poniżej ramki z formularzem znajduje się odnośnik, zróbmy z niego użytek!

W nowej zakładce powinien się otworzyć dokument webstoragemonitor.html. Umieśćmy oba dokumenty obok siebie, tak aby były jednocześnie widoczne.

Czas na magię - zmieńmy kolor tła i zapiszmy nową wartość w Web Storage.

Jak to działa?

Otwórzmy dokument webstoragemonitor.html w naszym ulubionym edytorze i zobaczmy, co tam się dzieje.

Czy wszystko jasne? Nie wygląda to aż tak magicznie ;)

Spróbujmy zrobić jakiś użytek z tego, co widzimy.

Trzecie zadanie

Sprawmy, aby strona webstoragemonitor.html zmieniła kolor tła za każdym razem, gdy zmieniamy go i zapisujemy na stronie webstorage.html.

Napiszmy funkcję setStyle, która ustawi kolor tła dokumentu za kadym razem, gdy pojawi się zdarzenie związane z Web Storage.

200kcal później...

function setStyle(ev) {
  document.body.style[ev.key] = ev.newValue;
}

window.addEventListener('storage', setStyle);

Web Storage mamy w jednym paluszku!

Pora na ciastka

(tylko jeśli mamy działający nasz serwer)

Autorem zdjęcia jest mackenzie - Grafika na licencji Creative Commons CC BY-ND 2.0

Zapisujemy różne informacje w przeglądarce i w myśl dyrektywy unijnej powinniśmy poprosić o zgodę,
co niezwłocznie uczynimy.

W tym celu wykorzystamy nieużywany jeszcze element aside na stronie webstorage.html

Zawiera on notyfikację o ciasteczku oraz przycisk do jej zamknięcia.

Jedyny problem jest taki, że ta notyfikacja się nie wyświetla na stronie.

Sprawdźmy dlaczego.

Prośba o zgodę na zapisywanie danych w przeglądarce

Pomyślmy nad scenariuszem, który powinien być realizowany podczas ładowania strony

Jakie powinniśmy uwzględnić wymagania?

  • Pokaż notyfikację o ciasteczkach, jeśli użytkownik jest u nas pierwszy raz.
  • Schowaj notyfikację, gdy użytkownik wyrazi zgodę na ciasteczka.
  • Nie nękaj go więcej notyfikacjami (powiedzmy przez nadchodzący rok).

Scenariusz, który chcemy zrealizować

  1. Sprawdź, czy użytkowik ma zapisane nasze magiczne ciasteczko
  2. Jeśli nie, natychmiast pokaż notyfikację o ciasteczkach
  3. Gdy wyrazi zgodę, ukryj notyfikację i zapisz nasze magiczne ciasteczko z rocznym terminem przydatności do spożycia

Krok 1. Sprawdź ciasteczko

Napiszmy funkcję isCookieSet, która przyjmie nazwę ciasteczka jako jedyny parametr i zwróci wartość logiczną true / false mówiącą o tym, czy ciasteczko o podanej nazwie jest ustawione.

Jedno z możliwych rozwiązań:

function isCookieSet(name) {
  const cookies = document.cookie.split('; ');
  for (let i = 0; i < cookies.length; i += 1) {
    if (cookies[i].startsWith(name + '=')) {
      return true;
    }
  }
  return false;
}

Krok 2. Pokaż notyfikację o ciasteczkach

Napiszmy funkcję showCookieNotice, która pokaże element aside oraz połączmy jej działanie z funkcją z kroku pierwszego.

Skorzystamy tu z element.classList i classList.remove()

function showCookieNotice() {
  document.querySelector('#cookie-notice').classList.remove('hide');
}

if ( !isCookieSet('accept-cookies') ) {
  showCookieNotice();
}

Krok 3. Ukryj notyfikację i zapisz ciasteczko

Ten krok podzielimy na dwie niezależne części.

Po pierwsze potrzebujemy funkcji hideCookieNotice działającej odwrotnie do funkcji z kroku drugiego. Skorzystamy tu z metody classList.add()

function hideCookieNotice() {
  document.querySelector('#cookie-notice').classList.add('hide');
}

Po drugie potrzebujemy fukncji, która zapisze ciasteczko w przeglądarce.

Nasza funkcja setCookie powinna przyjmować nazwę ciasteczka, jego wartość i opcjonalnie czas przydatności do spożycia.

Oto jedno z możliwych rozwiązań:

function setCookie(name, value, time) {
  let cookie = name + '=' + value;
  if (time) {
    cookie += '; max-age=' + time;
  }
  document.cookie = cookie;
}

Pozostaje nam tylko połączenie wszystkich elementów

Na przykład tak:

function acceptCookies() {
  hideCookieNotice();
  setCookie('accept-cookies', true, 60*60*24*365);
}

document
  .querySelector('#cookie-notice-button')
  .addEventListener('click', acceptCookies);

Ufff... mamy już wszystkie potrzebne elementy.

Czas próby!

Zapisujemy naszą stronę, odświeżamy i patrzymy co się dzieje

Wszystko gra?

Dzięki za wspólnie spędzony czas i do zobaczenia!