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

Rozwiązanie krok po kroku: Aplikacja internetowa restauracji (Wersja podstawowa)

Rozwiązanie buduje stronę wegetariańskiej restauracji z koszykiem zamówienia: baza restauracja (kelnerzy, stoliki, zamówienia, potrawy i tabela łącząca zamówienia z potrawami) i pięć operacji - sortowanie malejące, zliczanie ze złączeniem, dwa złączenia z warunkiem na dzień (DATE() na polu z godziną), utworzenie użytkownika CREATE USER i zmiana typu kolumny na DECIMAL(6,2) z zachowaniem NOT NULL, potem strona index.html z nagłówkiem i blokiem głównym po dwie sekcje i sześcioma klikanymi blokami potraw, style w styl.css i trzy skrypty JavaScript: dodanie potrawy do listy zamówienia, wyczyszczenie listy i zatwierdzenie z komunikatem.

Kroki idą zdanie po zdaniu za treścią arkusza - każdy ma polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypty są najpierw pisane najprościej, tak jak podpowiada tabela 2 arkusza (atrybut onclick, createElement, appendChild, innerHTML), a na końcu zostają przerobione na wersję z prawdziwych projektów: nasłuchiwacze zdarzeń, nazwa potrawy brana z bloku zamiast przepisywana drugi raz i zatwierdzanie, które nie przepuści pustego zamówienia. W tym arkuszu nie ma PHP.

Baza, zdjęcia potraw i logo pochodzą z prawdziwego archiwum pliki19 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy uruchomionej w MariaDB z XAMPP-a - na egzaminie robisz je sam, z całego ekranu. Strona w podglądzie działa: od etapu skryptów można klikać potrawy i przyciski.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, zdarzenia)” jest drugi sposób rozwiązania tego samego arkusza: zmienne CSS i siatka dla bloków potraw, skrypt w osobnym pliku z jednym nasłuchiwaczem dla wszystkich potraw - obie wersje są zgodne z kluczem.

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

  1. Etap 1: Baza danych

    Kroki 1-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).

    Rozpakuj pliki19.7z z pulpitu (hasło ReStAuRac1a - z cyfrą 1 przed ostatnią literą) do folderu z numerem zdającego: plik restauracja.sql, sześć zdjęć potraw w formacie WebP i logo.png. W phpMyAdmin: Nowa, nazwa restauracja, porównywanie 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. Powstaje pięć tabel z ilustracji 1: Kelnerzy, Stoliki (sala i numer stolika), Zamowienia (kelner, stolik, data i godzina złożenia), Potrawy i ZamowieniaPotrawy - tabela łącząca, bo jedno zamówienie ma wiele potraw, a jedna potrawa trafia do wielu zamówień. MariaDB na Windows zapisuje nazwy tabel małymi literami, ale zapytania z wielkimi literami działają tak samo.

  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.

    Print Screen, wklejasz do edytora grafiki i zapisujesz 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.

    • SELECT imie, nazwisko FROM Kelnerzy - dwie kolumny,
    • ORDER BY nazwisko DESC - sortowanie według nazwiska, DESC to malejąco (od Z do A).

    Wynik: 3 wiersze - Piotr Wiśniewski, Anna Nowak, Jan Kowalski, jak w kluczu. Zapytania zapisujesz 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 JOIN Stoliki ON Stoliki.id = Zamowienia.idStolika - zamówienie zna tylko identyfikator stolika, a numer i salę trzyma tabela Stoliki, dlatego złączenie,
    • WHERE Stoliki.numerStolika = 3 AND Stoliki.sala = 1 - stolik 3 jest w obu salach, więc potrzebne są oba warunki,
    • SELECT COUNT(*) - zamiast wierszy jedna liczba: ile ich jest.

    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 - działa w tej bazie przypadkiem, bo stolik o id 3 to akurat stolik nr 3 w sali 1. Klucz wymaga relacji, a zapytanie ma być uniwersalne.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko FROM Kelnerzy ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) FROM Zamowienia JOIN Stoliki ON Stoliki.id = Zamowienia.idStolika WHERE Stoliki.numerStolika = 3 AND Stoliki.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ą.

    Droga od potrawy do daty prowadzi przez tabelę łączącą:

    • FROM Potrawy JOIN ZamowieniaPotrawy ON ZamowieniaPotrawy.idPotrawy = Potrawy.id - potrawa z jej pozycjami w zamówieniach,
    • JOIN Zamowienia ON ZamowieniaPotrawy.idZamowienia = Zamowienia.id - pozycja z zamówieniem, które ma datę,
    • WHERE DATE(Zamowienia.dataZlozenia) = '2024-06-09' - pole dataZlozenia przechowuje datę i godzinę, a DATE() odcina godzinę.

    Wynik: jeden wiersz - Spaghetti bolognese. Sprawdzone na tej bazie: bez DATE() wynik ma 0 wierszy, bo serwer porównuje z północą 9 czerwca, a zamówienie złożono o 14:30. Zrzut: kw3.png.

    Typowe błędy

    WHERE dataZlozenia = '2024-06-09' bez DATE() daje pusty wynik. Alternatywa bez funkcji: dataZlozenia LIKE '2024-06-09%' albo przedział od północy do północy.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko FROM Kelnerzy ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) FROM Zamowienia JOIN Stoliki ON Stoliki.id = Zamowienia.idStolika WHERE Stoliki.numerStolika = 3 AND Stoliki.sala = 1;
    
    -- Zapytanie 3
    SELECT Potrawy.nazwa FROM Potrawy JOIN ZamowieniaPotrawy ON ZamowieniaPotrawy.idPotrawy = Potrawy.id JOIN Zamowienia ON ZamowieniaPotrawy.idZamowienia = Zamowienia.id WHERE DATE(Zamowienia.dataZlozenia) = '2024-06-09';
    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!

    CREATE USER 'administrator'@'localhost' IDENTIFIED BY 'boss123!':

    • 'administrator'@'localhost' - nazwa i host; „lokalny” to localhost - takie konto zaloguje się tylko z tego samego komputera, na którym działa serwer (klucz R.1.6 wymaga @localhost),
    • IDENTIFIED BY 'boss123!' - hasło w apostrofach, z wykrzyknikiem na końcu.

    Konto nie ma jeszcze żadnych uprawnień - nadaje się je osobno poleceniem GRANT, arkusz tego nie wymaga. Zrzut kw4.png pokazuje konto na liście użytkowników. Sprawdzone na MariaDB z XAMPP-a.

    Typowe błędy

    Przykład w kluczu ma literówkę („administator”) - pisz nazwę z arkusza: administrator. CREATE USER administrator bez hosta tworzy konto 'administrator'@'%' (dowolny host), czyli nie lokalne.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko FROM Kelnerzy ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) FROM Zamowienia JOIN Stoliki ON Stoliki.id = Zamowienia.idStolika WHERE Stoliki.numerStolika = 3 AND Stoliki.sala = 1;
    
    -- Zapytanie 3
    SELECT Potrawy.nazwa FROM Potrawy JOIN ZamowieniaPotrawy ON ZamowieniaPotrawy.idPotrawy = Potrawy.id JOIN Zamowienia ON ZamowieniaPotrawy.idZamowienia = Zamowienia.id WHERE DATE(Zamowienia.dataZlozenia) = '2024-06-09';
    
    -- 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 - wszystkie cyfry, D - cyfry po przecinku. 4 cyfry przed przecinkiem + 2 po = DECIMAL(6,2), największa wartość 9999.99. Dotąd kolumna miała DECIMAL(5,2).

    ALTER TABLE Potrawy MODIFY cena DECIMAL(6,2) NOT NULL - MODIFY podaje całą nową definicję kolumny, więc ograniczenie NOT NULL trzeba przepisać. Sprawdzone na kopii tabeli: MODIFY cena DECIMAL(6,2) bez NOT NULL zmienia kolumnę na dopuszczającą NULL. Zrzut kw5.png pokazuje strukturę po zmianie.

    Typowe błędy

    FLOAT albo DOUBLE to typy zmiennoprzecinkowe - przy pieniądzach dają błędy zaokrągleń, a arkusz wymaga zapisu stałoprzecinkowego. DECIMAL(4,2) to tylko 2 cyfry przed przecinkiem.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko FROM Kelnerzy ORDER BY nazwisko DESC;
    
    -- Zapytanie 2
    SELECT COUNT(*) FROM Zamowienia JOIN Stoliki ON Stoliki.id = Zamowienia.idStolika WHERE Stoliki.numerStolika = 3 AND Stoliki.sala = 1;
    
    -- Zapytanie 3
    SELECT Potrawy.nazwa FROM Potrawy JOIN ZamowieniaPotrawy ON ZamowieniaPotrawy.idPotrawy = Potrawy.id JOIN Zamowienia ON ZamowieniaPotrawy.idZamowienia = Zamowienia.id WHERE DATE(Zamowienia.dataZlozenia) = '2024-06-09';
    
    -- 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.

    Deklaracja <!DOCTYPE html> w pierwszej linii. Plik index.html zapisujesz 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 znaczniku <html> - 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>.

    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> w <head>. Kodowanie i tytuł razem to R.2.2.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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.

    Nazwa: styl.css. Całe formatowanie ma pochodzić z tego pliku (R.3.2).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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. Sekcje dostają identyfikatory po angielsku: header-left, header-right, order (zamówienie) i dishes (potrawy) - każda ma inny styl, a skrypty będą sięgać do zamówienia.

    index.html HTML zmienione: 14 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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> w lewej sekcji nagłówka.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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> - stopnie nagłówków wybierasz według arkusza, nie według wyglądu (rozmiar ustawi styl).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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 (R.2.5). Logo ma 118 x 200 px - tyle samo co wysokość sekcji, którą ustawi styl.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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">
        <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> - lista bez żadnego <li> (R.2.6). Pozycje będzie dokładał skrypt 1, a identyfikator pozwoli mu znaleźć listę. Pusta lista nic nie wyświetla - w podglądzie jej nie widać.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></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> z napisem. Strona nie ma formularza, więc przycisk niczego nie wysyła - jego jedyną rolą będzie uruchomienie skryptu 2; wywołanie dopiszesz w etapie skryptów.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>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 obok pierwszego. Oba przyciski to kryterium R.2.7; skrypt 3 podepniesz później.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>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 to <div class="dish"> z obrazem i akapitem. Wszystkie sześć bloków wygląda tak samo, więc klasa (nie identyfikator) - jeden styl dla wszystkich. Zdjęcia są w formacie WebP: nowoczesny format obrazów, który przeglądarki wyświetlają tak samo jak JPEG czy PNG, a pliki są mniejsze. Zdjęcie ma 1024 px - zmniejszy je styl.

    index.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish">
                    <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”.

    Skopiuj pierwszy blok pięć razy i zmień plik, tekst alternatywny i akapit - w kolejności z arkusza. Nazwy plików są bez polskich znaków (rosol.webp), a teksty na stronie z nimi („Wege rosół”). Sześć bloków z obrazem, tekstem alternatywnym i podpisem to R.2.8.

    index.html HTML zmienione: 20 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish">
                    <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 kryterium R.2.4: <h1> i <h3> w nagłówku, <h4> w sekcji zamówienia i <p> z numerem w stopce.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish">
                    <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: Plik styl.css: krój i zaokrąglenie

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    Selektor *: każdy element dostaje krój Verdana i zaokrąglone rogi 5 px. Zaokrąglenie widać tylko tam, gdzie jest tło albo ramka - sekcje, bloki potraw, przyciski (R.4.1).

    styl.css CSS nowy plik
    * {
        font-family: Verdana;
        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, jak wymaga uwaga pod listą stylów (R.4.2).

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    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.

    Selektor identyfikatora. Sekcje nagłówka stoją jeszcze jedna pod drugą - obok siebie ustawi je krok z układem.

    styl.css CSS zmienione: 5 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    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 tło i wysokość, inna szerokość: 80% + 20% = cały wiersz.

    styl.css CSS zmienione: 5 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    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 - margines wewnętrzny tylko z lewej strony; pozostałe zostają domyślne.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    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: 5 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    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 odróżnia zamówienie od zielonego tła strony.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    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 w nagłówku, 25/75 w bloku głównym) to R.4.6.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #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. 2 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.

    display: flex (tabela 1) na nagłówku i bloku głównym ustawia ich sekcje w jednym rzędzie, a szerokości procentowe dzielą wiersz. W bloku głównym dokładasz align-items: flex-start: bez tego szara sekcja zamówienia rozciągnęłaby się na wysokość wszystkich potraw, a na ilustracji 2 jest niska i stoi przy górze. Stopka zostaje pod spodem (R.3.1).

    styl.css CSS zmienione: 6 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #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

    Kryteria:

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

    ok. 2 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.

    <div> jest blokiem i zajmuje całą szerokość. display: inline-block sprawia, że blok potrawy stoi w linii jak słowo (obok następnego i przechodzi do nowego wiersza, gdy brakuje miejsca), a jednocześnie zachowuje marginesy i tło bloku. Szerokość bloku dopasuje się do zdjęcia (R.4.9). Układ zależy od szerokości okna - arkusz sam o tym uprzedza.

    styl.css CSS zmienione: 6 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #dishes {
        width: 75%;
    }
    header, main {
        display: flex;
    }
    main {
        align-items: flex-start;
    }
    .dish {
        background-color: #778A35;
        text-align: center;
        margin: 20px;
        display: inline-block;
    }
    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 dotyczy tylko zdjęć w blokach potraw - logo w nagłówku zostaje nietknięte. Przy samej wysokości szerokość przelicza się z proporcji: zdjęcia są kwadratowe, więc mają 150 x 150 px. Obie wysokości (sekcje nagłówka 200 px i zdjęcie 150 px) to R.4.5.

    Typowe błędy

    Sam selektor img zmniejszyłby też logo do 150 px - arkusz mówi o obrazie w bloku z potrawą.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #dishes {
        width: 75%;
    }
    header, main {
        display: flex;
    }
    main {
        align-items: flex-start;
    }
    .dish {
        background-color: #778A35;
        text-align: center;
        margin: 20px;
        display: inline-block;
    }
    .dish img {
        margin: 15px;
        height: 150px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Obrys bloku pod kursorem

    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. 1 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 rysuje się poza ramką i nie zajmuje miejsca, więc bloki nie przesuwają się po najechaniu. Najedź na potrawę w podglądzie (R.4.10).

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #dishes {
        width: 75%;
    }
    header, main {
        display: flex;
    }
    main {
        align-items: flex-start;
    }
    .dish {
        background-color: #778A35;
        text-align: center;
        margin: 20px;
        display: inline-block;
    }
    .dish img {
        margin: 15px;
        height: 150px;
    }
    .dish:hover {
        outline: 2px solid white;
    }
    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: 6 linii
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        width: 80%;
        background-color: #778A35;
        height: 200px;
    }
    #header-right {
        width: 20%;
        background-color: #778A35;
        height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #dishes {
        width: 75%;
    }
    header, main {
        display: flex;
    }
    main {
        align-items: flex-start;
    }
    .dish {
        background-color: #778A35;
        text-align: center;
        margin: 20px;
        display: inline-block;
    }
    .dish img {
        margin: 15px;
        height: 150px;
    }
    .dish:hover {
        outline: 2px solid white;
    }
    footer {
        background-color: #778A35;
        margin-top: 10px;
        padding: 10px;
        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 (sekcje nagłówka, bloki potraw, stopka, przyciski i sekcja zamówienia - R.4.3) i marginesy (stopka, przyciski, nagłówki, bloki potraw i ich zdjęcia - R.4.8).

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

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

    Krok 39: Skrypt 1: funkcja wywoływana kliknięciem bloku

    Kryteria:

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

    ok. 3 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.

    Skrypty piszesz w bloku <script> na końcu <body> - wtedy lista i bloki już istnieją. Skrypt 1 to funkcja addDish(name) („dodaj potrawę”, nazwa po angielsku i mówiąca, co robi - R.5.2) z parametrem: nazwą potrawy.

    Każdy z sześciu bloków dostaje onclick z wywołaniem i nazwą swojej potrawy w apostrofach: onclick="addDish('Naleśniki')". Apostrofy wewnątrz, bo cudzysłów otwiera już wartość atrybutu.

    Typowe błędy

    onclick="addDish("Naleśniki")" - cudzysłów w środku zamyka atrybut i przeglądarka widzi tylko addDish(. Wewnątrz atrybutu w cudzysłowie używasz apostrofów.

    index.html HTML zmienione: 10 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" onclick="addDish('Naleśniki')">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" onclick="addDish('Lasagne szpinakowa')">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" onclick="addDish('Pieczona marchewka')">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" onclick="addDish('Wege rosół')">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" onclick="addDish('Tarta szparagowa')">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" onclick="addDish('Kompot')">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
            }
        </script>
    </body>
    </html>
    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).

    Trzy instrukcje z tabeli 2:

    • document.createElement("li") tworzy nowy element listy (na razie tylko w pamięci),
    • item.innerHTML = name wpisuje do niego nazwę potrawy z parametru,
    • getElementById("order-list").appendChild(item) dokłada go na koniec listy.

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

    Typowe błędy

    getElementById("order-list").innerHTML = name zastępuje całą listę - zamiast nowej pozycji zostaje sam tekst, bez <li>.

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button>Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" onclick="addDish('Naleśniki')">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" onclick="addDish('Lasagne szpinakowa')">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" onclick="addDish('Pieczona marchewka')">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" onclick="addDish('Wege rosół')">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" onclick="addDish('Tarta szparagowa')">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" onclick="addDish('Kompot')">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  41. Krok 41: 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.

    Funkcja clearOrder() wpisuje do listy pusty napis: innerHTML = "" usuwa wszystkie <li> naraz, a sam znacznik <ul> zostaje. Przycisk „Wyczyść” dostaje onclick="clearOrder()" - zdarzenie wciśnięcia przycisku, które uruchamia funkcję (R.3.3, R.5.4). Dodaj w podglądzie kilka potraw i wyczyść listę.

    index.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button onclick="clearOrder()">Wyczyść</button>
                <button>Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" onclick="addDish('Naleśniki')">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" onclick="addDish('Lasagne szpinakowa')">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" onclick="addDish('Pieczona marchewka')">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" onclick="addDish('Wege rosół')">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" onclick="addDish('Tarta szparagowa')">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" onclick="addDish('Kompot')">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").innerHTML = "";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  42. Krok 42: 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).

    Funkcja confirmOrder() i alert(komunikat) - okienko z komunikatem i przyciskiem OK, jak na ilustracji 5 (R.5.5). Przycisk „Zatwierdź” wywołuje ją przez onclick.

    Uwaga do podglądu: ramka podglądu blokuje okienka alert, więc tu komunikat się nie pokaże. Otwórz plik w przeglądarce - okienko pojawi się po kliknięciu.

    index.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button onclick="clearOrder()">Wyczyść</button>
                <button onclick="confirmOrder()">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" onclick="addDish('Naleśniki')">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" onclick="addDish('Lasagne szpinakowa')">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" onclick="addDish('Pieczona marchewka')">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" onclick="addDish('Wege rosół')">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" onclick="addDish('Tarta szparagowa')">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" onclick="addDish('Kompot')">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").innerHTML = "";
            }
    
            function confirmOrder() {
                alert("Zamówienie zostało przekazane do realizacji");
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  43. Krok 43: 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.

    Po komunikacie lista jest czyszczona tak samo jak w skrypcie 2. Kolejność ma znaczenie: alert zatrzymuje skrypt, dopóki użytkownik nie kliknie OK - dopiero wtedy lista znika, więc przy komunikacie zamówienie jest jeszcze widoczne (R.5.6).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button onclick="clearOrder()">Wyczyść</button>
                <button onclick="confirmOrder()">Zatwierdź</button>
            </section>
            <section id="dishes">
                <div class="dish" onclick="addDish('Naleśniki')">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish" onclick="addDish('Lasagne szpinakowa')">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish" onclick="addDish('Pieczona marchewka')">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish" onclick="addDish('Wege rosół')">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish" onclick="addDish('Tarta szparagowa')">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish" onclick="addDish('Kompot')">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").innerHTML = "";
            }
    
            function confirmOrder() {
                alert("Zamówienie zostało przekazane do realizacji");
                document.getElementById("order-list").innerHTML = "";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  44. Krok 44: 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 sprawdza osobno, że po wyczyszczeniu listy można znowu dodawać potrawy (R.5.7). W tym rozwiązaniu działa to bez dodatkowego kodu: innerHTML = "" usuwa zawartość listy, a sam <ul id="order-list"> zostaje na stronie, więc appendChild w skrypcie 1 nadal ma do czego dopisywać. W podglądzie: dodaj potrawy, wyczyść, dodaj znowu.

    Typowe błędy

    Usunięcie całej listy (np. getElementById("order-list").remove()) zamiast jej zawartości psuje skrypt 1 - przy następnym kliknięciu getElementById zwraca null i nic się nie dodaje.

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

  45. Etap 5: Dobre praktyki (poza kluczem)

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

    Krok 45: Nasłuchiwacze i nazwa potrawy brana z bloku

    ok. 4 min
    Polecenie z arkusza

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

    Nazwa każdej potrawy była zapisana dwa razy: w akapicie i w onclick. Wystarczy poprawić jedną (np. „Wege rosół” na „Rosół warzywny”), żeby lista zamówienia pokazywała co innego niż menu. Teraz skrypt sam dopina nasłuchiwacze: querySelectorAll(".dish") (tabela 2) zwraca wszystkie bloki, a w każdym addEventListener("click", ...) czyta nazwę z jego akapitu - dish.querySelector("p").textContent. Nowy blok potrawy dopisany w HTML-u działa od razu, bez dopisywania wywołania. Stara postać bloku zostaje w komentarzu.

    Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    Typowe błędy

    addEventListener("click", addDish(dish.querySelector("p").textContent)) bez funkcji anonimowej wywołuje addDish od razu przy wczytaniu - lista zapełnia się sześcioma potrawami bez kliknięcia.

    index.html HTML zmienione: 14 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button onclick="clearOrder()">Wyczyść</button>
                <button onclick="confirmOrder()">Zatwierdź</button>
            </section>
            <section id="dishes">
                <!-- wersja z egzaminu: <div class="dish" onclick="addDish('Naleśniki')"> -->
                <div class="dish">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").innerHTML = "";
            }
    
            function confirmOrder() {
                alert("Zamówienie zostało przekazane do realizacji");
                document.getElementById("order-list").innerHTML = "";
            }
    
            // zamiast atrybutu onclick w każdym bloku potrawy
            for (const dish of document.querySelectorAll(".dish")) {
                dish.addEventListener("click", function () {
                    addDish(dish.querySelector("p").textContent);
                });
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  46. Krok 46: Bez powtórzeń i bez pustego zamówienia

    ok. 4 min
    Polecenie z arkusza

    Na stronie pojawia się alert z informacją „Zamówienie zostało przekazane do realizacji” (ilustracja 5).

    Wersja z egzaminu „przekazuje do realizacji” także pustą listę - restauracja dostałaby zamówienie bez potraw. Poprawki:

    • confirmOrder() najpierw sprawdza, czy lista ma jakiekolwiek pozycje (children.length); pusta - inny komunikat i return,
    • czyszczenie po zatwierdzeniu woła clearOrder() zamiast powtarzać tę samą linię - jedno miejsce do zmiany,
    • replaceChildren() bez argumentów usuwa wszystkie dzieci elementu - mówi wprost, co robi, zamiast podstawiać pusty HTML,
    • textContent zamiast innerHTML w nowej pozycji - wstawiasz zwykły tekst, a nie kod HTML.

    Stare funkcje zostają w komentarzu /* */. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    index.html HTML zmienione: 21 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <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"></ul>
                <button onclick="clearOrder()">Wyczyść</button>
                <button onclick="confirmOrder()">Zatwierdź</button>
            </section>
            <section id="dishes">
                <!-- wersja z egzaminu: <div class="dish" onclick="addDish('Naleśniki')"> -->
                <div class="dish">
                    <img src="nalesniki.webp" alt="Naleśniki">
                    <p>Naleśniki</p>
                </div>
                <div class="dish">
                    <img src="lasagne.webp" alt="Lasagne szpinakowa">
                    <p>Lasagne szpinakowa</p>
                </div>
                <div class="dish">
                    <img src="marchewka.webp" alt="Pieczona marchewka">
                    <p>Pieczona marchewka</p>
                </div>
                <div class="dish">
                    <img src="rosol.webp" alt="Wege rosół">
                    <p>Wege rosół</p>
                </div>
                <div class="dish">
                    <img src="tarta.webp" alt="Tarta szparagowa">
                    <p>Tarta szparagowa</p>
                </div>
                <div class="dish">
                    <img src="kompot.webp" alt="Kompot">
                    <p>Kompot</p>
                </div>
            </section>
        </main>
        <footer>
            <p>Wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addDish(name) {
                const item = document.createElement("li");
                item.textContent = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").replaceChildren();
            }
    
            function confirmOrder() {
                if (document.getElementById("order-list").children.length == 0) {
                    alert("Zamówienie jest puste - kliknij potrawę, aby ją dodać");
                    return;
                }
                alert("Zamówienie zostało przekazane do realizacji");
                clearOrder();
            }
    
            /* wersja z egzaminu:
            function addDish(name) {
                let item = document.createElement("li");
                item.innerHTML = name;
                document.getElementById("order-list").appendChild(item);
            }
    
            function clearOrder() {
                document.getElementById("order-list").innerHTML = "";
            }
    
            function confirmOrder() {
                alert("Zamówienie zostało przekazane do realizacji");
                document.getElementById("order-list").innerHTML = "";
            }
            */
    
            // zamiast atrybutu onclick w każdym bloku potrawy
            for (const dish of document.querySelectorAll(".dish")) {
                dish.addEventListener("click", function () {
                    addDish(dish.querySelector("p").textContent);
                });
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  47. Krok 47: Nagłówek, który nie wylewa się w wąskim oknie

    ok. 2 min
    Polecenie z arkusza

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

    Tu arkusz rozmija się z praktyką. Lewa sekcja ma sztywne 200 px wysokości, a nagłówki dostają po 200 px wcięcia z lewej i duże litery. Na monitorze egzaminacyjnym (szeroki ekran) mieszczą się w jednej linii, ale przy oknie szerokim na ok. 1100 px nazwa restauracji łamie się na dwie linie i podtytuł wychodzi poza zielony pas, wchodząc na sekcję zamówienia - sprawdzone w Chrome. height obcina wysokość tła, a nie treść.

    Zamiana na min-height: 200px zostawia 200 px jako minimum: gdy treść się mieści, wygląd jest identyczny jak na ilustracji 2, a gdy nie - sekcja rośnie razem z nią. Stara linia zostaje w komentarzu. Na egzaminie zostaw height: 200px - klucz (R.4.5) sprawdza właśnie wysokość.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Verdana;
        border-radius: 5px;
    }
    body {
        background-color: #D1E2C4;
    }
    #header-left {
        /* height: 200px; - wersja z egzaminu */
        width: 80%;
        background-color: #778A35;
        min-height: 200px;
    }
    #header-right {
        /* height: 200px; - wersja z egzaminu */
        width: 20%;
        background-color: #778A35;
        min-height: 200px;
    }
    h1 {
        font-size: 50px;
        padding-left: 200px;
    }
    h3 {
        font-size: 30px;
        font-style: italic;
        padding-left: 200px;
    }
    #order {
        background-color: #EBEBE8;
        width: 25%;
    }
    #dishes {
        width: 75%;
    }
    header, main {
        display: flex;
    }
    main {
        align-items: flex-start;
    }
    .dish {
        background-color: #778A35;
        text-align: center;
        margin: 20px;
        display: inline-block;
    }
    .dish img {
        margin: 15px;
        height: 150px;
    }
    .dish:hover {
        outline: 2px solid white;
    }
    footer {
        background-color: #778A35;
        margin-top: 10px;
        padding: 10px;
        text-align: right;
    }
    button {
        background-color: #778A35;
        padding: 5px;
    }
    Podgląd strony po tym kroku (index.html)
  48. Etap 6: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

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

    W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę.

    W folderze z numerem zdającego: index.html, styl.css, kwerendy.txt, import.png, kw1.png - kw5.png, zdjęcia potraw, logo.png i przeglądarka.txt. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.