Przejdź do głównej treści
EE.09-02-23.01-SGStyczeń 2023 · 34 kroki · ok. 76 min · 38 kryteriów z klucza

Rozwiązanie krok po kroku: Galeria obrazów z przyciskami nawigacji (Nowoczesny kod (grid, nasłuchiwacze))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza gory z czterema zapytaniami i kontem leon, zdjęcie wykadrowane w pionie i strona galeria.html z dużym zdjęciem przełączanym przyciskami i miniaturami - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS zamiast float: bloki lewy i prawy stoją w znaczniku <main> z grid-template-columns: 20% 65%, a stopka nie potrzebuje clear,
  • zmienne CSS dla kolorów, cienia i marginesu - cień bloku lewego i dużego zdjęcia jest zapisany raz,
  • miniatury bez przeskoku: przezroczysta ramka czeka na swoje miejsce, a pod kursorem zmienia się tylko jej wygląd,
  • skrypt w osobnym pliku galeria.js z atrybutem defer, bez atrybutów onclick w HTML-u - przyciski i miniatury dostają nasłuchiwacze addEventListener, a numer zdjęcia miniatury stoi w atrybucie data-photo,
  • jedna funkcja zmienia zdjęcie, a funkcje „next” i „prev” tylko wyliczają numer; do tego obsługa strzałek na klawiaturze.

Skrypt może być w osobnym pliku, bo klucz tego arkusza nie każe sprawdzać skryptu „w kodzie strony” - plik galeria.js trafia na płytę razem ze stroną („ewentualnie inne przygotowane pliki” z listy w arkuszu).

To arkusz EE.09 ze stycznia 2023 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Baza i zdjęcia pochodzą z oryginalnego archiwum CKE zad2.zip (załącznik na stronie arkusza), zapytania i zrzuty są policzone na MariaDB 10.4, a skrypt sprawdzony w przeglądarce Chrome.

Jak liczą się punkty. Klucz ma 38 kryteriów (R.1.1 - R.5.6), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 29 punktów. Przy każdym kroku jest napisane, które kryteria spełnia; klucz przyjmuje zarówno atrybut onClick, jak i nasłuchiwacz zdarzenia.

  1. Etap 1: Baza danych

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

    Krok 1: Folder zdającego i archiwum zad2.zip

    ok. 2 min
    Polecenie z arkusza

    Na pulpicie konta Egzamin należy utworzyć folder. Jako nazwy folderu należy użyć numeru zdającego, którym został podpisany arkusz. Rozpakowane pliki należy umieścić w tym folderze. Zaleca się, aby rozpakowane pliki znajdowały się w tym samym folderze, co pliki strony. Po skończonej pracy wszystkie wyniki należy zapisać w tym folderze.

    Folder na pulpicie nazwany numerem zdającego (w tym rozwiązaniu Bartosz Bryniarski), do niego zad2.zip z hasłem !<MojaG@leri@>!: szczyty.sql, zdjecie.jpg i zdjęcia galerii 1.jpg - 5.jpg. Strona i zdjęcia w jednym folderze - w kodzie wystarczy sama nazwa pliku.

  2. Krok 2: XAMPP i baza gory

    ok. 2 min
    Polecenie z arkusza

    Za pomocą narzędzia phpMyAdmin wykonaj operacje na bazie danych: Utwórz bazę danych o nazwie gory

    Start przy Apache i MySQL, http://localhost/phpmyadmin, Nowa, nazwa gory, porównywanie np. utf8_polish_ci (polskie litery i polska kolejność alfabetyczna).

  3. Krok 3: Import tabeli z pliku szczyty.sql i zrzut import.jpg

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych gory , czynność udokumentowano plikiem o nazwie import w formacie JPEG

    ok. 3 min
    Polecenie z arkusza

    Do bazy gory zaimportuj tabele z pliku szczyty.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie JPEG 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

    Karta Import bazy gory, plik szczyty.sql. Jedna tabela: szczyty z 26 szczytami (id, pasmo, nazwa, wysokosc). Zrzut całego ekranu z komunikatem o sukcesie: import.jpg.

    Typowe błędy

    Zrzut importu w JPEG, zrzuty zapytań w PNG.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Zapytanie 1: szczyty wyższe niż 1500 m

    Kryteria: ,

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

    R.1.3 Utworzono zapytanie 1 wybierające jedynie pola nazwa i pasmo z tabeli szczyty dla szczytów wyższych niż 1500 m. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, pasmo FROM szczyty WHERE wysokosc > 1500; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są dokładnie 3 rekordy: Babia Góra (Diablak), Beskid Żywiecki; Śnieżka, Karkonosze; Rysy, Tatry

    ok. 3 min
    Polecenie z arkusza

    Wykonaj zapytania SQL działające na bazie gory. Zapytania zapisz w pliku kwerendy.txt. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie PNG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola nazwa i pasmo z tabeli szczyty dla szczytów wyższych niż 1500 m

    Każda klauzula w osobnej linii. WHERE wysokosc > 1500 - „wyższe niż”, bez równości. Wynik: 3 rekordy - Babia Góra (Diablak), Śnieżka i Rysy z pasmami. Zapytanie do kwerendy.txt, zrzut: kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, pasmo
    FROM szczyty
    WHERE wysokosc > 1500;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: nazwa najwyższego szczytu

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające jedynie nazwę najwyższego szczytu w tabeli szczyty . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa FROM szczyty ORDER BY wysokosc DESC LIMIT 1; (Uwaga! Zapytanie można zapisać na kilka sposobów - ważny jest rezultat wykonania) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczna jest jedynie nazwa Rysy

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie nazwę najwyższego szczytu w tabeli szczyty

    Sortowanie malejąco po wysokości (ORDER BY wysokosc DESC) i pierwszy wiersz (LIMIT 1). Wynik: Rysy. Zrzut: kw2.png.

    Typowe błędy

    SELECT nazwa, MAX(wysokosc) zwraca największą wysokość, ale nazwę z dowolnego wiersza - nie Rysy.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwa, pasmo
    FROM szczyty
    WHERE wysokosc > 1500;
    
    -- Zapytanie 2
    SELECT nazwa
    FROM szczyty
    ORDER BY wysokosc DESC
    LIMIT 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: użytkownik leon

    Kryteria:

    R.1.5 Utworzono zapytanie 3 tworzące użytkownika leon@localhost z hasłem Leon%Zawodowiec W pliku z kwerendami lub na zrzucie istnieje zapis z jawnym hasłem, np.: CREATE USER 'leon'@'localhost' IDENTIFIED BY 'Leon%Zawodowiec'; oraz wynik działania zapytania udokumentowano zrzutem, wskazującym na poprawne założenie konta użytkownika

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: tworzące użytkownika leon@localhost z hasłem Leon%Zawodowiec

    CREATE USER z hasłem zapisanym jawnie w apostrofach; komunikat „MySQL zwrócił pusty wynik” oznacza sukces. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, pasmo
    FROM szczyty
    WHERE wysokosc > 1500;
    
    -- Zapytanie 2
    SELECT nazwa
    FROM szczyty
    ORDER BY wysokosc DESC
    LIMIT 1;
    
    -- Zapytanie 3
    CREATE USER 'leon'@'localhost' IDENTIFIED BY 'Leon%Zawodowiec';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: prawa do manipulowania danymi w bazie gory

    Kryteria:

    R.1.6 Utworzono zapytanie 4 Nadające użytkownikowi leon@localhost jedynie wszystkie prawa do manipulowania danymi we wszystkich tabelach bazy gory . W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT UPDATE, DELETE, INSERT ON gory.* TO 'leon'@'localhost'; (możliwe też gory.szczyty - zamiast gwiazdki; opcjonalnie może być też SELECT) oraz wynik działania zapytania udokumentowano zrzutem wskazującym na poprawnie nadane prawa

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: Nadające użytkownikowi leon@localhost jedynie wszystkie prawa do manipulowania danymi we wszystkich tabelach bazy gory

    Prawa do rekordów: SELECT, INSERT, UPDATE, DELETE, bez praw do budowy bazy. Przykład w kluczu pomija SELECT i dopuszcza jego dopisanie - tutaj jest, bo bez niego DELETE … WHERE id = 26 kończy się odmową dostępu (warunek musi odczytać kolumnę; sprawdzone logowaniem na konto leon). Zrzut: kw4.png.

    Typowe błędy

    GRANT ALL PRIVILEGES daje też prawo do usuwania tabel - arkusz mówi „jedynie” o danych.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT nazwa, pasmo
    FROM szczyty
    WHERE wysokosc > 1500;
    
    -- Zapytanie 2
    SELECT nazwa
    FROM szczyty
    ORDER BY wysokosc DESC
    LIMIT 1;
    
    -- Zapytanie 3
    CREATE USER 'leon'@'localhost' IDENTIFIED BY 'Leon%Zawodowiec';
    
    -- Zapytanie 4
    GRANT SELECT, INSERT, UPDATE, DELETE
    ON gory.*
    TO 'leon'@'localhost';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: SHOW GRANTS z pełnymi tekstami i zrzut grants.png

    Kryteria:

    R.1.7 W pliku grants.png widoczne są przydzielone prawa dla użytkownika leon dla tabel bazy gory

    ok. 2 min
    Polecenie z arkusza

    Wykonanie zapytania 3 oraz 4 należy dodatkowo udokumentować obrazem o nazwie grants.png, na którym jest widoczny efekt wywołania polecenia SHOW GRANTS FOR ‘leon’@’localhost’;. Uwaga: należy zaznaczyć opcję „Pełne teksty” nad wyświetlanymi prawami

    Polecenie wpisane ze zwykłymi apostrofami: SHOW GRANTS FOR 'leon'@'localhost';. Nad wynikiem + Opcje → Pełne teksty → Wykonaj: widać GRANT USAGE (logowanie) i GRANT SELECT, INSERT, UPDATE, DELETE ONgory.*. Zrzut całego ekranu: grants.png.

    Typowe błędy

    Apostrofy drukarskie skopiowane z arkusza (‘ ’) dają błąd składni.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Etap 2: Grafika i strona HTML

    Kroki 9-18 · po tym etapie masz 19 z 38 kryteriów (pkt)

    Krok 9: Zdjęcie wykadrowane w pionie: 300 × 424 px

    Kryteria:

    R.2.1 Plik zdjecie .jpg wykadrowano tak, aby był widoczny zamek oraz fragment gór. Po wykadrowaniu obraz ma orientację pionową

    ok. 3 min
    Polecenie z arkusza

    Plik zdjecie.jpg, wypakowany z archiwum, należy wykadrować tak, aby był widoczny zamek oraz fragment gór. Po wykadrowaniu obraz ma orientację pionową. Przykład wykadrowania znajduje się po lewej stronie obrazu 2. Wymiary obrazu użytego w panelu lewym wynoszą 300 px na 424 px. Skadrowany obraz powinien mieć zbliżone wymiary.

    Oryginał 640 × 426 px. Narzędzie Kadrowanie w GIMP-ie (Shift+C), pozycja 60 × 1, rozmiar 300 × 424 - zamek w dolnej części, nad nim mgła i ośnieżone szczyty. Zapis pod tą samą nazwą (Plik → Zastąp zdjecie.jpg), bez skalowania.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Plik galeria.html

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku o nazwie galeria.html

    ok. 1 min
    Polecenie z arkusza

    Cechy witryny: Składa się ze strony o nazwie galeria.html

    Nowy plik galeria.html w folderze ze zdjęciami.

    galeria.html HTML nowy plik
    Podgląd strony po tym kroku (galeria.html)
  11. Krok 11: Szkielet HTML5, kodowanie i język

    Kryteria:

    R.2.3 Zastosowano deklarację języka HTML5, jawnie zapisany standard kodowania polskich znaków oraz zadeklarowano język witryny (np. <html lang = 'pl'>)

    ok. 2 min
    Polecenie z arkusza

    Zapisana w języku HTML5. Jawnie zastosowano właściwy standard kodowania polskich znaków. Zadeklarowany język zawartości witryny: polski

    Trzy zdania arkusza w jednym szkielecie: <!DOCTYPE html>, lang="pl" i <meta charset="UTF-8">. Linia viewport każe telefonowi wyświetlić stronę w szerokości ekranu - arkusz jej nie wymaga.

    galeria.html HTML zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  12. Krok 12: Tytuł strony i arkusz stylów

    Kryteria: ,

    R.2.4 Nadano tytuł stronie: "Galeria"

    R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl2.css , formatowanie 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

    Tytuł strony widoczny na karcie przeglądarki: „Galeria”. Arkusz stylów w pliku o nazwie styl2.css prawidłowo połączony z kodem strony

    <title> i <link> do styl2.css - całe formatowanie w tym pliku, bez atrybutów style.

    galeria.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  13. Krok 13: Bloki: baner, główna część z dwiema sekcjami i stopka

    Kryteria:

    R.2.5 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, lewy i prawy, stopka. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na: blok banera, obok siebie bloki lewy i prawy, stopka. Podział zrealizowany za pomocą znaczników sekcji tak, aby wygląd układu bloków strony po uruchomieniu w przeglądarce, był zgodny z Obrazem 2

    Baner <header>, stopka <footer>, a bloki lewy i prawy - dwie sekcje <section> z identyfikatorami left i right - stoją w znaczniku <main>. <main> to główna treść strony (jedna na stronę) i zarazem kontener siatki: CSS ułoży w nim sekcje obok siebie, a stopka pod nim zostanie na swoim miejscu bez clear (R.2.5).

    galeria.html HTML zmienione: 10 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
        </header>
        <main>
            <section id="left">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  14. Krok 14: Baner: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Galeria obrazów”

    <h1> w <header>.

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  15. Krok 15: Blok lewy: zdjęcie, nagłówek i tabela autorów

    Kryteria:

    R.2.7 W bloku lewym umieszczono tabelę o trzech wierszach i dwóch kolumnach, zastosowano znaczniki <table>, <tr>, <td>

    ok. 3 min
    Polecenie z arkusza

    Zawartość bloku lewego: obraz zdjecie.jpg z tekstem alternatywnym „zdjęcie dnia”, nagłówek trzeciego stopnia o treści „Zdjęcia opublikowali”, tabela o trzech wierszach i dwóch kolumnach wypełniona zgodnie z Obrazem 3

    Wykadrowane zdjęcie z alt, nagłówek <h3> i tabela przepisana z obrazu 3: trzy wiersze <tr> po dwie komórki <td> - osoba i liczba zdjęć (R.2.7). Tabela nie ma wiersza nagłówkowego, bo obraz 3 go nie pokazuje, a klucz wymaga znaczników <table>, <tr> i <td>.

    Typowe błędy

    „4 zdjęcia”, a nie „4 zdjęć”.

    galeria.html HTML zmienione: 16 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
                <img src="zdjecie.jpg" alt="zdjęcie dnia">
                <h3>Zdjęcia opublikowali</h3>
                <table>
                    <tr>
                        <td>Anna Porada</td>
                        <td>10 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Krzysztof Wasilewski</td>
                        <td>12 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Monika Kowalska</td>
                        <td>4 zdjęcia</td>
                    </tr>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  16. Krok 16: Blok prawy: przyciski, duże zdjęcie i linia

    Kryteria: ,

    R.2.8 W bloku lewym umieszczono obraz zdjecie.jpg z tekstem alternatywnym „zdjęcie dnia” oraz w bloku prawym obraz 1.jpg z tekstem alternatywnym „galeria”

    R.2.10 W bloku prawym umieszczono dwa przyciski opisane "prev" i "next"

    ok. 2 min
    Polecenie z arkusza

    Zawartość prawego bloku: przycisk o treści „prev”, którego kliknięcie uruchamia funkcję skryptu wyświetlającą poprzednie zdjęcie, obraz 1.jpg z tekstem alternatywnym „galeria”, przycisk o treści „next”, którego kliknięcie uruchamia funkcję skryptu wyświetlającą następne zdjęcie, linia horyzontalna

    Kolejność z arkusza: „prev”, duże zdjęcie, „next”, linia <hr>. Przyciski i zdjęcie dostają identyfikatory (prev, photo, next) - po nich skrypt przypnie obsługę kliknięć, a CSS ustawi wygląd tylko dużemu zdjęciu. type="button" mówi wprost, że przycisk niczego nie wysyła; bez tego atrybutu przycisk wstawiony kiedyś do formularza zacząłby go wysyłać.

    Zdjęcia w obu blokach mają teksty alternatywne (R.2.8), a przyciski - napisy „prev” i „next” (R.2.10).

    galeria.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
                <img src="zdjecie.jpg" alt="zdjęcie dnia">
                <h3>Zdjęcia opublikowali</h3>
                <table>
                    <tr>
                        <td>Anna Porada</td>
                        <td>10 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Krzysztof Wasilewski</td>
                        <td>12 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Monika Kowalska</td>
                        <td>4 zdjęcia</td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <button type="button" id="prev">prev</button>
                <img src="1.jpg" alt="galeria" id="photo">
                <button type="button" id="next">next</button>
                <hr>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  17. Krok 17: Blok prawy: pięć miniatur z numerem zdjęcia

    Kryteria:

    R.2.9 W bloku prawym umieszczono pięć zdjęć 1.jpg ÷ 5.jpg , przynajmniej jedno z nich ma tekst alternatywny "miniatura"

    ok. 2 min
    Polecenie z arkusza

    5 miniatur, kolejno 1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg. Każda miniatura ma tekst alternatywny „miniatura”. Po kliknięciu na miniaturę uruchamia się funkcja skryptu zamieniająca widoczne duże zdjęcie na kliknięte

    Pięć obrazów z alt="miniatura" i wspólną klasą thumb (R.2.9). Atrybut data-photo przechowuje numer zdjęcia: atrybuty zaczynające się od data- są przeznaczone na własne dane strony, a skrypt odczyta je jako thumb.dataset.photo. Numer nie musi być wtedy wyciągany z nazwy pliku ani wpisany w wywołanie funkcji w HTML-u.

    galeria.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
                <img src="zdjecie.jpg" alt="zdjęcie dnia">
                <h3>Zdjęcia opublikowali</h3>
                <table>
                    <tr>
                        <td>Anna Porada</td>
                        <td>10 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Krzysztof Wasilewski</td>
                        <td>12 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Monika Kowalska</td>
                        <td>4 zdjęcia</td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <button type="button" id="prev">prev</button>
                <img src="1.jpg" alt="galeria" id="photo">
                <button type="button" id="next">next</button>
                <hr>
                <img src="1.jpg" alt="miniatura" class="thumb" data-photo="1">
                <img src="2.jpg" alt="miniatura" class="thumb" data-photo="2">
                <img src="3.jpg" alt="miniatura" class="thumb" data-photo="3">
                <img src="4.jpg" alt="miniatura" class="thumb" data-photo="4">
                <img src="5.jpg" alt="miniatura" class="thumb" data-photo="5">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  18. Krok 18: Stopka: odnośnik w nowej karcie i autor

    Kryteria: ,

    R.3.2 Na stronie umieszczono odnośnik, którego kliknięcie inicjuje otwarcie strony https://pixabay.com w nowej karcie przeglądarki

    R.2.6 W bloku banera zapisano nagłówek h1: "Galeria obrazów", w bloku lewym - h3: "Zdjęcia opublikowali", w bloku stopki paragraf: „Galerię wykonał: "

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku stopki: odnośnik do strony https://pixabay.com otwierany w nowej karcie przeglądarki i podpisany „Więcej obrazów”, paragraf o treści „Galerię wykonał: ”, dalej wstawiony numer zdającego

    target="_blank" otwiera stronę w nowej karcie (R.3.2), a rel="noopener noreferrer" odcina obcej stronie dostęp do karty galerii (window.opener) i nie przekazuje jej adresu, z którego przyszedł użytkownik. W paragrafie po dwukropku na egzaminie stoi numer PESEL, tutaj Bartosz Bryniarski (R.2.6).

    galeria.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
                <img src="zdjecie.jpg" alt="zdjęcie dnia">
                <h3>Zdjęcia opublikowali</h3>
                <table>
                    <tr>
                        <td>Anna Porada</td>
                        <td>10 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Krzysztof Wasilewski</td>
                        <td>12 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Monika Kowalska</td>
                        <td>4 zdjęcia</td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <button type="button" id="prev">prev</button>
                <img src="1.jpg" alt="galeria" id="photo">
                <button type="button" id="next">next</button>
                <hr>
                <img src="1.jpg" alt="miniatura" class="thumb" data-photo="1">
                <img src="2.jpg" alt="miniatura" class="thumb" data-photo="2">
                <img src="3.jpg" alt="miniatura" class="thumb" data-photo="3">
                <img src="4.jpg" alt="miniatura" class="thumb" data-photo="4">
                <img src="5.jpg" alt="miniatura" class="thumb" data-photo="5">
            </section>
        </main>
        <footer>
            <a href="https://pixabay.com" target="_blank" rel="noopener noreferrer">Więcej obrazów</a>
            <p>Galerię wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (galeria.html)
  19. Etap 3: Styl CSS

    Kroki 19-26 · po tym etapie masz 30 z 38 kryteriów (pkt)

    Krok 19: Zmienne i wartości domyślne dla wszystkich elementów

    Kryteria: ,

    R.4.1 Ustawiono domyślne wartości dla selektorów (*): krój czcionki Garamond, wyrównanie tekstu do środka

    R.4.2 Ustawiono domyślne wartości dla selektorów (*): kolor tła MistyRose, kolor czcionki rgb(62, 39, 35)

    ok. 2 min
    Polecenie z arkusza

    Styl CSS powinien być zdefiniowany jedynie w zewnętrznym pliku CSS. Ustawione domyślne wartości dla wszystkich selektorów stylu CSS: krój czcionki Garamond, kolor tła MistyRose, kolor czcionki RGB: 62, 39,35; wyrównanie tekstu do środka

    Na początku styl2.css reguła :root ze zmiennymi CSS (nazwy od --): kolory z arkusza, cień 15px 15px 10px DimGray (występuje dwa razy) i margines 30 px (też dwa razy). Wartość odczytuje się przez var(--nazwa) - zmiana koloru albo cienia to jedna poprawka w jednym miejscu.

    Selektor * dostaje krój, tło, kolor i wyrównanie (R.4.1, R.4.2). Po przecinku serif - krój zapasowy, gdy Garamonda nie ma w systemie; Garamond jest pierwszy, więc to on jest używany.

    styl2.css CSS nowy plik
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    Podgląd strony po tym kroku (galeria.html)
  20. Krok 20: Bloki obok siebie: siatka 20% i 65%

    Kryteria: ,

    R.4.4 Ustawiono szerokość 20% dla bloku lewego i 65% dla bloku prawego (width lub grid- template-columns lub flex)

    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 układające bloki na stronie, np. float i clear albo display flex albo grid)

    ok. 3 min
    Polecenie z arkusza

    Dla bloku lewego: szerokość 20%, wysokość 600 px, marginesy zewnętrzne 30 px, cień bloku z przesunięciem równym 15 px w poziomie i pionie, rozmycie 10 px i kolor DimGray, w przypadku, gdy zawartość bloku nie mieści się dodawane są paski przewijania. Dla bloku prawego: szerokość 65%, wysokość 600 px

    display: grid w <main> i grid-template-columns: 20% 65% - dwie kolumny o szerokościach z arkusza; sekcje trafiają do nich w kolejności z HTML-u (R.4.4, R.3.1). Reszta szerokości (15%) zostaje wolna, jak na obrazie 2. align-items: start przykleja sekcje do góry kolumn, zamiast rozciągać je na wysokość wiersza.

    Margines bloku lewego (następny krok) mieści się w kolumnie: blok ma szerokość kolumny pomniejszoną o 2 × 30 px. Zmierzone w Chrome przy oknie 1280 px: kolumna ma 248 px, blok lewy 188 px (w wersji podstawowej 248 px plus marginesy na zewnątrz), blok prawy 807 px - tyle samo co w wersji podstawowej. Klucz przyjmuje szerokości ustawione przez grid-template-columns.

    styl2.css CSS zmienione: 6 linii
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    Podgląd strony po tym kroku (galeria.html)
  21. Krok 21: Bloki: wysokość, a lewy także margines, cień i przewijanie

    Kryteria: ,

    R.4.3 Ustawiono wysokość 600px dla bloku lewego i prawego

    R.4.6 Ustawiono dla bloku lewego lub dla dużego obrazu z bloku prawego cień o cechach: oba przesunięcia 15 px, rozmycie 10px, kolor DimGray, np. box-shadow: 15px 15px 10px DimGray (lub 15px 15px 10px 0 DimGray)

    ok. 2 min
    Polecenie z arkusza

    Dla bloku lewego: szerokość 20%, wysokość 600 px, marginesy zewnętrzne 30 px, cień bloku z przesunięciem równym 15 px w poziomie i pionie, rozmycie 10 px i kolor DimGray, w przypadku, gdy zawartość bloku nie mieści się dodawane są paski przewijania. Dla bloku prawego: szerokość 65%, wysokość 600 px

    Wspólna wysokość obu bloków w jednej regule z dwoma selektorami (R.4.3). Blok lewy dostaje margines 30 px, cień ze zmiennej - przesunięcie 15 px w prawo i w dół, rozmycie 10 px, kolor DimGray (R.4.6) - oraz overflow: auto: pasek przewijania pojawia się tylko wtedy, gdy zawartość nie mieści się w 600 px.

    styl2.css CSS zmienione: 10 linii
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    Podgląd strony po tym kroku (galeria.html)
  22. Krok 22: Zdjęcie w bloku lewym: szerokość 100%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu umieszczonego jedynie w bloku lewym: szerokość 100%

    Selektor potomka #left img - obraz wewnątrz bloku lewego, zgodnie z uwagą w arkuszu (selektor znacznika obrazu, nie klasa). Zdjęcie wypełnia szerokość bloku, wysokość przelicza się z zachowaniem proporcji.

    styl2.css CSS zmienione: 4 linie
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    
    #left img {
        width: 100%;
    }
    Podgląd strony po tym kroku (galeria.html)
  23. Krok 23: Miniatury: rozmiar, zaokrąglenie i miejsce na ramkę

    Kryteria:

    R.4.8 Ustawiono zaokrąglenie rogów (border-radius) 5% jedynie dla miniatur oraz paski przewijania w przypadku przepełnienia bloku lewego (overflow: auto;)

    ok. 2 min
    Polecenie z arkusza

    Jedynie dla miniatur: szerokość 140 px, marginesy wewnętrzne 2 px, zaokrąglenie rogów 5%.

    Wartości z arkusza: width: 140px, padding: 2px, border-radius: 5% (R.4.8 - razem z przewijaniem bloku lewego). Dwie linie ponad arkusz:

    • border: 1px solid transparent - niewidoczna ramka, która od początku zajmuje swój 1 px. Gdy pod kursorem pojawi się ramka kropkowa, miniatury nie przesuną się o 2 px, jak w wersji podstawowej,
    • cursor: pointer - kursor „rączki” podpowiada, że miniaturę można kliknąć.
    styl2.css CSS zmienione: 8 linii
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    
    #left img {
        width: 100%;
    }
    
    .thumb {
        width: 140px;
        padding: 2px;
        border-radius: 5%;
        border: 1px solid transparent;
        cursor: pointer;
    }
    Podgląd strony po tym kroku (galeria.html)
  24. Krok 24: Miniatura pod kursorem: ramka kropkowa

    Kryteria:

    R.4.9 Ustawiono pseudoklasę hover dla miniatur. Gdy kursor znajdzie się na miniaturze pojawia się ramka o szerokości 1 px, czarną linią kropkową (dotted)

    ok. 1 min
    Polecenie z arkusza

    Gdy kursor znajdzie się na miniaturze pojawia się ramka o szerokości 1 px, czarną linią kropkową

    Pseudoklasa :hover zamienia przezroczystą ramkę na czarną kropkową (dotted) o szerokości 1 px (R.4.9). Rozmiar miniatury się nie zmienia - sprawdzone w Chrome.

    styl2.css CSS zmienione: 4 linie
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    
    #left img {
        width: 100%;
    }
    
    .thumb {
        width: 140px;
        padding: 2px;
        border-radius: 5%;
        border: 1px solid transparent;
        cursor: pointer;
    }
    
    .thumb:hover {
        border: 1px dotted black;
    }
    Podgląd strony po tym kroku (galeria.html)
  25. Krok 25: Duże zdjęcie: szerokość, marginesy i cień

    Kryteria: ,

    R.4.5 Ustawiono marginesy zewnętrzne (margin) 30px dla bloku lewego, 30px dla dużego obrazu w bloku prawym i marginesy wewnętrzne (padding) 2px dla miniatur

    R.4.7 Ustawiono szerokość 100% dla selektora img umieszczonego jedynie w bloku lewym np. z użyciem selektora dziecka lub potomka, 500px dla dużego obrazu z bloku prawego oraz 140px dla miniatur

    ok. 1 min
    Polecenie z arkusza

    Jedynie dla dużego obrazu z bloku prawego: szerokość 500 px, marginesy zewnętrzne 30 px, cień bloku z przesunięciem równym 15 px w poziomie i pionie, rozmycie 10 px i kolor DimGray

    Selektor #photo, margines i cień z tych samych zmiennych co blok lewy. Komplet marginesów (R.4.5) i szerokości obrazów: 100%, 500 px, 140 px (R.4.7) jest ustawiony.

    styl2.css CSS zmienione: 6 linii
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    
    #left img {
        width: 100%;
    }
    
    .thumb {
        width: 140px;
        padding: 2px;
        border-radius: 5%;
        border: 1px solid transparent;
        cursor: pointer;
    }
    
    .thumb:hover {
        border: 1px dotted black;
    }
    
    #photo {
        width: 500px;
        margin: var(--space);
        box-shadow: var(--shadow);
    }
    Podgląd strony po tym kroku (galeria.html)
  26. Krok 26: Tabela: obramowanie kreskowe i szerokość 100%

    Kryteria:

    R.4.10 Ustawiono dla selektora tabeli obramowanie o szerokości 1 px, czarną linią kreskową (dashed) oraz szerokość 100%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora tabeli: obramowanie o szerokości 1 px, czarną linią kreskową, szerokość 100%

    Selektor znacznika table, linia kreskowa dashed, ramka tylko wokół tabeli - jak na obrazie 3 (R.4.10).

    styl2.css CSS zmienione: 5 linii
    :root {
        --background: MistyRose;
        --text: rgb(62, 39, 35);
        --shadow: 15px 15px 10px DimGray;
        --space: 30px;
    }
    
    * {
        font-family: Garamond, serif;
        background-color: var(--background);
        color: var(--text);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 65%;
        align-items: start;
    }
    
    #left, #right {
        height: 600px;
    }
    
    #left {
        margin: var(--space);
        box-shadow: var(--shadow);
        overflow: auto;
    }
    
    #left img {
        width: 100%;
    }
    
    .thumb {
        width: 140px;
        padding: 2px;
        border-radius: 5%;
        border: 1px solid transparent;
        cursor: pointer;
    }
    
    .thumb:hover {
        border: 1px dotted black;
    }
    
    #photo {
        width: 500px;
        margin: var(--space);
        box-shadow: var(--shadow);
    }
    
    table {
        border: 1px dashed black;
        width: 100%;
    }
    Podgląd strony po tym kroku (galeria.html)
  27. Etap 4: JavaScript

    Kroki 27-32 · po tym etapie masz 38 z 38 kryteriów (pkt)

    Krok 27: Plik galeria.js, zmienna aktywnego zdjęcia i duże zdjęcie

    Kryteria:

    R.5.1 Skrypt zapisano w języku JavaScript i zawarto w nim przynajmniej jedną poprawną składniowo instrukcję języka

    ok. 3 min
    Polecenie z arkusza

    Napisany w języku JavaScript. Składa się z trzech funkcji obsługujących wyświetlanie dużego zdjęcia w bloku prawym, zwanego dalej aktywnym zdjęciem oraz zmiennej liczbowej przechowującej numer aktywnego zdjęcia

    Skrypt w osobnym pliku galeria.js, dołączonym w <head> przez <script src="galeria.js" defer>. defer każe przeglądarce wykonać skrypt dopiero po wczytaniu całego HTML-u - duże zdjęcie i przyciski już wtedy istnieją, choć znacznik stoi na górze strony.

    • const PHOTO_COUNT = 5; - liczba zdjęć jako stała (const nie da się nadpisać); w warunkach zamiast „magicznej” piątki stoi nazwa,
    • let activePhoto = 1; - zmienna liczbowa z numerem aktywnego zdjęcia, na początku pierwsze,
    • const photo = document.getElementById("photo"); - duże zdjęcie wyszukane raz, a nie przy każdym kliknięciu.

    Skrypt jest napisany w JavaScript i ma poprawne instrukcje (R.5.1).

    galeria.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Galeria</title>
        <link rel="stylesheet" href="styl2.css">
        <script src="galeria.js" defer></script>
    </head>
    <body>
        <header>
            <h1>Galeria obrazów</h1>
        </header>
        <main>
            <section id="left">
                <img src="zdjecie.jpg" alt="zdjęcie dnia">
                <h3>Zdjęcia opublikowali</h3>
                <table>
                    <tr>
                        <td>Anna Porada</td>
                        <td>10 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Krzysztof Wasilewski</td>
                        <td>12 zdjęć</td>
                    </tr>
                    <tr>
                        <td>Monika Kowalska</td>
                        <td>4 zdjęcia</td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <button type="button" id="prev">prev</button>
                <img src="1.jpg" alt="galeria" id="photo">
                <button type="button" id="next">next</button>
                <hr>
                <img src="1.jpg" alt="miniatura" class="thumb" data-photo="1">
                <img src="2.jpg" alt="miniatura" class="thumb" data-photo="2">
                <img src="3.jpg" alt="miniatura" class="thumb" data-photo="3">
                <img src="4.jpg" alt="miniatura" class="thumb" data-photo="4">
                <img src="5.jpg" alt="miniatura" class="thumb" data-photo="5">
            </section>
        </main>
        <footer>
            <a href="https://pixabay.com" target="_blank" rel="noopener noreferrer">Więcej obrazów</a>
            <p>Galerię wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    galeria.js JavaScript nowy plik
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    Podgląd strony po tym kroku (galeria.html)
  28. Krok 28: Funkcja zmieniająca duże zdjęcie

    Kryteria:

    R.5.2 Zapisano w skrypcie przynajmniej jedną poprawną składniowo funkcję zmieniającą w bloku prawym wartość atrybutu .src dużego zdjęcia (prawidłowa definicja funkcji i operacja getElementBy…)

    ok. 2 min
    Polecenie z arkusza

    Po kliknięciu na miniaturę, aktywnym zdjęciem staje się to kliknięte.

    Jedyne miejsce, które zmienia zdjęcie. showPhoto(number) zapisuje numer w zmiennej activePhoto i ustawia atrybut src dużego zdjęcia, wyszukanego wcześniej metodą getElementById (R.5.2). Nazwę pliku składa szablon tekstowy w odwrotnych apostrofach: ${activePhoto} wstawia wartość zmiennej, więc dla 3 powstaje 3.jpg.

    Funkcja od razu obsługuje miniatury: kliknięta miniatura poda swój numer. Następne dwie funkcje tylko wyliczą numer i przekażą go tutaj - zmienna i obraz nie rozjadą się nigdy.

    galeria.js JavaScript zmienione: 5 linii
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    
    function showPhoto(number) {
        activePhoto = number;
        photo.src = `${activePhoto}.jpg`;
    }
    Podgląd strony po tym kroku (galeria.html)
  29. Krok 29: Funkcje „next” i „prev” z przejściem przez koniec

    Kryteria: ,

    R.5.4 Po kliknięciu przycisku prev duże zdjęcie jest zmieniane na poprzednie lub w przypadku pierwszego - na piąte

    R.5.5 Po kliknięciu przycisku next duże zdjęcie jest zmieniane na następne lub w przypadku piątego - na pierwsze

    ok. 3 min
    Polecenie z arkusza

    Wciśnięcie przycisku „next” zmienia aktywne zdjęcie na następne. Ponieważ zdjęć jest 5, gdy aktywnym zdjęciem jest piąte, po wciśnięciu „next” aktywnym zdjęciem zostaje pierwsze. Podobnie wciskając przycisk „prev”, aktywne zdjęcie jest zmieniane na poprzednie, np. 4 -> 3, 3 -> 2 ale 1 -> 5.

    Każda funkcja to jedna linia z operatorem warunkowym warunek ? wartość_gdy_tak : wartość_gdy_nie:

    • showNext - przy ostatnim zdjęciu (activePhoto === PHOTO_COUNT) numer 1, w przeciwnym razie następny,
    • showPrevious - przy pierwszym zdjęciu numer PHOTO_COUNT, czyli 5, w przeciwnym razie poprzedni.

    Porównanie === sprawdza wartość i typ - nie ma tu niespodzianek z zamianą napisu na liczbę. Skrypt ma teraz zmienną i trzy funkcje, jak wymaga arkusz (R.5.4, R.5.5 - sprawdzone w Chrome po przypięciu przycisków).

    galeria.js JavaScript zmienione: 8 linii
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    
    function showPhoto(number) {
        activePhoto = number;
        photo.src = `${activePhoto}.jpg`;
    }
    
    function showNext() {
        showPhoto(activePhoto === PHOTO_COUNT ? 1 : activePhoto + 1);
    }
    
    function showPrevious() {
        showPhoto(activePhoto === 1 ? PHOTO_COUNT : activePhoto - 1);
    }
    Podgląd strony po tym kroku (galeria.html)
  30. Krok 30: Przyciski: nasłuchiwacze kliknięcia

    Kryteria:

    R.3.3 Dla dowolnego przycisku zdefiniowano obsługę zdarzenia kliknięcia (atrybut onClick lub słuchacz zdarzenia click, lub właściwość onclick obiektu DOM)

    ok. 2 min
    Polecenie z arkusza

    przycisk o treści „next”, którego kliknięcie uruchamia funkcję skryptu wyświetlającą następne zdjęcie

    addEventListener("click", showNext) przypina funkcję do kliknięcia przycisku. Nazwa funkcji stoi bez nawiasów - przekazujesz samą funkcję, którą przeglądarka wywoła przy kliknięciu; showNext() z nawiasami wykonałoby ją od razu przy wczytaniu strony. HTML nie ma żadnego onclick - wygląd i zachowanie są rozdzielone (R.3.3).

    Sprawdzone w Chrome: pięć kliknięć „next” od pierwszego zdjęcia daje 2, 3, 4, 5, 1, a dwa „prev” potem - 5 i 4.

    galeria.js JavaScript zmienione: 3 linie
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    
    function showPhoto(number) {
        activePhoto = number;
        photo.src = `${activePhoto}.jpg`;
    }
    
    function showNext() {
        showPhoto(activePhoto === PHOTO_COUNT ? 1 : activePhoto + 1);
    }
    
    function showPrevious() {
        showPhoto(activePhoto === 1 ? PHOTO_COUNT : activePhoto - 1);
    }
    
    document.getElementById("next").addEventListener("click", showNext);
    document.getElementById("prev").addEventListener("click", showPrevious);
    Podgląd strony po tym kroku (galeria.html)
  31. Krok 31: Miniatury: kliknięcie wybiera zdjęcie

    Kryteria: , ,

    R.3.4 Dla dowolnej miniatury zdefiniowano obsługę zdarzenia kliknięcia (atrybut onClick lub słuchacz zdarzenia click, lub właściwość onclick obiektu DOM)

    R.5.3 Funkcje skryptu są kontrolowane przez zmienną przechowującą numer zdjęcia. Zmienna jest modyfikowana zgodnie z kontekstem aplikacji, wg wzoru: 1. przycisk next -> gdy zdjęcie 5 -> 1 lub inkrementacja 2. przycisk prev -> gdy zdjęcie 1 -> 5 lub dekrementacja 3. miniatura -> zmienna przyjmuje wartość numeru zdjęcia np. zmienna = parseInt(nazwa);

    R.5.6 Po kliknięciu miniatury duże zdjęcie jest zmieniane na zdjęcie odpowiadające miniaturze (przetestować na zmianę z przyciskami)

    ok. 3 min
    Polecenie z arkusza

    Aplikacja utrzymuje kontekst tak, że użytkownik może nawigować na zmianę miniaturami oraz przyciskami.

    • document.querySelectorAll(".thumb") - wszystkie miniatury (selektor jak w CSS),
    • for (const thumb of …) - pętla po każdej z nich,
    • () => showPhoto(Number(thumb.dataset.photo)) - funkcja strzałkowa wywoływana przy kliknięciu: odczytuje numer z atrybutu data-photo (dataset daje napis, Number zamienia go na liczbę) i przekazuje go do showPhoto (R.3.4).

    Zmienna activePhoto zmienia się tylko w showPhoto, więc kontekst jest zawsze wspólny (R.5.3). Sprawdzone w Chrome, na zmianę: miniatura 4 → 4.jpg, „next” → 5.jpg, „next” → 1.jpg, „prev” → 5.jpg, miniatura 1 → 1.jpg, „prev” → 5.jpg (R.5.6).

    Typowe błędy

    Bez Number zmienna dostaje napis "4" - porównanie "4" === 5 jest fałszywe zawsze, a "4" + 1 to "41": „next” po miniaturze pokazałby plik 41.jpg.

    galeria.js JavaScript zmienione: 4 linie
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    
    function showPhoto(number) {
        activePhoto = number;
        photo.src = `${activePhoto}.jpg`;
    }
    
    function showNext() {
        showPhoto(activePhoto === PHOTO_COUNT ? 1 : activePhoto + 1);
    }
    
    function showPrevious() {
        showPhoto(activePhoto === 1 ? PHOTO_COUNT : activePhoto - 1);
    }
    
    document.getElementById("next").addEventListener("click", showNext);
    document.getElementById("prev").addEventListener("click", showPrevious);
    
    for (const thumb of document.querySelectorAll(".thumb")) {
        thumb.addEventListener("click", () => showPhoto(Number(thumb.dataset.photo)));
    }
    Podgląd strony po tym kroku (galeria.html)
  32. Krok 32: Strzałki na klawiaturze (poza arkuszem)

    ok. 2 min

    Dodatek, którego arkusz i klucz nie wymagają: nasłuchiwacz keydown na całym dokumencie. Strzałka w prawo wywołuje showNext, w lewo - showPrevious; event.key to nazwa wciśniętego klawisza. Te same funkcje co przy przyciskach, więc numer zdjęcia zostaje wspólny. Galerią da się wtedy przeglądać także bez myszy.

    Sprawdzone w Chrome: dwie strzałki w prawo od pierwszego zdjęcia pokazują 3.jpg, strzałka w lewo - 2.jpg.

    galeria.js JavaScript zmienione: 8 linii
    const PHOTO_COUNT = 5;
    let activePhoto = 1;
    const photo = document.getElementById("photo");
    
    function showPhoto(number) {
        activePhoto = number;
        photo.src = `${activePhoto}.jpg`;
    }
    
    function showNext() {
        showPhoto(activePhoto === PHOTO_COUNT ? 1 : activePhoto + 1);
    }
    
    function showPrevious() {
        showPhoto(activePhoto === 1 ? PHOTO_COUNT : activePhoto - 1);
    }
    
    document.getElementById("next").addEventListener("click", showNext);
    document.getElementById("prev").addEventListener("click", showPrevious);
    
    for (const thumb of document.querySelectorAll(".thumb")) {
        thumb.addEventListener("click", () => showPhoto(Number(thumb.dataset.photo)));
    }
    
    document.addEventListener("keydown", (event) => {
        if (event.key === "ArrowRight") {
            showNext();
        } else if (event.key === "ArrowLeft") {
            showPrevious();
        }
    });
    Podgląd strony po tym kroku (galeria.html)
  33. Etap 5: Porównanie z wersją podstawową

    Krok 33 · po tym etapie masz 38 z 38 kryteriów (pkt)

    Krok 33: Co jest inaczej i którą wersję wybrać na egzaminie

    ok. 3 min

    Obie wersje dają komplet 38 punktów. Różnice:

    wersja podstawowawersja nowoczesna
    układfloat: left sekcji, clear stopki<main> z grid-template-columns: 20% 65%
    szerokość bloku lewego20% okna, margines na zewnątrzkolumna 20%, margines w środku kolumny
    powtarzane wartościwpisane w każdej regulezmienne --shadow, --space, kolory
    ramka miniatury pod kursoremdokłada 2 px, sąsiednie miniatury się przesuwająprzezroczysta ramka od początku, nic się nie rusza
    skrypt<script> na końcu stronyplik galeria.js z defer
    przyciski i miniaturyonclick="…" w HTML-uaddEventListener w skrypcie
    numer miniaturywpisany w wywołanie showPhoto(4)atrybut data-photo="4"
    zmiana zdjęciatrzy funkcje, każda ustawia srcjedna showPhoto, dwie pozostałe tylko liczą numer
    przejście przez koniecif / elseoperator warunkowy ? : i stała PHOTO_COUNT
    klawiaturabrakstrzałki w lewo i w prawo
    odnośniktarget="_blank"do tego rel="noopener noreferrer"

    Na egzaminie wersja podstawowa trzyma się metod z tabeli 1 arkusza i łatwiej ją napisać bez dokumentacji. Nowoczesna łatwiej się rozbudowuje: szóste zdjęcie to jedna miniatura w HTML-u i zmiana stałej PHOTO_COUNT - a klucz przyjmuje obie.

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

  34. Etap 6: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

    UWAGA: po zakończeniu pracy utwórz w folderze z numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Nagraj płytę z rezultatami pracy. W folderze powinny się znajdować pliki z grafiką 1.jpg ÷ 5.jpg oraz pliki: galeria.html, grants.png, import.jpg, kw1.png, kw2.png, kw3.png, kw4.png, kwerendy.txt, przeglądarka.txt, styl2.css, zdjecie.jpg ewentualnie inne przygotowane pliki. Po nagraniu płyty sprawdź poprawność nagrania. Opisz płytę numerem, którym został podpisany arkusz i pozostaw na stanowisku, zapakowaną w pudełku wraz z arkuszem egzaminacyjnym.

    W przeglądarka.txt nazwa przeglądarki. Na płytę idą pliki z listy w arkuszu oraz galeria.js - bez niego strona na płycie nie zmieni zdjęcia ani razu, a egzaminator sprawdza skrypt w przeglądarce. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    Typowe błędy

    Pominięty galeria.js to utrata praktycznie całego rezultatu „Skrypt” i kryteriów R.3.3 i R.3.4.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.

Potwierdzenie

Informacja