Przejdź do głównej treści
INF.03-09-24.06-SGCzerwiec 2024 · 41 kroków · ok. 75 min · 34 kryteria z klucza

Rozwiązanie krok po kroku: Animowana galeria wycieczek (Wersja podstawowa)

Animowana galeria biura turystycznego: baza wycieczki (wycieczki i ich zdjęcia) i cztery zapytania - warunek na cenę, AVG z GROUP BY i aliasem, złączenie JOIN i CREATE USER - potem zdjęcie wykadrowane między czarnymi kreskami i strona galeria.html: baner, duże zdjęcie między przyciskami „<” i „>”, pasek siedmiu miniatur i stopka. Dwie animacje CSS (@keyframes): miniatury wjeżdżają z prawej przy wczytaniu strony, a duże zdjęcie powiększa się pod kursorem. JavaScript przełącza zdjęcia i zawija numerację: za siódmym jest pierwsze, przed pierwszym - siódme.

Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Animacje są rozpisane na klatki: co jest w stanie początkowym (from), co w końcowym (to) i ile trwa przejście. Skrypt powstaje najpierw najprościej (zmienna z numerem zdjęcia, if, atrybut onclick), a na końcu przechodzi do wersji z prawdziwych projektów: płynne powiększanie i pomniejszanie, klikalne miniatury, opis zdjęcia zgodny z miejscem i obsługa strzałek klawiatury.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid)” jest drugi sposób rozwiązania tego samego arkusza: bloki na siatce CSS, kolory w zmiennych, galeria prowadzona przez listę miniatur (zawijanie numeracji resztą z dzielenia) i zdarzenia podpięte w skrypcie - obie wersje są zgodne z kluczem.

Baza i zdjęcia pochodzą z prawdziwego archiwum pliki9 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robi się je samemu, z całego ekranu. Skrypt i animacje zostały sprawdzone w prawdziwej przeglądarce. Podgląd strony jest interaktywny: przyciski przełączają zdjęcia, miniatury wjeżdżają po wczytaniu, a zdjęcie powiększa się pod kursorem.

Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.6), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów - można stracić 8 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 34 kryteriów (pkt)

    Krok 1: Baza danych wycieczki

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie wycieczki, z zestawem polskich znaków (np. utf8_unicode_ci)

    Najpierw archiwum pliki9.zip z pulpitu (hasło G@leri@Animowan@ - trzy małpy w miejscu liter „a”) rozpakowuje się do folderu nazwanego numerem zdającego. W phpMyAdmin: Nowa, nazwa wycieczki, porównywanie utf8_unicode_ci.

  2. Krok 2: Import tabel z pliku wycieczki.sql

    ok. 2 min
    Polecenie z arkusza

    Do bazy zaimportuj tabele z pliku wycieczki.sql z rozpakowanego archiwum

    Zaznaczona baza wycieczki, potem Import → wycieczki.sql → Wykonaj. Powstają dwie tabele z obrazu 1: wycieczki (7 wycieczek: miejsce, cena, liczba dni) i zdjecia (nazwy plików 1.jpg - 7.jpg, każde z polem Wycieczki_id wskazującym wycieczkę).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych wycieczki czynność udokumentowano plikiem o nazwie import w formacie PNG

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie PNG i nazwij import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.

    Print Screen, wklejenie do edytora grafiki i zapis jako import.png. Zrzuty zapytań idą później do JPEG.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

  4. Krok 4: Zapytanie 1: wycieczki tańsze niż 1000 zł

    Kryteria: ,

    R.1.2 Zapisano plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonano zapytanie 1 wybierające jedynie miejsce i liczbę dni dla wycieczek, których cena jest mniejsza od 1000 zł. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT miejsce, liczbaDni FROM wycieczki WHERE cena < 1000; oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 5 rekordów z danymi: Gdańsk 2; Kraków 3; Niedzica 1; Szklarska Poręba 4; Wrocław 2

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie miejsce i liczbę dni dla wycieczek, których cena jest mniejsza od 1000 zł

    • SELECT miejsce, liczbaDni - dwa pola, bez ceny (warunek może dotyczyć pola, którego się nie wybiera),
    • FROM wycieczki,
    • WHERE cena < 1000.

    Wynik: 5 wierszy - Gdańsk 2, Kraków 3, Niedzica 1, Szklarska Poręba 4, Wrocław 2, jak w kluczu. Zapytania zapisuje się w kwerendy.txt, zrzut jako kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT miejsce, liczbaDni FROM wycieczki WHERE cena < 1000;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: średnia cena według liczby dni

    Kryteria:

    R.1.4 Wykonano zapytanie 2 liczące średnią cenę dla wycieczek pogrupowanych ze względu na liczbę dni. Kwerenda wybiera jedynie liczbę dni oraz średnią cenę, której kolumna nosi nazwę sredniaCena . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT liczbaDni, AVG(cena) AS sredniaCena FROM wycieczki GROUP BY liczbaDni; oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 5 rekordów, kolumna ze średnią nazwana jest sredniaCena , wyświetlono dane z dowolną dokładnością: 1 150; 2 350; 3 500; 4 540; 7: 1350

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: liczące średnią cenę dla wycieczek pogrupowanych ze względu na liczbę dni (czyli średnia cena wycieczek jednodniowych, dwudniowych itd.). Kwerenda wybiera jedynie liczbę dni oraz średnią cenę, której kolumnę należy nazwać (alias) sredniaCena

    • SELECT liczbaDni, AVG(cena) AS sredniaCena - liczba dni i średnia; AS nadaje kolumnie nazwę (alias jednym słowem, bez spacji, więc nie potrzebuje cudzysłowów),
    • FROM wycieczki,
    • GROUP BY liczbaDni - wycieczki o tej samej liczbie dni tworzą jedną grupę, a AVG liczy średnią w każdej grupie osobno.

    Wynik: 5 wierszy - 1 dzień: 150, 2 dni: 350 (Gdańsk 400 i Wrocław 300), 3 dni: 500, 4 dni: 540, 7 dni: 1350 (Pieniny 1200 i Tatry 1500). Baza pokazuje średnie z czterema miejscami po przecinku (350.0000) - klucz uznaje dowolną dokładność. Zrzut: kw2.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT miejsce, liczbaDni FROM wycieczki WHERE cena < 1000;
    
    -- Zapytanie 2
    SELECT liczbaDni, AVG(cena) AS sredniaCena FROM wycieczki GROUP BY liczbaDni;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: miejsca droższe niż 500 zł ze zdjęciem

    Kryteria:

    R.1.5 Wykonano zapytanie 3 wybierające jedynie miejsce wycieczki i odpowiadającą mu nazwę zdjęcia dla wycieczek których cena jest wyższa od 500 zł. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT miejsce, nazwa FROM Wycieczki JOIN Zdjecia ON Wycieczki.id = Wycieczki_id WHERE cena > 500; (możliwe również INNER JOIN lub porównanie kluczy po WHERE, poprawne również porównanie kluczy głównych) oraz wynik działania udokumentowano zrzutem, na którym widoczne są dokładnie 3 rekordy z danymi: Pieniny 4.jpg; Szklarska Poręba 5.jpg; Tatry 6.jpg

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie miejsce wycieczki i odpowiadającą mu nazwę zdjęcia dla wycieczek, których cena jest wyższa od 500 zł. Należy posłużyć się relacją

    • SELECT miejsce, nazwa - miejsce z tabeli wycieczki, nazwa pliku z tabeli zdjecia,
    • FROM wycieczki JOIN zdjecia ON wycieczki.id = zdjecia.Wycieczki_id - relacja: do wycieczki dołączane jest jej zdjęcie,
    • WHERE cena > 500 - ostro większa; Kraków za dokładnie 500 zł się nie łapie.

    Wynik: 3 wiersze - Pieniny 4.jpg, Szklarska Poręba 5.jpg, Tatry 6.jpg, jak w kluczu. Zrzut: kw3.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT miejsce, liczbaDni FROM wycieczki WHERE cena < 1000;
    
    -- Zapytanie 2
    SELECT liczbaDni, AVG(cena) AS sredniaCena FROM wycieczki GROUP BY liczbaDni;
    
    -- Zapytanie 3
    SELECT miejsce, nazwa FROM wycieczki JOIN zdjecia ON wycieczki.id = zdjecia.Wycieczki_id WHERE cena > 500;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: użytkownik Ewa

    Kryteria:

    R.1.6 Wykonano zapytanie 4 tworzące dla bazy wycieczki użytkownika Ewa o haśle Ewa!Ewa na serwerze localhost . W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'Ewa'@'localhost' IDENTIFIED BY 'Ewa!Ewa'; oraz wynik działania udokumentowano zrzutem, na którym jest widoczne poprawnie wykonane zapytanie; wybrano bazę wycieczki, a zapytanie nie zwraca błędów

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: Tworzące użytkownika Ewa o haśle Ewa!Ewa dla bazy wycieczki na serwerze localhost

    • CREATE USER 'Ewa'@'localhost' - konto składa się z nazwy i hosta, z którego wolno się logować; localhost znaczy: tylko z tego samego komputera,
    • IDENTIFIED BY 'Ewa!Ewa' - hasło jako tekst w apostrofach (wykrzyknik jest zwykłym znakiem hasła).

    Zapytanie wykonuje się w zakładce SQL przy zaznaczonej bazie wycieczki (klucz tego wymaga na zrzucie kw4.jpg).

    ⚠️ Rozbieżność arkusz-klucz: arkusz mówi o użytkowniku „dla bazy wycieczki”, a samo CREATE USER nie wiąże konta z żadną bazą. Sprawdzone na tej bazie: konto Ewa loguje się poprawnie, ale SHOW GRANTS pokazuje tylko GRANT USAGE ON *.*, a próba otwarcia bazy kończy się błędem „Access denied for user 'Ewa'@'localhost' to database 'wycieczki'”. Dostęp dałoby dopiero GRANT ... ON wycieczki.* TO 'Ewa'@'localhost'. Klucz CKE przyjmuje samo CREATE USER - na egzaminie punkt daje wersja z klucza.

    Typowe błędy

    CREATE USER Ewa IDENTIFIED BY Ewa!Ewa bez apostrofów - hasło z wykrzyknikiem to błąd składni; bez @'localhost' konto dostaje host % (logowanie z dowolnego komputera).

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT miejsce, liczbaDni FROM wycieczki WHERE cena < 1000;
    
    -- Zapytanie 2
    SELECT liczbaDni, AVG(cena) AS sredniaCena FROM wycieczki GROUP BY liczbaDni;
    
    -- Zapytanie 3
    SELECT miejsce, nazwa FROM wycieczki JOIN zdjecia ON wycieczki.id = zdjecia.Wycieczki_id WHERE cena > 500;
    
    -- Zapytanie 4
    CREATE USER 'Ewa'@'localhost' IDENTIFIED BY 'Ewa!Ewa';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-22 · po tym etapie masz 16 z 34 kryteriów (pkt)

    Krok 8: 6.jpg: kadr między czarnymi kreskami

    Kryteria:

    R.2.1 Plik 6.jpg przycięto do czarnych kresek (nie są widoczne) i rozmiar obrazu wynosi dokładnie 640 px szerokości i 427 px wysokości

    ok. 3 min
    Polecenie z arkusza

    Plik 6.jpg, wypakowany z archiwum, należy skadrować, tak aby była widoczna tylko część zdjęcia pomiędzy czarnymi kreskami (bez widocznych kresek). Odpowiednio wycięte zdjęcie powinno mieć rozmiary 640 px na 427 px. W przypadku drobnych rozbieżności rozmiaru spowodowanych niedokładnym przycięciem należy przeskalować obraz do dokładnego wymiaru 640 px na 427 px

    Plik ma 1093×427 px, a kreski zajmują kolumny 210-238 i 879-904. W GIMP-ie: narzędzie Kadrowanie i w jego opcjach wpisana pozycja 239, 0 i rozmiar 640 × 427 - zaznaczenie zaczyna się w pierwszej kolumnie za lewą kreską i kończy tuż przed prawą. Wpisanie liczb jest dokładniejsze niż przeciąganie myszą; wtedy skalowanie z polecenia nie jest potrzebne (tutaj kadr ma od razu 640×427 px). Zapis: Plik → Nadpisz 6.jpg. Podgląd pokazuje oryginał z zaznaczonym kadrem.

    Typowe błędy

    Kadr z jedną kolumną kreski - przy krawędzi zostaje ciemny pasek, a klucz wymaga, żeby kreski nie były widoczne.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik galeria.html w HTML5

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie galeria.html zapisanej w języku HTML5

    Deklaracja <!DOCTYPE html> i szkielet z sekcjami head i body. Strona bez PHP - otwiera się ją prosto z dysku.

    galeria.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  10. Krok 10: Język strony

    ok. 1 min
    Polecenie z arkusza

    Ustawiony język zawartości strony na polski

    Atrybut lang="pl" w znaczniku <html>.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  11. Krok 11: Kodowanie polskich znaków

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku galeria.html oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> i zadeklarowano język witryny polski np.<HTML lang="pl">. Strona zawiera sekcje head i body

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head>. Z deklaracją HTML5, językiem i nazwą pliku to jedno kryterium klucza.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  12. Krok 12: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł stronie: Biuro turystyczne

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Biuro turystyczne”

    <title> w <head>.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  13. Krok 13: Podpięcie arkusza stylów

    Kryteria:

    R.3.4 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css , formatowanie CSS pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony

    Nazwa pliku: styl.css. Całe formatowanie, także animacje, ma pochodzić z tego pliku.

    Typowe błędy

    Klucz odbiera R.3.4 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast #).

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  14. Krok 14: Bloki: baner, trzy bloki, miniatury, stopka

    Kryteria:

    R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: banera, lewy, środkowy, prawy, miniatur oraz stopkę. Zastosowano semantyczne znaczniki sekcji HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, stopki - footer, dopuszcza się zagnieżdżenie bloków div w znacznikach semantycznych

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, poniżej trzy bloki: lewy, środkowy i prawy, poniżej blok miniatur, na dole blok stopki. Podział zrealizowany wyłącznie za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    Baner to <header>, stopka <footer> (klucz R.2.4 wymaga ich wprost), a cztery bloki pomiędzy - <section> z identyfikatorami po angielsku: left, middle, right i thumbnails (miniatury). Trzy pierwsze mają wspólne tło i wysokość, ale różne szerokości, a pasek miniatur ma własny styl - stąd identyfikatory.

    galeria.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <section id="thumbnails">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  15. Krok 15: Baner: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Zwiedzamy Polskę”

    <h1> w banerze.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <section id="thumbnails">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  16. Krok 16: Blok lewy: przycisk „<”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku lewego: przycisk o treści „<” (znak mniejszości – patrz tabela 2), którego wybranie powoduje wywołanie funkcji wyświetlającej poprzednie zdjęcie

    Znak mniejszości zaczyna w HTML-u znacznik, więc w treści zapisuje się go encją &lt; (ang. less than) z tabeli 2 arkusza - przeglądarka wyświetli „<”. Funkcję, którą przycisk wywoła, dopisze część o JavaScripcie.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <section id="thumbnails">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  17. Krok 17: Blok środkowy: aktywne zdjęcie

    Kryteria:

    R.2.7 W bloku środkowym umieszczono obraz 1.jpg z tekstem alternatywnym "Aktywne zdjęcie"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku środkowego: obraz o nazwie 1.jpg i tekście alternatywnym „Aktywne zdjęcie”

    Obraz dostaje identyfikator activePhoto - po nim skrypt podmieni źródło zdjęcia, a arkusz stylów odróżni duże zdjęcie od miniatur.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
        </section>
        <section id="thumbnails">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  18. Krok 18: Blok prawy: przycisk „>”

    Kryteria:

    R.2.6 W bloku lewym umieszczono przycisk o treści "<" oraz w bloku prawym umieszczono przycisk o treści „>”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku prawego: przycisk o treści „>” (znak większości – patrz tabela 2), którego wybranie powoduje wywołanie funkcji wyświetlającej następne zdjęcie

    Znak większości jako encja &gt; (greater than). Goły „>” w treści przeglądarki zwykle wyświetlają poprawnie, ale encja jest jednoznaczna i zgodna z tabelą 2.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button>&gt;</button>
        </section>
        <section id="thumbnails">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  19. Krok 19: Blok miniatur: siedem zdjęć

    Kryteria:

    R.2.8 W bloku miniatur umieszczono 7 obrazów od 1.jpg do 7.jpg . Teksty alternatywne kolejno: Gdańsk, Kraków, Niedzica, Pieniny, Szklarska Poręba, Tatry, Wrocław

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku miniatur: Siedem obrazów od 1.jpg do 7.jpg. Teksty alternatywne kolejno: Gdańsk, Kraków, Niedzica, Pieniny, Szklarska Poręba, Tatry, Wrocław

    Siedem <img> z tymi samymi plikami co duże zdjęcie - miniaturą zrobi je dopiero wysokość z arkusza stylów. Teksty alternatywne to nazwy miejsc w kolejności z arkusza (zgodne z bazą: zdjęcie 1 to Gdańsk, 7 to Wrocław). Na razie zdjęcia są w pełnym rozmiarze.

    galeria.html HTML zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button>&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  20. Krok 20: Stopka: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: Nagłówek trzeciego stopnia o treści: „Autorem galerii jest:”

    <h3> w stopce.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button>&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  21. Krok 21: Stopka: autor

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "Zwiedzamy Polskę" , w bloku stopki nagłówek h3: "Autorem galerii jest:" oraz paragraf z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

    Paragraf z wstawionym numerem zdającego

    Akapit pod nagłówkiem. Na egzaminie wpisuje się swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania. Z tym krokiem są nagłówki i akapit z R.2.5.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button>&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  22. Krok 22: Stopka: odnośnik w nowej karcie

    Kryteria:

    R.3.2 Odnośnik o treści „Więcej zdjęć” inicjuje otwarcie strony http://pixabay.com, strona otwiera się w nowej zakładce przeglądarki

    ok. 1 min
    Polecenie z arkusza

    Odnośnik o treści „Więcej zdjęć” do strony http://pixabay.com otwierający się w nowej karcie przeglądarki

    Nową kartę otwiera atrybut target="_blank" (z podkreśleniem na początku). Bez niego strona z przykładowymi zdjęciami zastąpiłaby galerię w tej samej karcie.

    Typowe błędy

    target="blank" bez podkreślenia też otwiera nową kartę, ale nazwaną „blank” - kolejne kliknięcie trafi do tej samej karty. Poprawna wartość to _blank.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button>&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  23. Etap 3: Styl CSS

    Kroki 23-33 · po tym etapie masz 27 z 34 kryteriów (pkt)

    Krok 23: Plik styl.css: krój Georgia, biały tekst

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (dla *): krój czcionki Georgia, biały kolor czcionki

    ok. 1 min
    Polecenie z arkusza

    Domyślne formatowanie wszystkich selektorów: krój czcionki Georgia, biały kolor czcionki

    Selektor uniwersalny * - biały kolor dostaje każdy element, także odnośnik (zwykle niebieski) i przyciski. Na białym tle strony tekst chwilowo znika - tła bloków dojdą w kolejnych regułach.

    styl.css CSS nowy plik
    * {
        font-family: Georgia;
        color: white;
    }
    Podgląd strony po tym kroku (galeria.html)
  24. Krok 24: Baner i stopka

    Kryteria:

    R.4.6 Ustawiono wyrównanie tekstu do środka dla banera i stopki

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla bloku banera i stopki: kolor tła Maroon, wyrównanie tekstu do środka, marginesy wewnętrzne 2 px

    Dwa selektory znaczników po przecinku.

    styl.css CSS zmienione: 5 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    Podgląd strony po tym kroku (galeria.html)
  25. Krok 25: Trzy bloki: tło i wysokość

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla bloków lewego, środkowego i prawego: kolor tła LightSalmon, wysokość 527 px

    Trzy identyfikatory po przecinku - selektor section złapałby też blok miniatur, który ma inne tło i wysokość.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    Podgląd strony po tym kroku (galeria.html)
  26. Krok 26: Bloki boczne: szerokość

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku lewego i prawego: szerokość 15%

    Bloki z przyciskami są wąskie.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    Podgląd strony po tym kroku (galeria.html)
  27. Krok 27: Blok środkowy: szerokość

    Kryteria:

    R.4.5 Ustawiono szerokość dla bloków lewego i prawego 15% oraz dla bloku środkowego 70% (width lub grid-template-columns lub flex)

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku środkowego: szerokość 70%

    15% + 70% + 15% = 100% - trzy bloki wypełnią wiersz, gdy staną obok siebie (R.4.5).

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    Podgląd strony po tym kroku (galeria.html)
  28. Krok 28: Blok miniatur: tło i wysokość

    ok. 1 min
    Polecenie z arkusza

    Dla bloku miniatur: kolor tła Maroon, wysokość 70 px

    Pasek ma dokładnie wysokość miniatur (70 px, ustawioną za chwilę) - zdjęcia wypełnią go od góry do dołu.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    Podgląd strony po tym kroku (galeria.html)
  29. Krok 29: Przyciski strzałek

    Kryteria:

    R.4.3 Ustawiono kolor czcionki Maroon dla przycisku

    ok. 2 min
    Polecenie z arkusza

    Dla obu przycisków: kolor tła LightSalmon, kolor czcionki Maroon, bez obramowania, rozmiar czcionki 400%, blokowy sposób wyświetlania elementu, marginesy zewnętrzne automatycznie obliczane przez przeglądarkę, margines wewnętrzny górny 210 px

    Przycisk ma tło takie jak blok i nie ma ramki, więc widać tylko dużą strzałkę (400% wielkości tekstu). display: block razem z margin: auto wyśrodkowuje przycisk w poziomie: element blokowy o szerokości mniejszej niż rodzic dostaje po równo wolnego miejsca z obu stron. padding-top: 210px spycha strzałkę w dół, mniej więcej na wysokość środka zdjęcia. Reguła zamyka kolor czcionki przycisku (R.4.3, color z tej reguły wygrywa z białym z *) i R.4.8: przyciski blokowe, 400%, bez ramki - razem z obrazem, który dostanie display: block za chwilę.

    styl.css CSS zmienione: 9 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    Podgląd strony po tym kroku (galeria.html)
  30. Krok 30: Miniatury: wysokość i animacja wjazdu

    Kryteria:

    R.4.9 Dla obrazów miniatur ustawiono animację trwającą 4 sekundy polegającą na zmianie cechy padding-left z 50 px na początku do 0 px na końcu. Po odświeżeniu strony miniatury przesuwają się od prawej do lewej strony okna przeglądarki

    ok. 3 min
    Polecenie z arkusza

    Dla obrazów miniatur: Styl miniatury: wysokość 70 px, animacja trwa 4 sekundy. Stan początkowy animacji: lewy margines wewnętrzny: 50 px. Stan końcowy animacji: lewy margines wewnętrzny: 0 px

    Animacja CSS ma dwie części (tabela 3 arkusza):
    - @keyframes slideIn opisuje klatki: from (0%, stan początkowy) - każda miniatura ma 50 px dopełnienia z lewej, to (100%, stan końcowy) - 0 px. Przeglądarka sama liczy klatki pośrednie: po 2 sekundach jest 25 px,
    - w regule miniatur animation-name wskazuje te klatki, a animation-duration: 4s - czas trwania.

    Efekt po wczytaniu strony: siedem miniatur stoi na początku rozsuniętych (7 · 50 px = 350 px dodatkowego miejsca), a przez 4 sekundy dosuwa się do siebie w lewo - „przesuwają się od prawej do lewej”, jak opisuje klucz. Po animacji zostaje styl bez dopełnienia. W podglądzie animacja odtwarza się po każdym wczytaniu strony.

    Typowe błędy

    Same klatki @keyframes bez animation-name i animation-duration w regule obrazu - animacja nigdy się nie uruchamia.

    styl.css CSS zmienione: 13 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    #thumbnails img {
        height: 70px;
        animation-name: slideIn;
        animation-duration: 4s;
    }
    @keyframes slideIn {
        from {
            padding-left: 50px;
        }
        to {
            padding-left: 0px;
        }
    }
    Podgląd strony po tym kroku (galeria.html)
  31. Krok 31: Duże zdjęcie: wyśrodkowane

    Kryteria: ,

    R.4.7 Ustawiono marginesy wewnętrzne (padding) dla banera i stopki 2px, górny 210px dla obu przycisków, górny 45px dla obrazu z bloku środkowego oraz margin: auto; dla obu przycisków oraz obrazu wyświetlanego w bloku środkowym

    R.4.8 Ustawiono dla obrazu z bloku środkowego i obu przycisków blokowy sposób wyświetlania oraz dla obu przycisków rozmiar czcionki 400% i brak obramowania

    ok. 1 min
    Polecenie z arkusza

    Dla obrazu z bloku środkowego: blokowy sposób wyświetlania elementu, marginesy zewnętrzne automatycznie obliczane przez przeglądarkę, górny margines wewnętrzny 45 px

    To samo wyśrodkowanie co przy przyciskach: display: block + margin: auto. Zdjęcie ma 640 px szerokości, więc wolne miejsce w bloku środkowym rozkłada się po równo na lewo i prawo. Komplet marginesów z R.4.7 (baner, stopka, przyciski, zdjęcie) i sposobów wyświetlania z R.4.8.

    styl.css CSS zmienione: 5 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    #thumbnails img {
        height: 70px;
        animation-name: slideIn;
        animation-duration: 4s;
    }
    @keyframes slideIn {
        from {
            padding-left: 50px;
        }
        to {
            padding-left: 0px;
        }
    }
    #activePhoto {
        display: block;
        margin: auto;
        padding-top: 45px;
    }
    Podgląd strony po tym kroku (galeria.html)
  32. Krok 32: Duże zdjęcie: powiększanie pod kursorem

    Kryteria:

    R.4.10 Obraz powiększa się po umieszczeniu na nim kursora myszy. Dla pseudoklasy hover obrazu z bloku środkowego ustawiono skalę 120% oraz animację trwającą 5 sekund, polegającą na zmianie skali obrazu ze 100% na początku do 120% na końcu

    ok. 3 min
    Polecenie z arkusza

    Gdy kursor znajduje się na obrazie z bloku środkowego wykonana jest animacja: Stan początkowy animacji: skala 100%. Stan końcowy animacji: skala 120%. Styl obrazu: Skala 120%, czas trwania animacji 5 sekund

    Pseudoklasa :hover - reguła działa tylko wtedy, gdy kursor jest na zdjęciu. Skala to właściwość transform z funkcją scale: scale(1) = 100%, scale(1.2) = 120%. Klatki zoomIn prowadzą od 100% do 120% przez 5 sekund. Po co dodatkowo transform: scale(1.2) w samej regule („Styl obrazu: Skala 120%”)? Animacja po zakończeniu wraca do stylu elementu - bez tej linii zdjęcie po 5 sekundach skoczyłoby z powrotem do 100%, choć kursor nadal na nim stoi. Uwaga: po zdjęciu kursora powiększenie znika od razu, bez animacji.

    Typowe błędy

    Osobna właściwość scale: 120% zamiast transform: scale(1.2) działa dopiero w przeglądarkach z 2022 roku i nowszych (Chrome od wersji 104) - na starszym stanowisku powiększenia nie będzie. Zapis z transform działa wszędzie.

    styl.css CSS zmienione: 13 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    #thumbnails img {
        height: 70px;
        animation-name: slideIn;
        animation-duration: 4s;
    }
    @keyframes slideIn {
        from {
            padding-left: 50px;
        }
        to {
            padding-left: 0px;
        }
    }
    #activePhoto {
        display: block;
        margin: auto;
        padding-top: 45px;
    }
    #activePhoto:hover {
        transform: scale(1.2);
        animation-name: zoomIn;
        animation-duration: 5s;
    }
    @keyframes zoomIn {
        from {
            transform: scale(1);
        }
        to {
            transform: scale(1.2);
        }
    }
    Podgląd strony po tym kroku (galeria.html)
  33. Krok 33: Układ bloków zgodny z obrazem 2

    Kryteria: , ,

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS decydujące o układzie strony, np. float i clear albo display flex albo grid)

    R.4.2 Ustawiono kolor tła Maroon dla bloków: banera, miniatur i stopki oraz LightSalmon dla bloków lewego, środkowego i prawego oraz dla przycisków

    R.4.4 Ustawiono wysokość bloków lewego, środkowego i prawego 527px oraz bloku miniatur i obrazu miniatur 70px

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, poniżej trzy bloki: lewy, środkowy i prawy, poniżej blok miniatur, na dole blok stopki. Podział zrealizowany wyłącznie za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    float: left dla trzech bloków ustawia je w jednym wierszu (15% + 70% + 15%). clear: both dla bloku miniatur stawia go pod nimi - bez tego pasek wjechałby pod pływające bloki na górę strony. Stopka i tak stoi pod paskiem miniatur, bo pasek nie pływa. Ten krok zamyka kryteria tła (Maroon banera, miniatur i stopki, LightSalmon bloków i przycisków - R.4.2) i wysokości (527 px bloków, 70 px paska i miniatur - R.4.4).

    Typowe błędy

    clear dla stopki zamiast dla bloku miniatur - pasek miniatur chowa się pod pływającymi blokami.

    styl.css CSS zmienione: 6 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    #thumbnails img {
        height: 70px;
        animation-name: slideIn;
        animation-duration: 4s;
    }
    @keyframes slideIn {
        from {
            padding-left: 50px;
        }
        to {
            padding-left: 0px;
        }
    }
    #activePhoto {
        display: block;
        margin: auto;
        padding-top: 45px;
    }
    #activePhoto:hover {
        transform: scale(1.2);
        animation-name: zoomIn;
        animation-duration: 5s;
    }
    @keyframes zoomIn {
        from {
            transform: scale(1);
        }
        to {
            transform: scale(1.2);
        }
    }
    #left, #middle, #right {
        float: left;
    }
    #thumbnails {
        clear: both;
    }
    Podgląd strony po tym kroku (galeria.html)
  34. Etap 4: JavaScript

    Kroki 34-37 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 34: Następne zdjęcie

    Kryteria: , ,

    R.5.1 Skrypt zapisano w języku JavaScript i zawiera on przynajmniej jedną instrukcję zapisaną zgodnie ze składnią

    R.5.2 Po wybraniu przycisku ">" obraz w bloku środkowym zmienia się na następny, np. 1.jpg na 2.jpg

    R.3.3 Wybranie przynajmniej jednego przycisku powoduje wywołanie funkcji skryptu

    ok. 3 min
    Polecenie z arkusza

    Działanie funkcji wyświetlającej następne zdjęcie: Zmienia aktywne zdjęcie w bloku środkowym na następne (np. 1.jpg na 2.jpg)

    Pliki mają nazwy z numerami, więc wystarczy pamiętać numer wyświetlanego zdjęcia: zmienna photoNumber stoi poza funkcją i zaczyna od 1 (na stronie jest 1.jpg). Funkcja nextPhoto zwiększa numer i skleja nazwę pliku: photoNumber + ".jpg" daje „2.jpg”, które trafia do atrybutu src dużego zdjęcia. Przycisk „>” dostaje onclick="nextPhoto()". W podglądzie przycisk już działa - ale po siódmym zdjęciu pokazuje pusty obraz „8.jpg”, którego nie ma.

    galeria.html HTML zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button onclick="nextPhoto()">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            let photoNumber = 1;
    
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  35. Krok 35: Za siódmym zdjęciem pierwsze

    Kryteria:

    R.5.3 Gdy w bloku środkowym jest wyświetlany obraz 7.jpg , wybranie przycisku ">" powoduje wyświetlenie obrazu 1.jpg

    ok. 1 min
    Polecenie z arkusza

    W przypadku, gdy jest wyświetlane ostatnie zdjęcie: 7.jpg zmienia zdjęcie na: 1.jpg

    Warunek po zwiększeniu numeru: gdy wyszedł poza 7, wraca do 1. Teraz „>” przewija galerię w kółko.

    galeria.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button onclick="nextPhoto()">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            let photoNumber = 1;
    
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                if (photoNumber > 7) {
                    photoNumber = 1;
                }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  36. Krok 36: Poprzednie zdjęcie

    Kryteria:

    R.5.4 Po wybraniu przycisku "<" obraz w bloku środkowym zmienia się na poprzedni, np. 3.jpg na 2.jpg

    ok. 2 min
    Polecenie z arkusza

    Działanie funkcji wyświetlającej poprzednie zdjęcie: Zmienia aktywne zdjęcie w bloku środkowym na poprzednie (np. 3.jpg na 2.jpg)

    Lustrzana funkcja previousPhoto: zmniejsza ten sam numer o 1. Wspólna zmienna sprawia, że obie strzałki wiedzą, które zdjęcie jest teraz na ekranie.

    galeria.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button>&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button onclick="nextPhoto()">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            let photoNumber = 1;
    
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                if (photoNumber > 7) {
                    photoNumber = 1;
                }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
    
            function previousPhoto() {
                photoNumber = photoNumber - 1;
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  37. Krok 37: Przed pierwszym zdjęciem siódme; przycisk „<”

    Kryteria: ,

    R.5.5 Gdy w bloku środkowym jest wyświetlany obraz 1.jpg , wybranie przycisku "<" powoduje wyświetlenie obrazu 7.jpg

    R.5.6 Zastosowano znaczące nazewnictwo dla wszystkich zmiennych i funkcji w języku polskim lub angielskim. Nazwy odzwierciedlają cel zastosowania

    ok. 2 min
    Polecenie z arkusza

    W przypadku, gdy jest wyświetlane pierwsze zdjęcie: 1.jpg zmienia zdjęcie na ostatnie: 7.jpg

    Gdy numer spadnie poniżej 1, wraca do 7. Przycisk „<” dostaje onclick="previousPhoto()" - od razu po wczytaniu strony kliknięcie „<” pokazuje Wrocław (7.jpg). Nazwy mówią, co robią i co przechowują (photoNumber, nextPhoto, previousPhoto) - kryterium R.5.6.

    galeria.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button onclick="previousPhoto()">&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button onclick="nextPhoto()">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            let photoNumber = 1;
    
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                if (photoNumber > 7) {
                    photoNumber = 1;
                }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
    
            function previousPhoto() {
                photoNumber = photoNumber - 1;
                if (photoNumber < 1) {
                    photoNumber = 7;
                }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  38. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 38-40 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 38: Płynne powiększanie w obie strony

    ok. 3 min
    Polecenie z arkusza

    Gdy kursor znajduje się na obrazie z bloku środkowego wykonana jest animacja: Stan początkowy animacji: skala 100%. Stan końcowy animacji: skala 120%. Styl obrazu: Skala 120%, czas trwania animacji 5 sekund

    Animacja z @keyframes w regule :hover działa tylko w jedną stronę: po zdjęciu kursora reguła przestaje obowiązywać i zdjęcie skacze do 100%. Do zmiany stanu pod kursorem lepiej pasuje przejście (transition): w zwykłej regule zdjęcia transition: transform 5s mówi „każdą zmianę transform rozłóż na 5 sekund”, a :hover podaje tylko stan docelowy. Zdjęcie rośnie przez 5 sekund pod kursorem i tak samo płynnie wraca, gdy kursor odjedzie - nawet w połowie powiększenia. Druga zmiana: zapytanie prefers-reduced-motion wyłącza obie animacje u osób, które w systemie zaznaczyły ograniczenie ruchu (ruch na ekranie bywa dla nich męczący). Stare reguły zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz (R.4.10) wymaga animacji z klatkami 100% i 120%.

    styl.css CSS zmienione: 15 linii
    * {
        font-family: Georgia;
        color: white;
    }
    header, footer {
        background-color: Maroon;
        text-align: center;
        padding: 2px;
    }
    #left, #middle, #right {
        background-color: LightSalmon;
        height: 527px;
    }
    #left, #right {
        width: 15%;
    }
    #middle {
        width: 70%;
    }
    #thumbnails {
        background-color: Maroon;
        height: 70px;
    }
    button {
        background-color: LightSalmon;
        color: Maroon;
        border: none;
        font-size: 400%;
        display: block;
        margin: auto;
        padding-top: 210px;
    }
    #thumbnails img {
        height: 70px;
        animation-name: slideIn;
        animation-duration: 4s;
    }
    @keyframes slideIn {
        from {
            padding-left: 50px;
        }
        to {
            padding-left: 0px;
        }
    }
    #activePhoto {
        display: block;
        margin: auto;
        padding-top: 45px;
    }
    #activePhoto {
        transition: transform 5s;
    }
    #activePhoto:hover {
        transform: scale(1.2);
    }
    /* Wersja z egzaminu - animacja tylko w jedną stronę:
    #activePhoto:hover {
        transform: scale(1.2);
        animation-name: zoomIn;
        animation-duration: 5s;
    }
    @keyframes zoomIn {
        from { transform: scale(1); }
        to { transform: scale(1.2); }
    }
    */
    @media (prefers-reduced-motion: reduce) {
        #activePhoto, #thumbnails img {
            transition: none;
            animation: none;
        }
    }
    #left, #middle, #right {
        float: left;
    }
    #thumbnails {
        clear: both;
    }
    Podgląd strony po tym kroku (galeria.html)
  39. Krok 39: Galeria z listy miniatur: zawijanie resztą z dzielenia

    ok. 4 min
    Polecenie z arkusza

    Działanie funkcji wyświetlającej następne zdjęcie: Zmienia aktywne zdjęcie w bloku środkowym na następne (np. 1.jpg na 2.jpg)

    Wersja z egzaminu ma liczbę 7 wpisaną w dwóch warunkach i zakłada, że pliki nazywają się kolejnymi numerami - ósme zdjęcie w galerii wymagałoby poprawek w skrypcie. Teraz źródłem prawdy jest lista miniatur: querySelectorAll("#thumbnails img") zwraca wszystkie, a jedna funkcja showPhoto(index) bierze z wybranej miniatury plik i nazwę miejsca. Zawijanie robi reszta z dzielenia: (index + liczba) % liczba zamienia -1 na ostatni indeks, a 7 na 0 - bez dwóch if-ów. Przy okazji tekst alternatywny dużego zdjęcia mówi, co na nim jest („Aktywne zdjęcie: Wrocław”), a kliknięcie miniatury pokazuje ją od razu (sprawdzone w przeglądarce). Funkcje nextPhoto i previousPhoto zostają, więc przyciski działają bez zmian. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    galeria.html HTML zmienione: 29 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button onclick="previousPhoto()">&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button onclick="nextPhoto()">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            const activePhoto = document.getElementById("activePhoto");
            const thumbnails = document.querySelectorAll("#thumbnails img");
            let photoIndex = 0;      // 0 = pierwsza miniatura (1.jpg)
    
            function showPhoto(index) {
                // reszta z dzielenia zawija numerację w obie strony: -1 -> ostatnie, 7 -> pierwsze
                photoIndex = (index + thumbnails.length) % thumbnails.length;
                activePhoto.src = thumbnails[photoIndex].getAttribute("src");
                activePhoto.alt = "Aktywne zdjęcie: " + thumbnails[photoIndex].alt;
            }
    
            function nextPhoto() {
                showPhoto(photoIndex + 1);
            }
    
            function previousPhoto() {
                showPhoto(photoIndex - 1);
            }
    
            // kliknięcie miniatury pokazuje ją jako aktywne zdjęcie
            thumbnails.forEach(function (thumbnail, index) {
                thumbnail.addEventListener("click", function () { showPhoto(index); });
            });
            /* Wersja z egzaminu:
            let photoNumber = 1;
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                if (photoNumber > 7) { photoNumber = 1; }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
            function previousPhoto() {
                photoNumber = photoNumber - 1;
                if (photoNumber < 1) { photoNumber = 7; }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
            */
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  40. Krok 40: Nasłuchiwacze zdarzeń i strzałki klawiatury

    ok. 3 min
    Polecenie z arkusza

    Zawartość bloku prawego: przycisk o treści „>” (znak większości – patrz tabela 2), którego wybranie powoduje wywołanie funkcji wyświetlającej następne zdjęcie

    Atrybuty onclick znikają z HTML-u: przyciski dostają identyfikatory, a skrypt podpina im funkcje przez addEventListener("click", ...) - zachowanie strony jest w jednym miejscu. Galeria reaguje też na klawiaturę: nasłuchiwacz zdarzenia keydown na całym dokumencie sprawdza event.key i przy strzałce w lewo albo w prawo wywołuje te same funkcje (sprawdzone: strzałka w lewo po wczytaniu - 7.jpg). Przyciski z samym znakiem „<” i „>” dostają atrybut aria-label - czytnik ekranu przeczyta „Poprzednie zdjęcie” zamiast „mniejsze niż”. Na egzaminie wystarczy wersja wcześniejsza - klucz uznaje oba sposoby obsługi zdarzeń (R.3.3).

    galeria.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Biuro turystyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zwiedzamy Polskę</h1>
        </header>
        <section id="left">
            <button id="previousButton" aria-label="Poprzednie zdjęcie">&lt;</button>
        </section>
        <section id="middle">
            <img src="1.jpg" alt="Aktywne zdjęcie" id="activePhoto">
        </section>
        <section id="right">
            <button id="nextButton" aria-label="Następne zdjęcie">&gt;</button>
        </section>
        <section id="thumbnails">
            <img src="1.jpg" alt="Gdańsk">
            <img src="2.jpg" alt="Kraków">
            <img src="3.jpg" alt="Niedzica">
            <img src="4.jpg" alt="Pieniny">
            <img src="5.jpg" alt="Szklarska Poręba">
            <img src="6.jpg" alt="Tatry">
            <img src="7.jpg" alt="Wrocław">
        </section>
        <footer>
            <h3>Autorem galerii jest:</h3>
            <p>Bartosz Bryniarski</p>
            <a href="http://pixabay.com" target="_blank">Więcej zdjęć</a>
        </footer>
        <script>
            const activePhoto = document.getElementById("activePhoto");
            const thumbnails = document.querySelectorAll("#thumbnails img");
            let photoIndex = 0;      // 0 = pierwsza miniatura (1.jpg)
    
            function showPhoto(index) {
                // reszta z dzielenia zawija numerację w obie strony: -1 -> ostatnie, 7 -> pierwsze
                photoIndex = (index + thumbnails.length) % thumbnails.length;
                activePhoto.src = thumbnails[photoIndex].getAttribute("src");
                activePhoto.alt = "Aktywne zdjęcie: " + thumbnails[photoIndex].alt;
            }
    
            function nextPhoto() {
                showPhoto(photoIndex + 1);
            }
    
            function previousPhoto() {
                showPhoto(photoIndex - 1);
            }
    
            // kliknięcie miniatury pokazuje ją jako aktywne zdjęcie
            thumbnails.forEach(function (thumbnail, index) {
                thumbnail.addEventListener("click", function () { showPhoto(index); });
            });
            document.getElementById("previousButton").addEventListener("click", previousPhoto);
            document.getElementById("nextButton").addEventListener("click", nextPhoto);
            // strzałki klawiatury działają jak przyciski
            document.addEventListener("keydown", function (event) {
                if (event.key == "ArrowLeft") {
                    previousPhoto();
                } else if (event.key == "ArrowRight") {
                    nextPhoto();
                }
            });
            /* Wersja z egzaminu:
            let photoNumber = 1;
            function nextPhoto() {
                photoNumber = photoNumber + 1;
                if (photoNumber > 7) { photoNumber = 1; }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
            function previousPhoto() {
                photoNumber = photoNumber - 1;
                if (photoNumber < 1) { photoNumber = 7; }
                document.getElementById("activePhoto").src = photoNumber + ".jpg";
            }
            */
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  41. Etap 6: Oddanie pracy

    Krok 41 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 41: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wpisuje się nazwę przeglądarki, w której sprawdzana była strona (także animacje).

    W folderze z numerem zdającego: 1.jpg - 7.jpg (6.jpg wykadrowany), galeria.html, import.png, kw1.jpg - kw4.jpg, kwerendy.txt, przeglądarka.txt, styl.css. Płytę trzeba nagrać, sprawdzić jej odczyt i opisać numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 40.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.