Przejdź do głównej treści
INF.03-09-26.06-SGCzerwiec 2026 · 47 kroków · ok. 79 min · 35 kryteriów z klucza

Rozwiązanie krok po kroku: Aplikacja internetowa restauracji (Nowoczesny kod (grid, zdarzenia))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza restauracja z pięcioma zapytaniami i strona index.html z sześcioma klikanymi potrawami, listą zamówienia i dwoma przyciskami - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • zmienne CSS: zieleń #778A35 pojawia się w arkuszu pięć razy, w kodzie jest wpisana raz,
  • bloki potraw na siatce CSS (display: grid na sekcji potraw) zamiast display: inline-block na każdym bloku,
  • skrypt w osobnym pliku skrypt.js z atrybutem defer: jeden nasłuchiwacz zdarzeń na całej sekcji potraw zamiast sześciu atrybutów onclick, nazwa potrawy czytana z jej podpisu, textContent zamiast innerHTML, potrawę można dodać także klawiaturą,
  • zapytania z aliasami i warunkiem na przedział dat zamiast funkcji DATE().

Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza, zdjęcia i logo pochodzą z prawdziwego archiwum pliki19, zapytania zostały wykonane na tej bazie w MariaDB z XAMPP-a, a skrypty sprawdzone w prawdziwej przeglądarce. Strona w podglądzie działa - od kroków ze skryptem można klikać potrawy i przyciski.

Jak liczą się punkty. Klucz ma 35 kryteriów (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania to 75%, czyli 27 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.

  1. Etap 1: Baza danych

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

    Krok 1: Baza danych restauracja

    ok. 2 min
    Polecenie z arkusza

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

    Archiwum pliki19.7z rozpakuj hasłem ReStAuRac1a (wielkość liter ma znaczenie, przed ostatnią literą jest cyfra 1). W phpMyAdmin Nowa → restauracja, porównywanie utf8_polish_ci - albo jednym poleceniem:

    CREATE DATABASE restauracja CHARACTER SET utf8 COLLATE utf8_polish_ci;
    
  2. Krok 2: Import tabel z pliku restauracja.sql

    ok. 2 min
    Polecenie z arkusza

    Do utworzonej bazy zaimportuj tabele z pliku restauracja.sql.

    Import → restauracja.sql → Wykonaj. Pięć tabel z ilustracji 1: Kelnerzy, Stoliki, Zamowienia, Potrawy i tabela łącząca ZamowieniaPotrawy (jedno zamówienie ma wiele potraw, jedna potrawa trafia do wielu zamówień - relacja wiele do wielu zawsze potrzebuje takiej trzeciej tabeli).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych restauracja - plik import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą 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.

    Cały ekran z paskiem zadań, zapis jako import.png (w tym arkuszu wszystkie zrzuty są w PNG).

    Typowe błędy

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

  4. Krok 4: Zapytanie 1: kelnerzy malejąco po nazwisku

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie imię i nazwisko kelnera z tabeli Kelnerzy. Wyniki posortowane są malejąco według nazwiska. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT imie, nazwisko FROM Kelnerzy ORDER BY nazwisko DESC; oraz na zrzucie widoczne są dokładnie 3 rekordy (dla Piotra, Anny i Jana)

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie imiona i nazwiska kelnerów posortowane malejąco według nazwiska.

    Każda klauzula w osobnej linii - tak zapytanie czyta się od góry: co (SELECT imie, nazwisko), skąd (FROM Kelnerzy), w jakiej kolejności (ORDER BY nazwisko DESC - malejąco, od Z do A).

    Wynik: 3 wiersze - Piotr Wiśniewski, Anna Nowak, Jan Kowalski, jak w kluczu. Zapytania zapisuj w kwerendy.txt, zrzut jako kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, nazwisko
    FROM Kelnerzy
    ORDER BY nazwisko DESC;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: zamówienia przy stoliku 3 w sali 1

    Kryteria:

    R.1.4 Wykonane zapytanie 2 zliczające jedynie liczbę zamówień, które zostały złożone dla stolika numer 3 w sali numer 1. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT COUNT(*) FROM Zamowienia JOIN Stoliki ON Stoliki.id = idStolika WHERE numerStolika = 3 AND sala = 1; (możliwe również porównanie kluczy po WHERE) oraz na zrzucie widoczny jest jeden wiersz z wartością 2

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: zliczające jedynie liczbę zamówień, które zostały złożone dla stolika numer 3 w sali numer 1. Należy posłużyć się relacją.

    • FROM Zamowienia AS z JOIN Stoliki AS s - aliasy z i s to krótkie nazwy tabel na czas zapytania; zamiast Stoliki.numerStolika piszesz s.numerStolika,
    • ON s.id = z.idStolika - warunek złączenia stoi przy JOIN, a nie w WHERE: od razu widać, którą parą kluczy łączą się tabele, a WHERE zostaje na warunki z treści zadania,
    • WHERE s.numerStolika = 3 AND s.sala = 1 - stolik numer 3 jest w obu salach, więc potrzebne są oba warunki,
    • COUNT(*) AS liczba_zamowien - jedna liczba z czytelnym nagłówkiem kolumny zamiast COUNT(*).

    Wynik: jeden wiersz z wartością 2 (zamówienia 3 i 4). Zrzut: kw2.png.

    Typowe błędy

    WHERE idStolika = 3 bez złączenia porównuje identyfikator stolika, a nie jego numer. W tej bazie trafia przypadkiem (stolik o id 3 to stolik nr 3 w sali 1), ale klucz wymaga relacji i zapytania uniwersalnego.

    kwerendy.txt Tekst zmienione: 7 linii
    -- Zapytanie 1
    SELECT imie, nazwisko
    FROM Kelnerzy
    ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) AS liczba_zamowien
    FROM Zamowienia AS z
    JOIN Stoliki AS s ON s.id = z.idStolika
    WHERE s.numerStolika = 3
      AND s.sala = 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: potrawy zamówione 9 czerwca 2024

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie nazwy potraw, które zostały zamówione dnia 9 czerwca 2024. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT nazwa FROM Potrawy JOIN ZamowieniaPotrawy ON idPotrawy = Potrawy.id JOIN Zamowienia ON idZamowienia = Zamowienia.id WHERE DATE(Zamowienia.dataZlozenia)='2024-06-09'; (możliwe również porównanie kluczy po WHERE) oraz na zrzucie widoczny jest jedynie jeden rekord o treści Spaghetti bolognese

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie nazwy potraw, które zostały zamówione dnia 9 czerwca 2024. Należy posłużyć się relacją.

    Od potrawy do daty prowadzi droga przez tabelę łączącą: Potrawy → ZamowieniaPotrawy (pozycje zamówień) → Zamowienia (data). Dwa JOIN, każdy ze swoim ON.

    Pole dataZlozenia przechowuje datę i godzinę (2024-06-09 14:30:00). Zamiast odcinać godzinę funkcją DATE() (jak w przykładzie z klucza), warunek opisuje przedział: od północy 9 czerwca włącznie do północy 10 czerwca wyłącznie. Wynik jest ten sam, a różnica wychodzi przy dużych tabelach: na samej kolumnie serwer może użyć indeksu, a na DATE(kolumna) musi przeliczyć funkcję dla każdego wiersza.

    Wynik: jeden wiersz - Spaghetti bolognese (sprawdzone na tej bazie, z DATE() wychodzi to samo). Zrzut: kw3.png.

    Typowe błędy

    WHERE z.dataZlozenia = '2024-06-09' daje pusty wynik - serwer porównuje z północą, a zamówienie złożono o 14:30. <= '2024-06-09 23:59:59' gubi ułamki sekund; bezpieczny jest warunek < '2024-06-10'.

    kwerendy.txt Tekst zmienione: 8 linii
    -- Zapytanie 1
    SELECT imie, nazwisko
    FROM Kelnerzy
    ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) AS liczba_zamowien
    FROM Zamowienia AS z
    JOIN Stoliki AS s ON s.id = z.idStolika
    WHERE s.numerStolika = 3
      AND s.sala = 1;
    
    -- Zapytanie 3
    SELECT p.nazwa
    FROM Potrawy AS p
    JOIN ZamowieniaPotrawy AS zp ON zp.idPotrawy = p.id
    JOIN Zamowienia AS z ON z.id = zp.idZamowienia
    WHERE z.dataZlozenia >= '2024-06-09'
      AND z.dataZlozenia < '2024-06-10';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: użytkownik administrator

    Kryteria:

    R.1.6 Wykonane zapytanie 4 tworzące konto użytkownika lokalnego o nazwie administrator i haśle boss123!. W pliku z kwerendami lub na zrzucie istnieje zapis np. CREATE USER administator@localhost IDENTIFIED BY 'boss123!'; oraz na zrzucie jest widoczny komunikat o poprawnie wykonanym zapytaniu. (dopuszczalny jest błąd informujący o niewybraniu bazy, @localhost wymagany)

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: tworzące nowego użytkownika lokalnego o nazwie administrator i haśle boss123!

    • 'administrator'@'localhost' - konto to para nazwa + host; „lokalny” oznacza localhost, czyli logowanie tylko z komputera, na którym działa serwer (klucz R.1.6 wymaga @localhost),
    • IDENTIFIED BY 'boss123!' - hasło w apostrofach; serwer zapisze z niego tylko skrót, nie sam tekst.

    Nowe konto nie ma żadnych uprawnień - nadaje się je osobno poleceniem GRANT (arkusz tego nie wymaga). Zrzut kw4.png: konto na liście użytkowników.

    Typowe błędy

    Przykład w kluczu ma literówkę („administator”) - nazwa z arkusza to administrator. Bez @'localhost' powstaje konto 'administrator'@'%' (dowolny host), czyli nie lokalne.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, nazwisko
    FROM Kelnerzy
    ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) AS liczba_zamowien
    FROM Zamowienia AS z
    JOIN Stoliki AS s ON s.id = z.idStolika
    WHERE s.numerStolika = 3
      AND s.sala = 1;
    
    -- Zapytanie 3
    SELECT p.nazwa
    FROM Potrawy AS p
    JOIN ZamowieniaPotrawy AS zp ON zp.idPotrawy = p.id
    JOIN Zamowienia AS z ON z.id = zp.idZamowienia
    WHERE z.dataZlozenia >= '2024-06-09'
      AND z.dataZlozenia < '2024-06-10';
    
    -- Zapytanie 4
    CREATE USER 'administrator'@'localhost'
        IDENTIFIED BY 'boss123!';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: Zapytanie 5: cena jako DECIMAL(6,2)

    Kryteria:

    R.1.7 Wykonane zapytanie 5 zmieniające strukturę tabeli Potrawy poprzez modyfikację typu kolumny cena na decimal(6,2), przy jednoczesnym zachowaniu ograniczenia NOT NULL. W pliku z kwerendami lub na zrzucie istnieje zapis np. ALTER TABLE Potrawy MODIFY cena DECIMAL(6,2) NOT NULL; (zastosowanie CHANGE zamiast MODIFY wymaga dwukrotnego podania kolumny; możliwy też typ numeric) oraz na zrzucie jest widoczny komunikat o poprawnie wykonanym zapytaniu lub zmieniona struktura tabeli

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 5: zmieniające strukturę tabeli Potrawy poprzez zmianę typu kolumny cena w taki sposób, aby przechowywała ona liczby rzeczywiste składające się z maksimum 4 cyfr w części całkowitej (przed przecinkiem) i 2 cyfr w części ułamkowej (po przecinku). Typ ten powinien przechowywać dane w zapisie stałoprzecinkowym. Należy zachować wszystkie dotychczasowe ograniczenia nałożone na kolumnę.

    Typ stałoprzecinkowy to DECIMAL(M, D): M - liczba wszystkich cyfr, D - cyfr po przecinku. 4 + 2 = DECIMAL(6,2), największa wartość 9999.99. Dotąd kolumna miała DECIMAL(5,2) i NOT NULL.

    MODIFY podaje całą nową definicję kolumny - czego nie napiszesz, tego kolumna nie będzie miała. Dlatego NOT NULL trzeba powtórzyć (bez niego kolumna zaczęłaby przyjmować NULL - sprawdzone na kopii tabeli w wersji podstawowej). Zrzut kw5.png: struktura po zmianie.

    Typowe błędy

    FLOAT i DOUBLE są zmiennoprzecinkowe - przy kwotach dają błędy zaokrągleń (0.1 + 0.2 to nie dokładnie 0.3), a arkusz żąda zapisu stałoprzecinkowego.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, nazwisko
    FROM Kelnerzy
    ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) AS liczba_zamowien
    FROM Zamowienia AS z
    JOIN Stoliki AS s ON s.id = z.idStolika
    WHERE s.numerStolika = 3
      AND s.sala = 1;
    
    -- Zapytanie 3
    SELECT p.nazwa
    FROM Potrawy AS p
    JOIN ZamowieniaPotrawy AS zp ON zp.idPotrawy = p.id
    JOIN Zamowienia AS z ON z.id = zp.idZamowienia
    WHERE z.dataZlozenia >= '2024-06-09'
      AND z.dataZlozenia < '2024-06-10';
    
    -- Zapytanie 4
    CREATE USER 'administrator'@'localhost'
        IDENTIFIED BY 'boss123!';
    
    -- Zapytanie 5
    ALTER TABLE Potrawy
    MODIFY cena DECIMAL(6,2) NOT NULL;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Etap 2: Strona HTML

    Kroki 9-24 · po tym etapie masz 16 z 35 kryteriów (pkt)

    Krok 9: Plik index.html w HTML5

    ok. 1 min
    Polecenie z arkusza

    Zapisana w języku HTML5.

    Pierwsza linia <!DOCTYPE html> - przeglądarka renderuje stronę według standardu, a nie w trybie zgodności ze starymi stronami. Plik index.html zapisz w folderze z numerem zdającego, obok zdjęć i logo.

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

    Kryteria:

    R.2.1 W pliku index.html znajduje się deklaracja HTML5 <!DOCTYPE HTML>, deklaracja języka zawartości: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny.

    lang="pl" w <html> - czytnik ekranu czyta tekst z polską wymową, a przeglądarka dzieli wyrazy według polskich reguł. Razem z deklaracją HTML5 to R.2.1.

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

    ok. 1 min
    Polecenie z arkusza

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

    <meta charset="UTF-8"> jako pierwszy element <head> - przeglądarka musi znać kodowanie, zanim przeczyta pierwszy polski znak (np. w tytule).

    index.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 (index.html)
  12. Krok 12: Tytuł strony

    Kryteria:

    R.2.2 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków i tytuł strony "Restauracja Marchewka"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Restauracja Marchewka”.

    <title> z treścią z arkusza; kodowanie i tytuł razem to R.2.2. Dodatkowo <meta name="viewport"> - bez niej telefon udaje ekran szeroki na ok. 980 px i pomniejsza stronę. Arkusz tego nie wymaga, ale to stały element każdego współczesnego szablonu.

    index.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>Restauracja Marchewka</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

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

    <link rel="stylesheet" href="styl.css"> - bez ukośnika na końcu (w HTML5 <link> jest elementem pustym i nie potrzebuje />). Całe formatowanie ma pochodzić z tego pliku, bez atrybutów style w HTML-u (R.3.2).

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Bloki: nagłówek i blok główny po dwie sekcje, stopka

    Kryteria:

    R.2.3 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML 5: header -> section + section, main -> section + section, footer (dopuszcza się stosowanie bloków pomocniczych)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: blok nagłówkowy zawierający dwie sekcje, blok główny zawierający dwie sekcje, blok stopki. Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3.

    Struktura z klucza R.2.3: header z dwiema section, main z dwiema section, footer. Znaczniki semantyczne mówią, czym jest blok (nagłówek strony, treść główna, stopka), a nie tylko jak wygląda - korzystają z tego czytniki ekranu (skok do treści głównej) i wyszukiwarki.

    Identyfikatory po angielsku: header-left, header-right, order (zamówienie) i dishes (potrawy). Każda sekcja ma inny styl, a skrypt sięgnie do dwóch ostatnich.

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

    ok. 1 min
    Polecenie z arkusza

    Zawartość lewej sekcji nagłówkowej: Nagłówek pierwszego stopnia o treści „Restauracja Marchewka”.

    <h1> - jedyny nagłówek pierwszego stopnia na stronie, nazwa całej witryny.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
            </section>
            <section id="header-right">
            </section>
        </header>
        <main>
            <section id="order">
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Nagłówek trzeciego stopnia

    ok. 1 min
    Polecenie z arkusza

    Nagłówek trzeciego stopnia o treści „Twoje wegetariańskie miejsce na mapie miasta”.

    <h3> pod <h1> - stopień z arkusza, nawet jeśli pomija <h2>; rozmiar i pochylenie ustawi styl, nie wybór znacznika.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
            </section>
        </header>
        <main>
            <section id="order">
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Logo w prawej sekcji nagłówka

    Kryteria:

    R.2.5 W prawej sekcji nagłówkowej znajduje się obraz logo.png z tekstem alternatywnym "logo"

    ok. 1 min
    Polecenie z arkusza

    Zawartość prawej sekcji nagłówkowej: obraz logo.png z tekstem alternatywnym „logo”.

    Obraz z tekstem alternatywnym z arkusza (R.2.5). Logo ma 118 × 200 px - dokładnie wysokość sekcji, którą ustawi styl.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Sekcja zamówienia: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość lewej sekcji głównej: Nagłówek stopnia czwartego o treści „Twoje zamówienie”.

    <h4> w sekcji order.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Pusta lista zamówienia

    Kryteria:

    R.2.6 W lewej sekcji głównej znajduje się lista punktowana. W stanie początkowym lista nie zawiera elementów (znacznik <ul> - sprawdzić w kodzie)

    ok. 1 min
    Polecenie z arkusza

    Lista punktowana (nieuporządkowana) - lista w stanie początkowym jest pusta.

    <ul id="order-list"></ul> bez żadnego <li> (R.2.6) - pozycje dołoży skrypt. Atrybut aria-live="polite" to obietnica dla czytnika ekranu: gdy zawartość listy się zmieni, czytnik przeczyta nową pozycję (osoba niewidoma dowie się, że potrawa trafiła do zamówienia). Na wygląd nie wpływa.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Przycisk „Wyczyść”

    ok. 1 min
    Polecenie z arkusza

    Przycisk o treści „Wyczyść”, którego kliknięcie powoduje wykonanie skryptu 2.

    <button type="button"> - przycisk, który niczego nie wysyła. Domyślny typ to submit: tu nie ma formularza, więc nic by się nie stało, ale gdy ktoś kiedyś otoczy listę <form>, przycisk bez typu zacząłby przeładowywać stronę. Identyfikator clear-order posłuży skryptowi do podpięcia zdarzenia - HTML nie zawiera wywołania funkcji.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Przycisk „Zatwierdź”

    Kryteria:

    R.2.7 W lewej sekcji głównej znajdują się dwa przyciski o treściach "Wyczyść" i "Zatwierdź"

    ok. 1 min
    Polecenie z arkusza

    Przycisk o treści „Zatwierdź”, którego kliknięcie powoduje wykonanie skryptu 3.

    Drugi przycisk, też type="button" i z identyfikatorem. Oba przyciski to kryterium R.2.7; zdarzenia dopisze skrypt.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
                <button type="button" id="confirm-order">Zatwierdź</button>
            </section>
            <section id="dishes">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Pierwszy blok potrawy: naleśniki

    ok. 2 min
    Polecenie z arkusza

    Zawartość prawej sekcji głównej: 6 bloków z potrawami zawierających obraz oraz paragraf. Obraz nalesniki.webp z tekstem alternatywnym „Naleśniki” i paragraf o treści „Naleśniki”.

    Blok potrawy: <div class="dish"> z obrazem i akapitem. Klasa, bo bloków jest sześć i mają wspólny styl. Atrybut tabindex="0" dodaje blok do kolejności klawisza Tab - <div> sam z siebie nie przyjmuje fokusu, a ktoś, kto nie używa myszy, też powinien móc zamówić naleśniki. Obsługę Entera dopisze skrypt.

    Zdjęcia są w formacie WebP - przeglądarki wyświetlają go jak JPEG czy PNG, a pliki są mniejsze.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
                <button type="button" id="confirm-order">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" tabindex="0">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Pozostałe pięć bloków potraw

    Kryteria:

    R.2.8 Prawa sekcja główna składa się z 6 bloków z potrawami. Każdy z bloków zawiera zdjęcie wraz z tekstem alternatywnym oraz akapit z podpisem potrawy

    ok. 3 min
    Polecenie z arkusza

    Obraz lasagne.webp z tekstem alternatywnym „Lasagne szpinakowa” i paragraf o treści „Lasagne szpinakowa”. Obraz marchewka.webp z tekstem alternatywnym „Pieczona marchewka” i paragraf o treści „Pieczona marchewka”. Obraz rosol.webp z tekstem alternatywnym „Wege rosół” i paragraf o treści „Wege rosół”. Obraz tarta.webp z tekstem alternatywnym „Tarta szparagowa” i paragraf o treści „Tarta szparagowa”. Obraz kompot.webp z tekstem alternatywnym „Kompot” i paragraf o treści „Kompot”.

    Pięć kopii pierwszego bloku w kolejności z arkusza. Nazwy plików bez polskich znaków (rosol.webp), teksty na stronie z nimi („Wege rosół”). Nazwa potrawy stoi w bloku tylko w akapicie (i w tekście alternatywnym) - skrypt przeczyta ją stamtąd, więc nie trzeba jej powtarzać w wywołaniu funkcji (R.2.8).

    index.html HTML zmienione: 20 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
                <button type="button" id="confirm-order">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" tabindex="0">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Stopka

    Kryteria:

    R.2.4 W lewej sekcji nagłówkowej znajduje się <h1> :"Restauracja Marchewka" oraz <h3> : "Twoje wegetariańskie miejsce na mapie miasta", w lewej sekcji głównej <h4> : "Twoje zamówienie", w stopce <p> zawierający numer zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: paragraf o treści „Wykonał:”, dalej wstawiony numer zdającego.

    Akapit w <footer>. Na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania. Ten akapit domyka R.2.4: <h1> i <h3> w nagłówku, <h4> w sekcji zamówienia i <p> w stopce.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
                <button type="button" id="confirm-order">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" tabindex="0">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Etap 3: Styl CSS

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

    Krok 25: Zmienne z kolorami, krój i zaokrąglenie

    Kryteria:

    R.4.1 domyślne formatowanie selektorów (*): krój czcionki Verdana oraz zaokrąglenie obramowania - 5px

    ok. 2 min
    Polecenie z arkusza

    Domyślnie, dla wszystkich selektorów: krój czcionki „Verdana”, zaokrąglenie obramowania 5 px.

    Plik styl.css zaczyna się od zmiennych CSS w :root (to element <html>, więc zmienne są widoczne w całym dokumencie). Zieleń #778A35 arkusz każe ustawić pięć razy - wpisana raz, w regułach jest var(--green). Zmiana odcienia to jedna linia, a nie pięć miejsc, z których jedno łatwo pominąć. Inspektor przeglądarki pokazuje obliczony kolor, więc egzaminator sprawdza go tak samo.

    Selektor * (R.4.1): krój Verdana z rodziną zastępczą sans-serif (gdy Verdany nie ma, przeglądarka weźmie inny krój bezszeryfowy, a nie domyślny szeryfowy) i zaokrąglenie 5 px - widoczne tylko tam, gdzie jest tło: sekcje, bloki potraw, przyciski.

    styl.css CSS nowy plik
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Tło strony

    Kryteria:

    R.4.2 kolor tła: selektor body - #D1E2C4

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: kolor tła #D1E2C4.

    Selektor znacznika body - uwaga pod listą stylów każe użyć właśnie jego (R.4.2).

    styl.css CSS zmienione: 4 linie
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Lewa sekcja nagłówka

    ok. 1 min
    Polecenie z arkusza

    Dla lewej sekcji nagłówkowej: szerokość 80%, kolor tła #778A35, wysokość 200 px.

    Właściwości w stałej kolejności: wymiary, potem kolory - łatwiej porównać reguły między sobą. Sekcje stoją jeszcze jedna pod drugą; obok siebie ustawi je krok z układem.

    styl.css CSS zmienione: 6 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Prawa sekcja nagłówka

    ok. 1 min
    Polecenie z arkusza

    Dla prawej sekcji nagłówkowej: szerokość 20%, kolor tła #778A35, wysokość 200 px.

    Te same wysokość i tło, szerokość 20%: razem z lewą 80% + 20% = cały wiersz.

    styl.css CSS zmienione: 6 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Dla nagłówka pierwszego stopnia: rozmiar czcionki 50 px, margines wewnętrzny lewy 200 px.

    padding-left - tylko lewy margines wewnętrzny; klucz (R.4.8) sprawdza, że jedynie lewy, więc skrót padding: 0 0 0 200px też by przeszedł, ale wyzerowałby pozostałe.

    styl.css CSS zmienione: 5 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Nagłówek trzeciego stopnia

    Kryteria:

    R.4.4 rozmiar czcionki nagłówków: pierwszego stopnia - 50px, trzeciego stopnia - 30px, nagłówek trzeciego stopnia - pochylenie czcionki

    ok. 1 min
    Polecenie z arkusza

    Dla nagłówka trzeciego stopnia: rozmiar czcionki 30 px, czcionka pochylona, margines wewnętrzny lewy 200 px.

    Pochylenie to font-style: italic. Rozmiary obu nagłówków i pochylenie to R.4.4.

    styl.css CSS zmienione: 6 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Sekcja zamówienia

    ok. 1 min
    Polecenie z arkusza

    Dla lewej sekcji głównej: kolor tła #EBEBE8, szerokość 25%.

    Jasnoszare tło ze zmiennej --order.

    styl.css CSS zmienione: 5 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Sekcja potraw

    Kryteria:

    R.4.6 szerokość: sekcje nagłówkowe: lewa - 80%, prawa - 20%, sekcje główne: lewa - 25%, prawa - 75%

    ok. 1 min
    Polecenie z arkusza

    Dla prawej sekcji głównej: szerokość 75%.

    Wszystkie cztery szerokości sekcji (80/20 i 25/75) to R.4.6.

    styl.css CSS zmienione: 4 linie
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Układ bloków zgodny z ilustracją 3

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowane właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position; żaden blok nie zachodzi na inne bloki - sprawdzić w inspektorze)

    ok. 3 min
    Polecenie z arkusza

    Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3.

    Sekcje nagłówka i bloku głównego stają obok siebie dzięki display: flex na rodzicu; align-items: flex-start w bloku głównym zostawia sekcję zamówienia niską, przy górze, jak na ilustracji 2 (R.3.1).

    Dlaczego tu nie siatka? Arkusz i klucz (R.4.6) ustawiają szerokości na samych sekcjach (width: 80%). W siatce procent szerokości elementu liczy się od jego kolumny, a nie od rodzica: sprawdzone w Chrome - sekcja z width: 80% w kolumnie auto nagłówka szerokiego na 1000 px miała 400 px. Flex liczy procenty od rodzica, więc szerokości z arkusza działają bez zmian. Siatka przyda się za chwilę tam, gdzie arkusz nie podaje szerokości - przy blokach potraw.

    styl.css CSS zmienione: 9 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Bloki potraw obok siebie: siatka

    Kryteria:

    R.4.9 wyświetlanie bloków z potrawami obok siebie (ilustracja 2)

    ok. 3 min
    Polecenie z arkusza

    Dla bloków z potrawami: kolor tła #778A35, tekst wyrównany do środka, marginesy zewnętrzne 20 px, wyświetlanie elementów blokowych obok siebie zgodnie z ilustracją 2.

    Reguła .dish: margines 20 px, tło ze zmiennej, tekst do środka. „Obok siebie” ustawia rodzic - sekcja potraw staje się siatką:

    • display: grid - dzieci sekcji (bloki potraw) trafiają do komórek siatki,
    • grid-template-columns: repeat(auto-fill, 220px) - tyle kolumn po 220 px, ile się zmieści; gdy okno się zwęża, kolumn ubywa, a bloki przechodzą do kolejnego wiersza. Arkusz o tym uprzedza („układ bloków z potrawami może się różnić”),
    • 220 px to szerokość bloku z marginesami: zdjęcie 150 px + 2 × 15 px jego marginesu + 2 × 20 px marginesu bloku.

    W wersji podstawowej każdy blok miał display: inline-block i zachowywał się jak wyraz w zdaniu - z odstępem po spacji między znacznikami i wyrównaniem do linii tekstu. Siatka nie ma tych efektów: wszystkie bloki w wierszu mają tę samą wysokość, a odstępy wynikają tylko z marginesów (R.4.9).

    Typowe błędy

    repeat(auto-fill, 1fr) jest błędem składni - przy auto-fill kolumna musi mieć stałą szerokość albo minmax() ze stałym minimum (np. minmax(220px, 1fr) rozciągnęłoby bloki na całą szerokość sekcji).

    styl.css CSS zmienione: 8 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
        display: grid;
        grid-template-columns: repeat(auto-fill, 220px);
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    
    .dish {
        margin: 20px;
        background-color: var(--green);
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Zdjęcie w bloku potrawy

    Kryteria:

    R.4.5 wysokość: obie sekcje nagłówkowe - 200px, selektor img, znajdujący się w bloku z potrawą - 150px

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu znajdującego się w bloku z potrawą: marginesy zewnętrzne 15 px, wysokość 150 px.

    Selektor potomka .dish img kończy się selektorem znacznika img (tego wymaga uwaga arkusza) i dotyczy tylko zdjęć w blokach potraw - logo zostaje w spokoju. Szerokość przeliczy się z proporcji: zdjęcia są kwadratowe, więc mają 150 × 150 px. Wysokości sekcji nagłówka (200 px) i zdjęcia (150 px) to R.4.5.

    Typowe błędy

    Sam selektor img zmniejszyłby także logo do 150 px.

    styl.css CSS zmienione: 5 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
        display: grid;
        grid-template-columns: repeat(auto-fill, 220px);
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    
    .dish {
        margin: 20px;
        background-color: var(--green);
        text-align: center;
    }
    
    .dish img {
        margin: 15px;
        height: 150px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Obrys bloku pod kursorem i przy fokusie

    Kryteria:

    R.4.10 gdy kursor znajdzie się na bloku z potrawą ustawiany jest obrys outline: 2px white, dowolna pojedyncza linia ciągła

    ok. 2 min
    Polecenie z arkusza

    Gdy kursor znajdzie się na bloku z potrawą pojawia się obrys (outline) linią ciągłą, o szerokości 2 px i kolorze białym.

    outline: 2px solid white po najechaniu (R.4.10). Obrys rysuje się poza blokiem i nie zajmuje miejsca, więc nic się nie przesuwa.

    Ta sama reguła obsługuje :focus-visible - blok wybrany klawiszem Tab dostaje identyczny obrys, czyli użytkownik klawiatury widzi, gdzie jest. cursor: pointer (rączka) podpowiada, że blok da się kliknąć.

    styl.css CSS zmienione: 6 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
        display: grid;
        grid-template-columns: repeat(auto-fill, 220px);
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    
    .dish {
        margin: 20px;
        background-color: var(--green);
        text-align: center;
    }
    
    .dish img {
        margin: 15px;
        height: 150px;
    }
    
    .dish:hover,
    .dish:focus-visible {
        outline: 2px solid white;
        cursor: pointer;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Stopka

    Kryteria:

    R.4.7 wyrównanie tekstu do środka: dla bloków z potrawami dla stopki: wyrównanie tekstu do prawej strony

    ok. 1 min
    Polecenie z arkusza

    Dla stopki: kolor tła #778A35, margines zewnętrzny górny 10 px, marginesy wewnętrzne 10 px, wyrównanie tekstu do prawej strony.

    margin-top - tylko górny margines zewnętrzny, padding - wszystkie wewnętrzne. Wyrównania tekstu (środek w blokach potraw, prawa w stopce) to R.4.7.

    styl.css CSS zmienione: 7 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
        display: grid;
        grid-template-columns: repeat(auto-fill, 220px);
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    
    .dish {
        margin: 20px;
        background-color: var(--green);
        text-align: center;
    }
    
    .dish img {
        margin: 15px;
        height: 150px;
    }
    
    .dish:hover,
    .dish:focus-visible {
        outline: 2px solid white;
        cursor: pointer;
    }
    
    footer {
        margin-top: 10px;
        padding: 10px;
        background-color: var(--green);
        text-align: right;
    }
    Podgląd strony po tym kroku (index.html)
  38. Krok 38: Przyciski

    Kryteria: ,

    R.4.3 kolor tła: obie sekcje nagłówkowe, blok z potrawami, stopka i przyciski - #778A35 lewa sekcja główna - #EBEBE8

    R.4.8 marginesy wewnętrzne (padding): stopka - 10px, przyciski - 5px, nagłówki pierwszego i trzeciego stopnia - jedynie lewy 200px marginesy zewnętrzne (margin): bloki z potrawami - 20px, obraz znajdujący się w bloku z potrawami - 15px, stopka - jedynie górny 10px

    ok. 1 min
    Polecenie z arkusza

    Dla przycisków: kolor tła #778A35, marginesy wewnętrzne 5px.

    Selektor znacznika button. Tu domykają się dwa kryteria zbierane przez kilka reguł: kolory tła - wszystkie z var(--green) oraz var(--order) w sekcji zamówienia (R.4.3), i marginesy - stopka, przyciski, nagłówki, bloki potraw i ich zdjęcia (R.4.8).

    styl.css CSS zmienione: 5 linii
    :root {
        --green: #778A35;
        --page: #D1E2C4;
        --order: #EBEBE8;
    }
    
    * {
        font-family: Verdana, sans-serif;
        border-radius: 5px;
    }
    
    body {
        background-color: var(--page);
    }
    
    #header-left {
        width: 80%;
        height: 200px;
        background-color: var(--green);
    }
    
    #header-right {
        width: 20%;
        height: 200px;
        background-color: var(--green);
    }
    
    h1 {
        padding-left: 200px;
        font-size: 50px;
    }
    
    h3 {
        padding-left: 200px;
        font-size: 30px;
        font-style: italic;
    }
    
    #order {
        width: 25%;
        background-color: var(--order);
    }
    
    #dishes {
        width: 75%;
        display: grid;
        grid-template-columns: repeat(auto-fill, 220px);
    }
    
    header,
    main {
        display: flex;
    }
    
    main {
        align-items: flex-start;
    }
    
    .dish {
        margin: 20px;
        background-color: var(--green);
        text-align: center;
    }
    
    .dish img {
        margin: 15px;
        height: 150px;
    }
    
    .dish:hover,
    .dish:focus-visible {
        outline: 2px solid white;
        cursor: pointer;
    }
    
    footer {
        margin-top: 10px;
        padding: 10px;
        background-color: var(--green);
        text-align: right;
    }
    
    button {
        padding: 5px;
        background-color: var(--green);
    }
    Podgląd strony po tym kroku (index.html)
  39. Etap 4: JavaScript

    Kroki 39-45 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 39: Plik skrypt.js: jeden nasłuchiwacz dla sześciu potraw

    Kryteria:

    R.5.2 Zastosowana przynajmniej jedna zmienna lub funkcja oraz nazewnictwo jest w języku polskim lub angielskim i odzwierciedla cel zastosowania

    ok. 4 min
    Polecenie z arkusza

    Skrypt 1: Wywoływany jest po kliknięciu na blok z potrawą. Kliknięcie każdego z bloków powoduje wykonanie skryptu 1.

    Skrypt w osobnym pliku skrypt.js, podpięty w <head> z atrybutem defer: przeglądarka pobiera go równolegle ze stroną, a wykonuje dopiero po wczytaniu całego HTML-u - lista i bloki już istnieją, choć znacznik stoi przed nimi.

    • const orderList, const dishes - dwa elementy, do których skrypt będzie sięgał; const, bo zmienna zawsze wskazuje ten sam element,
    • delegacja zdarzeń: zamiast sześciu nasłuchiwaczy jeden, na całej sekcji potraw. Kliknięcie w zdjęcie „wędruje” w górę drzewa dokumentu aż do sekcji, a event.target mówi, w co dokładnie kliknięto,
    • event.target.closest('.dish') - najbliższy przodek z klasą dish (albo sam element); kliknięcie w odstęp między blokami daje null i if je pomija,
    • nazwę potrawy funkcja addDish dostaje z akapitu bloku (textContent) - zapisana raz w HTML-u.

    Funkcja addDish(name) jest jeszcze pusta (nazwa po angielsku i mówi, co robi - R.5.2).

    Typowe błędy

    Bez defer (i ze znacznikiem w <head>) skrypt wykona się przed powstaniem sekcji - querySelector('#dishes') zwróci null, a addEventListener rzuci błąd i nic nie zadziała.

    index.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>Restauracja Marchewka</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <section id="header-left">
                <h1>Restauracja Marchewka</h1>
                <h3>Twoje wegetariańskie miejsce na mapie miasta</h3>
            </section>
            <section id="header-right">
                <img src="logo.png" alt="logo">
            </section>
        </header>
        <main>
            <section id="order">
                <h4>Twoje zamówienie</h4>
                <ul id="order-list" aria-live="polite"></ul>
                <button type="button" id="clear-order">Wyczyść</button>
                <button type="button" id="confirm-order">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" tabindex="0">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" tabindex="0">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript nowy plik
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    Podgląd strony po tym kroku (index.html)
  40. Krok 40: Skrypt 1: nowa pozycja na liście zamówienia

    Kryteria: ,

    R.5.1 Skrypt w języku JavaScript zawiera przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    R.5.3 Po kliknięciu na blok z potrawą zostaje dodany nowy element <li> do listy w lewej sekcji głównej. Element ten zawiera nazwę klikniętej potrawy (działa dla więcej niż jednego bloku)

    ok. 3 min
    Polecenie z arkusza

    Dodaje nowy element do listy w lewej sekcji głównej. Element ten zawiera nazwę klikniętej potrawy (ilustracja 4).

    • document.createElement('li') - nowy element listy, na razie poza stroną,
    • item.textContent = name - wstawia tekst. innerHTML potraktowałby nazwę jak kod HTML: gdyby w nazwie potrawy znalazł się znak <, przeglądarka próbowałaby z niego zrobić znacznik,
    • orderList.append(item) - dokłada pozycję na koniec listy.

    Kliknij kilka potraw w podglądzie - każde kliknięcie dopisuje pozycję jak na ilustracji 4 (R.5.1, R.5.3).

    Typowe błędy

    orderList.textContent = name zastępuje całą zawartość listy zwykłym tekstem - zamiast nowej pozycji <li> zostaje jeden napis.

    skrypt.js JavaScript zmienione: 3 linie
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
        const item = document.createElement('li');
        item.textContent = name;
        orderList.append(item);
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    Podgląd strony po tym kroku (index.html)
  41. Krok 41: Skrypt 1 z klawiatury

    ok. 2 min
    Polecenie z arkusza

    Kliknięcie każdego z bloków powoduje wykonanie skryptu 1.

    Blok z tabindex="0" przyjmuje fokus, ale <div> nie zamienia Entera na kliknięcie (robi to tylko <button> i odnośnik). Drugi nasłuchiwacz, też na sekcji: zdarzenie keydown, a event.key mówi, który klawisz naciśnięto - Enter albo spacja dodają potrawę. preventDefault() przy spacji powstrzymuje przewinięcie strony.

    Klucz tego nie ocenia, ale arkusz mówi o „kliknięciu” bloku, a dla użytkownika klawiatury Enter jest kliknięciem. Spróbuj w podglądzie: Tab do potrawy, Enter.

    skrypt.js JavaScript zmienione: 8 linii
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
        const item = document.createElement('li');
        item.textContent = name;
        orderList.append(item);
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    dishes.addEventListener('keydown', (event) => {
        const dish = event.target.closest('.dish');
        if (dish && (event.key === 'Enter' || event.key === ' ')) {
            event.preventDefault();
            addDish(dish.querySelector('p').textContent);
        }
    });
    Podgląd strony po tym kroku (index.html)
  42. Krok 42: Skrypt 2: czyszczenie listy przyciskiem „Wyczyść”

    Kryteria: ,

    R.3.3 Zdefiniowano dla minimum jednego przycisku zdarzenie związane z jego wciśnięciem, które uruchamia funkcję skryptu

    R.5.4 Po kliknięciu na przycisk Wyczyść zawartość listy jest czyszczona

    ok. 2 min
    Polecenie z arkusza

    Skrypt 2: Wywoływany jest po kliknięciu na przycisk Wyczyść. Czyści zawartość listy lewej sekcji głównej.

    • orderList.replaceChildren() bez argumentów usuwa wszystkie dzieci elementu - nazwa mówi wprost, co się dzieje, zamiast podstawiania pustego HTML-u (innerHTML = ''),
    • addEventListener('click', clearOrder) - funkcję przekazujesz bez nawiasów: przeglądarka wywoła ją sama przy kliknięciu.

    To zdarzenie wciśnięcia przycisku, które uruchamia funkcję (R.3.3, R.5.4). Dodaj w podglądzie kilka potraw i wyczyść listę.

    Typowe błędy

    addEventListener('click', clearOrder()) z nawiasami wywołuje funkcję od razu przy wczytaniu, a jako obsługę zdarzenia przekazuje jej wynik (undefined) - przycisk przestaje działać.

    skrypt.js JavaScript zmienione: 6 linii
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
        const item = document.createElement('li');
        item.textContent = name;
        orderList.append(item);
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    dishes.addEventListener('keydown', (event) => {
        const dish = event.target.closest('.dish');
        if (dish && (event.key === 'Enter' || event.key === ' ')) {
            event.preventDefault();
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    function clearOrder() {
        orderList.replaceChildren();
    }
    
    document.querySelector('#clear-order').addEventListener('click', clearOrder);
    Podgląd strony po tym kroku (index.html)
  43. Krok 43: Skrypt 3: komunikat po zatwierdzeniu

    Kryteria:

    R.5.5 Po kliknięciu na przycisk Zatwierdź pojawia się alert o treści "Zamówienie zostało przekazane do realizacji"

    ok. 2 min
    Polecenie z arkusza

    Skrypt 3: Wywoływany jest po kliknięciu na przycisk Zatwierdź. Na stronie pojawia się alert z informacją „Zamówienie zostało przekazane do realizacji” (ilustracja 5).

    alert(komunikat) - okienko z tekstem z arkusza i przyciskiem OK (R.5.5). Przycisk dostaje nasłuchiwacz tak samo jak „Wyczyść”.

    Ramka podglądu blokuje okienka alert, więc tu komunikat się nie pokaże - po otwarciu pliku w przeglądarce pojawi się po kliknięciu.

    skrypt.js JavaScript zmienione: 6 linii
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
        const item = document.createElement('li');
        item.textContent = name;
        orderList.append(item);
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    dishes.addEventListener('keydown', (event) => {
        const dish = event.target.closest('.dish');
        if (dish && (event.key === 'Enter' || event.key === ' ')) {
            event.preventDefault();
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    function clearOrder() {
        orderList.replaceChildren();
    }
    
    document.querySelector('#clear-order').addEventListener('click', clearOrder);
    
    function confirmOrder() {
        alert('Zamówienie zostało przekazane do realizacji');
    }
    
    document.querySelector('#confirm-order').addEventListener('click', confirmOrder);
    Podgląd strony po tym kroku (index.html)
  44. Krok 44: Skrypt 3: czyszczenie listy po zatwierdzeniu

    Kryteria:

    R.5.6 Po kliknięciu na przycisk Zatwierdź zawartość listy jest czyszczona

    ok. 1 min
    Polecenie z arkusza

    Zawartość listy z lewej sekcji głównej jest czyszczona.

    Czyszczenie to już gotowa funkcja clearOrder() - skrypt 3 jej używa, zamiast powtarzać tę samą linię. Kolejność ma znaczenie: alert wstrzymuje skrypt do kliknięcia OK, więc przy komunikacie zamówienie jest jeszcze widoczne, a znika dopiero po zamknięciu okienka (R.5.6).

    skrypt.js JavaScript zmienione: 1 linia
    const orderList = document.querySelector('#order-list');
    const dishes = document.querySelector('#dishes');
    
    function addDish(name) {
        const item = document.createElement('li');
        item.textContent = name;
        orderList.append(item);
    }
    
    dishes.addEventListener('click', (event) => {
        const dish = event.target.closest('.dish');
        if (dish) {
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    dishes.addEventListener('keydown', (event) => {
        const dish = event.target.closest('.dish');
        if (dish && (event.key === 'Enter' || event.key === ' ')) {
            event.preventDefault();
            addDish(dish.querySelector('p').textContent);
        }
    });
    
    function clearOrder() {
        orderList.replaceChildren();
    }
    
    document.querySelector('#clear-order').addEventListener('click', clearOrder);
    
    function confirmOrder() {
        alert('Zamówienie zostało przekazane do realizacji');
        clearOrder();
    }
    
    document.querySelector('#confirm-order').addEventListener('click', confirmOrder);
    Podgląd strony po tym kroku (index.html)
  45. Krok 45: Sprawdzenie: ponowne zamawianie po wyczyszczeniu

    Kryteria:

    R.5.7 Po wyczyszczeniu zawartości listy możliwe jest ponowne dodanie przynajmniej jednego elementu (do pustej listy)

    ok. 1 min
    Polecenie z arkusza

    Dodaje nowy element do listy w lewej sekcji głównej.

    Klucz osobno sprawdza, że po wyczyszczeniu listy można znowu dodawać potrawy (R.5.7). Działa bez dodatkowego kodu: replaceChildren() usuwa pozycje, a sam <ul> zostaje, więc orderList z początku pliku nadal wskazuje istniejący element. W podglądzie: dodaj potrawy, wyczyść, dodaj znowu.

    Typowe błędy

    orderList.remove() usuwa całą listę ze strony - zmienna nadal wskazuje element, ale już odłączony, więc kolejne potrawy „dodają się” poza stroną i nic nie widać.

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

  46. Etap 5: Porównanie z wersją podstawową

    Krok 46 · po tym etapie masz 35 z 35 kryteriów (pkt)

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

    ok. 2 min

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

    wersja podstawowawersja nowoczesna
    kolorywpisane w każdej regulezmienne --green, --page, --order
    bloki potraw obok siebiedisplay: inline-block na blokudisplay: grid + repeat(auto-fill, 220px) na sekcji
    sekcje nagłówka i bloku głównegodisplay: flexdisplay: flex (szerokości procentowe sekcji)
    skrypt<script> na końcu <body>, 6 × onclick z nazwą potrawyskrypt.js z defer, jeden nasłuchiwacz, nazwa z akapitu
    treść pozycjiinnerHTMLtextContent
    czyszczenieinnerHTML = "" w dwóch funkcjachreplaceChildren() w jednej funkcji, wołanej dwa razy
    klawiaturabraktabindex, :focus-visible, Enter i spacja
    zapytanie 3DATE(dataZlozenia) = ...przedział >= '2024-06-09' AND < '2024-06-10'

    Na egzaminie wersja podstawowa trzyma się dosłownie tabeli 2 arkusza (onclick, getElementById, innerHTML) i jest szybsza do napisania. Nowoczesna wymaga pamiętania o defer i closest, ale nazwa potrawy nie może się już rozjechać między menu a zamówieniem. Wersja podstawowa w etapie „Dobre praktyki” pokazuje też blokadę pustego zamówienia - tu jej nie ma celowo: egzaminator może kliknąć „Zatwierdź” przy pustej liście i spodziewa się komunikatu z arkusza (R.5.5).

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

  47. Etap 6: Oddanie pracy

    Krok 47 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 47: 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 folderze z numerem zdającego: index.html, skrypt.js, styl.css, kwerendy.txt, import.png, kw1.png … kw5.png, zdjęcia potraw, logo.png i przeglądarka.txt. Bez skrypt.js potrawy nie trafiają do zamówienia. Płytę sprawdź po nagraniu.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.