Przejdź do głównej treści
EE.09-04-20.06-SGCzerwiec 2020 · 38 kroków · ok. 74 min · 33 kryteria z klucza

Rozwiązanie krok po kroku: Salon kosmetyczny z kalkulatorem zabiegów (Nowoczesny kod (flex, addEventListener))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza egzamin1 z czterema zapytaniami, dwa przeskalowane zdjęcia i strony index.html oraz twarz.html z kalkulatorem ceny zabiegów - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • kontener flex zamiast float: cztery bloki stoją w znaczniku <main>, który układa je w kolumny (flex-direction: column i flex-wrap: wrap) - szerokości 25% i 75% dalej są ustawione na samych blokach, a stopka nie potrzebuje clear,
  • zmienne CSS dla dwóch kolorów z arkusza, pola wyboru z etykietami <label> (kliknięcie podpisu zaznacza pole),
  • ceny zapisane przy polach w atrybutach data-price - skrypt nie powtarza cennika, tylko sumuje zaznaczone pola w pętli,
  • skrypt w osobnym pliku skrypt.js podpięty z atrybutem defer, przycisk obsłużony przez addEventListener, wynik wpisany przez textContent.

Kroki bazy danych i grafiki są takie same jak w wersji podstawowej. Arkusz to EE.09 z czerwca 2020 (formuła 2017, zastąpiona przez INF.03); materiały pochodzą z oryginalnego archiwum CKE egzamin1.zip, zapytania są wykonane na MariaDB 10.4, a skrypt sprawdzony w Chrome dla wszystkich 16 kombinacji zaznaczeń.

Jak liczą się punkty. Klucz ma 33 kryteria (R.1.1 - R.5.4), każde za 1 punkt; próg to 25 punktów.

  1. Etap 1: Baza danych

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

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

    ok. 2 min
    Polecenie z arkusza

    Na pulpicie znajdziesz archiwum ZIP o nazwie egzamin1.zip zabezpieczone hasłem: Do{Rozp4kow4ni4}. Archiwum należy rozpakować. Na pulpicie konta Egzamin utwórz folder. Jako nazwy folderu użyj swojego numeru PESEL. Umieść w tym folderze rozpakowane pliki.

    Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum egzamin1.zip rozpakowujesz do tego folderu, podając hasło Do{Rozp4kow4ni4} - z klamrami, wielką literą D i R oraz cyframi 4 w miejscu liter „a”. W środku są trzy pliki: egzamin.sql, obraz1.jpg i obraz2.jpg.

    Do tego folderu trafia wszystko, co powstanie: zrzuty, kwerendy.txt, strony, style i przeskalowane zdjęcia.

    Typowe błędy

    Hasło przepisuj znak po znaku - w czcionce arkusza łatwo pomylić { z (, a cyfrę 4 z literą A.

  2. Krok 2: XAMPP i pusta baza egzamin1

    ok. 2 min
    Polecenie z arkusza

    Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz bazę danych o nazwie egzamin1

    W XAMPP Control Panel Start przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa egzamin1 (z cyfrą 1 na końcu), Utwórz. Strony w tym zadaniu nie łączą się z bazą - baza służy do importu i czterech zapytań.

  3. Krok 3: Import pliku egzamin.sql i zrzut egzamin.jpg

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych egzamin1 , czynność udokumentowano plikiem o nazwie egzamin w formacie JPEG. Zrzut zawiera cały obszar ekranu monitora z widocznym paskiem zadań

    ok. 3 min
    Polecenie z arkusza

    Do bazy egzamin1 zaimportuj tabele z pliku egzamin.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie JPEG o nazwie egzamin, w folderze opisanym numerem PESEL. Nie kadruj zrzutu. Zrzut powinien obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Zaznacz bazę egzamin1, karta Import, Wybierz plik → egzamin.sql, Wykonaj. Plik tworzy sześć tabel, choć arkusz opisuje tylko dwie: kadra (5 pracowników) i uslugi (10 usług) oraz niepotrzebne w tym zadaniu matematycy, typy, uzytkownik i wyniki. Klucze główne i AUTO_INCREMENT ustawiają polecenia ALTER TABLE na końcu pliku.

    Na zrzucie ma być widać zielony komunikat o sukcesie i tabele w lewym panelu. Zrzut całego ekranu z paskiem zadań zapisujesz jako egzamin.jpg - na przykład Print Screen, wklejenie do edytora grafiki i eksport do JPEG.

    Typowe błędy

    Zrzut importu ma być w JPEG, a zrzuty zapytań w PNG - pomylony format to strata punktu. Wykadrowanego zrzutu albo zrzutu bez paska zadań klucz nie ocenia.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Zapytanie 1: usługi tańsze niż 30 zł

    Kryteria: ,

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

    R.1.3 Utworzono zapytanie 1 wybierające jedynie pola nazwa i cena z tabeli uslugi dla usług, których cena jest niższa od 30 zł. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, cena FROM uslugi WHERE cena < 30; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie trzy rekordy, jedynie pola nazwa i cena o wartościach: Masaz twarzy 20, Regulacja brwi 5, Henna 10

    ok. 3 min
    Polecenie z arkusza

    Zapisz i wykonaj zapytania SQL działające na bazie egzamin1. Zapytania zapisz w pliku kwerendy.txt, w folderze z numerem PESEL. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie PNG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora, z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola nazwa i cena z tabeli uslugi dla usług, których cena jest niższa od 30 zł

    Zaznacz bazę egzamin1 i otwórz kartę SQL:

    • SELECT nazwa, cena - tylko dwie kolumny; „jedynie” wyklucza SELECT *,
    • FROM uslugi,
    • WHERE cena < 30 - ostro mniejsze, bo arkusz mówi „niższa od 30 zł”; usługa za dokładnie 30 zł (Maska) się nie łapie.

    Wynik: Masaz twarzy 20, Regulacja brwi 5 i Henna 10 - dokładnie te trzy rekordy wymienia klucz. Nazwy są bez polskich liter, bo tak zapisano je w pliku egzamin.sql. Zapytanie kopiujesz do nowego pliku kwerendy.txt, zrzut całego ekranu - do kw1.png.

    Typowe błędy

    cena <= 30 doda Maskę i Czesanie - pięć rekordów zamiast trzech to brak punktu.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, cena FROM uslugi WHERE cena < 30;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: suma cen usług kosmetycznych

    Kryteria:

    R.1.4 Utworzono zapytanie 2 liczące sumę ceny dla wszystkich usług kosmetycznych (rodzaj=1). W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT SUM(cena) FROM uslugi WHERE rodzaj=1; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczna jest jedynie wartość 180 wynikająca z wydanego zapytania 2

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: liczące sumę cen dla wszystkich usług kosmetycznych (rodzaj odpowiada usługom kosmetycznym)

    Arkusz podaje znaczenie pola rodzaj: 1 - usługi kosmetyczne, 2 - fryzjerskie, 3 - inne.

    • SELECT SUM(cena) - funkcja SUM dodaje wartości kolumny ze wszystkich wierszy, które przeszły przez warunek,
    • FROM uslugi,
    • WHERE rodzaj = 1 - tylko usługi kosmetyczne.

    Kosmetyczne są: Piling enzymatyczny 45, Maska 30, Regulacja brwi 5, Henna 10 i Paznokcie 90, razem 180 - ta wartość jest w kluczu. Masaż twarzy ma rodzaj 3 („inne”), więc do sumy nie wchodzi. Zrzut: kw2.png.

    Typowe błędy

    COUNT(cena) policzy usługi (5), a nie ich ceny. Zapytanie ma działać dla dowolnych danych - warunek po polu rodzaj, nie lista nazw usług.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM uslugi WHERE cena < 30;
    
    -- Zapytanie 2
    SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: konto kosmetyczka na localhost

    Kryteria:

    R.1.5 Utworzono zapytanie 3 tworzące użytkownika kosmetyczka na localhost z hasłem Kosmet34 W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym na pomyślne dodanie użytkownika kosmetyczka nie uznajemy za spełnione jeśli nie jest widoczne hasło (np wygenerowano z kreatora)

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: tworzące użytkownika kosmetyczka na localhost z hasłem Kosmet34

    • CREATE USER 'kosmetyczka'@'localhost' - nowe konto serwera bazy danych (nie wiersz w tabeli); część @'localhost' oznacza, że konto może się łączyć tylko z tego samego komputera, na którym działa serwer,
    • IDENTIFIED BY 'Kosmet34' - hasło konta; wielkość liter ma znaczenie.

    phpMyAdmin odpowiada „MySQL zwrócił pusty wynik” - polecenie niczego nie wybiera, więc to znak sukcesu. Konto widać potem na karcie Konta użytkowników. Zrzut: kw3.png.

    Typowe błędy

    Klucz nie uznaje konta założonego kreatorem Dodaj konto użytkownika, bo na zrzucie nie widać hasła - zapytanie wpisz na karcie SQL. Drugie wykonanie zgłosi błąd #1396 - konto już istnieje.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM uslugi WHERE cena < 30;
    
    -- Zapytanie 2
    SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;
    
    -- Zapytanie 3
    CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: prawa SELECT i INSERT do tabeli uslugi

    Kryteria:

    R.1.6 Utworzono zapytanie 4 nadające prawa przeglądania danych i wstawiania rekordów do tabeli uslugi bazy egzamin1 dla użytkownika kosmetyczka. W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT SELECT, INSERT ON egzamin1.uslugi TO 'kosmetyczka'@'localhost'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym na pomyślne wykonanie zapytania 4

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: nadające prawa przeglądania danych i wstawiania rekordów do tabeli uslugi bazy egzamin1 dla użytkownika kosmetyczka

    • GRANT SELECT, INSERT - przeglądanie danych to SELECT, wstawianie rekordów to INSERT,
    • ON egzamin1.uslugi - zapis baza.tabela ogranicza prawa do jednej tabeli; egzamin1.* dałoby je do wszystkich sześciu,
    • TO 'kosmetyczka'@'localhost' - konto podane tak samo jak przy tworzeniu, razem z hostem.

    Sprawdzone poleceniem SHOW GRANTS: konto ma GRANT SELECT, INSERT ON egzamin1.uslugi i nic więcej. Zrzut: kw4.png; plik kwerendy.txt ma komplet czterech zapytań.

    Typowe błędy

    TO 'kosmetyczka' bez hosta oznacza konto 'kosmetyczka'@'%', którego nie ma - serwer zgłosi błąd albo (w innych ustawieniach) utworzy drugie konto bez hasła.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM uslugi WHERE cena < 30;
    
    -- Zapytanie 2
    SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;
    
    -- Zapytanie 3
    CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34';
    
    -- Zapytanie 4
    GRANT SELECT, INSERT ON egzamin1.uslugi TO 'kosmetyczka'@'localhost';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

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

    Krok 8: Grafika: obraz1.jpg o wysokości 250 px

    Kryteria:

    R.2.1 Plik obraz1.jpg przeskalowano z zachowaniem proporcji do wysokości 250 px, odpowiadająca temu szerokość wynosi 200 px (± 2 px) lub plik obraz2.jpg przeskalowano z zachowaniem proporcji do szerokości 800 px, odpowiadająca temu wysokość wynosi 339 px (± 2 px)

    ok. 2 min
    Polecenie z arkusza

    Plik obraz1.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 250 px

    Oryginał ma 352 × 440 px. W GIMP-ie Obraz → Skaluj obraz, łańcuch między szerokością a wysokością złączony (to jest zachowanie proporcji), wysokość 250 - szerokość przelicza się sama: 352 × 250 / 440 = 200 px. Klucz podaje właśnie 200 px (±2). Plik → Nadpisz obraz1.jpg.

    Typowe błędy

    Ustawienie wymiarów atrybutem height albo w CSS nie zmienia pliku - klucz mierzy sam plik. Wpisanie wysokości przy rozpiętym łańcuchu da obraz 352 × 250, rozciągnięty w poziomie.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Grafika: obraz2.jpg o szerokości 800 px

    ok. 2 min
    Polecenie z arkusza

    Plik obraz2.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego szerokość wynosiła dokładnie 800 px

    Oryginał ma 900 × 381 px. Ta sama operacja, tym razem wpisujesz szerokość 800 - wysokość: 381 × 800 / 900 = 338,7, czyli 339 px (klucz: 339 px ±2). Wystarczy jeden z dwóch obrazów, żeby dostać R.2.1, ale arkusz wymaga obu.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Etap 3: Strona HTML

    Kroki 10-22 · po tym etapie masz 17 z 33 kryteriów (pkt)

    Krok 10: Plik index.html i kodowanie

    Kryteria:

    R.2.2 Witrynę internetową zapisano w plikach HTML o nazwach index i twarz oraz na przynajmniej jednej stronie zastosowano właściwy standard kodowania polskich znaków

    ok. 2 min
    Polecenie z arkusza

    Składa się ze stron o nazwach index.html oraz twarz.html. Obie strony różnią się jedynie drugim blokiem prawym. Zastosowany właściwy standard kodowania polskich znaków

    Szkielet index.html z <meta charset="UTF-8"> (R.2.2) i znacznikiem viewport dla telefonów. twarz.html będzie kopią z innym drugim blokiem prawym.

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

    Kryteria: ,

    R.2.3 Nadano tytuł: "Usługi kosmetyczne” przynajmniej dla jednej strony

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

    ok. 1 min
    Polecenie z arkusza

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

    <title> (R.2.3) i <link rel="stylesheet" href="styl.css"> - całe formatowanie w tym pliku (R.3.5).

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  12. Krok 12: Bloki w kontenerze main

    Kryteria:

    R.2.4 Wygląd przynajmniej jednej strony zdefiniowano dzieląc ją na bloki: dwa bloki po lewej stronie i dwa po prawej, poniżej stopka. Zastosowano znaczniki sekcji

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki: dwa bloki po lewej stronie i dwa po prawej, poniżej stopka. Podział zrealizowany za pomocą znaczników sekcji, tak aby po uruchomieniu w przeglądarce układ bloków był zgodny z Obrazem 2

    Cztery bloki to znaczniki <section> (R.2.4) w kontenerze <main>, stopka to <footer> poza nim.

    Kolejność w kodzie jest kolumnami: najpierw dwa bloki lewe, potem dwa prawe. W stylach <main> ułoży bloki z góry na dół i po zapełnieniu lewej kolumny przejdzie do prawej - kod czyta się wtedy tak, jak wygląda strona. W wersji podstawowej z float kolejność musiała być inna (lewy, prawy, prawy, lewy).

    index.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
            </section>
            <section id="left2">
            </section>
            <section id="right1">
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Pierwszy blok lewy: nagłówek i lista z podlistą

    Kryteria:

    R.2.7 Na przynajmniej jednej stronie w pierwszym bloku lewym umieszczono listę punktową z trzema elementami, pierwszy z elementów ma zagnieżdżoną listę numerowaną z trzema elementami, zastosowano znaczniki <ul>, <ol>, <li> oraz ich zamknięcia

    ok. 3 min
    Polecenie z arkusza

    Zawartość pierwszego bloku po lewej stronie: Nagłówek drugiego stopnia o treści „W ofercie”. Lista punktowa (nieuporządkowana) z elementami: Zabiegi na twarz, Masaż, Diety oczyszczające. Element „Zabiegi na twarz” ma zagnieżdżoną listę numerowaną (uporządkowaną) z elementami: Piling, Maska, Regulacja brwi

    <h2>, lista <ul> i w jej pierwszym elemencie - przed </li> - lista <ol> (R.2.7). Wcięcia w kodzie pokazują zagnieżdżenie: łatwo sprawdzić, że <ol> należy do „Zabiegów na twarz”.

    index.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
            </section>
            <section id="left2">
            </section>
            <section id="right1">
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Odnośnik „Zabiegi na twarz”

    Kryteria:

    R.3.2 Na przynajmniej jednej stronie odnośnik "Zabiegi na twarz" prowadzi do strony twarz.html

    ok. 1 min
    Polecenie z arkusza

    Tekst elementu „Zabiegi na twarz” jest równocześnie odnośnikiem do strony twarz.html

    Tekst elementu jest już w odnośniku <a href="twarz.html"> ze ścieżką względną (R.3.2) - odnośnik obejmuje sam napis, a podlista stoi za nim.

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
            </section>
            <section id="left2">
            </section>
            <section id="right1">
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>

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

  15. Krok 15: Odnośnik „Do strony głównej”

    Kryteria:

    R.3.3 Na przynajmniej jednej stronie odnośnik "Do strony głównej" prowadzi do strony index.html

    ok. 1 min
    Polecenie z arkusza

    Odnośnik o treści „Do strony głównej” do strony index.html

    <a href="index.html"> pod listą (R.3.3).

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
            </section>
            <section id="right1">
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Pierwszy blok prawy: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość pierwszego bloku po prawej stronie: nagłówek pierwszego stopnia o treści „Salon Kosmetyczny”

    <h1> - najważniejszy nagłówek strony.

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Drugi blok lewy: zdjęcie

    ok. 1 min
    Polecenie z arkusza

    Zawartość drugiego bloku po lewej stronie: obraz o nazwie obraz1.jpg z tekstem alternatywnym „Kosmetyczka”

    <img> z alt. Atrybuty width i height (wymiary po przeskalowaniu) rezerwują miejsce, zanim obraz się wczyta.

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Stopka

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: akapit (paragraf) o treści „Autor: ”, dalej wstawiony numer PESEL zdającego

    Akapit <p> w <footer>; na egzaminie numer PESEL, tu Bartosz Bryniarski.

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Drugi blok prawy index.html

    Kryteria:

    R.2.6 Na przynajmniej jednej stronie umieszczono w drugim bloku lewym obraz obraz1.jpg z tekstem alternatywnym "Kosmetyczka" oraz na stronie index.html umieszczono w drugim panelu prawym obraz obraz2.jpg z tekstem alternatywnym "Zabiegi kosmetyczne"

    ok. 2 min
    Polecenie z arkusza

    Zawartość drugiego bloku po prawej stronie dla index.html: Obraz o nazwie obraz2.jpg z tekstem alternatywnym „Zabiegi kosmetyczne”. Akapit (paragraf) o treści zgodnej z Obrazem 2, łamanie wiersza zgodne z Obrazem 2. Nagłówek czwartego stopnia o treści „Telefon: 111 222 333”

    Zdjęcie (R.2.6 razem z obrazem w drugim bloku lewym), akapit z <br> po pierwszym zdaniu - tak jak na obrazie 2 - i nagłówek <h4>. Strona index.html jest kompletna.

    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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <img src="obraz2.jpg" alt="Zabiegi kosmetyczne" width="800" height="339">
                <p>Witaj! Miło nam, że odwiedziłeś nasz salon.<br>
                Zapoznaj się z ofertą i sprawdź ceny zabiegów lub skontaktuj się z nami</p>
                <h4>Telefon: 111 222 333</h4>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Strona twarz.html: nagłówek

    Kryteria:

    R.2.5 Na przynajmniej jednej stronie w pierwszym bloku lewym zapisano nagłówek h2: "W ofercie", w pierwszym bloku prawym zapisano nagłówek h1: "Salon Kosmetyczny", w bloku drugim prawym nagłówek h4: "Telefon: 111 222 333" i nagłówek h2: "Sprawdź cenę swojej wizyty" oraz przynajmniej jeden paragraf (znacznik <p>)

    ok. 2 min
    Polecenie z arkusza

    Wygląd drugiego bloku po prawej stronie dla twarz.html przedstawiono na Obrazie 3, jego zawartość to: Nagłówek drugiego stopnia o treści „Sprawdź cenę swojej wizyty”

    Kopia index.html jako twarz.html z nagłówkiem <h2> w drugim bloku prawym. Komplet nagłówków i akapit to R.2.5.

    twarz.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  21. Krok 21: Cztery pola z etykietami i cenami

    ok. 3 min
    Polecenie z arkusza

    Cztery pola checkbox jeden pod drugim z podpisami: Piling, Maska, Masaż twarzy, Regulacja brwi

    Każde pole stoi we własnym <div> - blok zaczyna nową linię, więc <br> nie jest potrzebne:

    • <label for="piling"> wiąże podpis z polem o tym identyfikatorze: kliknięcie napisu zaznacza pole, a czytnik ekranu odczytuje podpis razem z polem,
    • data-price="45" - własny atrybut z ceną z tabeli arkusza; cena stoi przy polu, którego dotyczy, a skrypt odczyta ją jako dataset.price.

    Masaż twarzy ma cenę 20 - w tabeli arkusza ta pozycja nazywa się „Masaż”.

    twarz.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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  22. Krok 22: Przycisk i miejsce na wynik

    Kryteria:

    R.2.8 Na stronie twarz.html w drugim bloku prawym umieszczono cztery pola checkbox oraz przycisk o treści: "Sprawdź cenę"

    ok. 2 min
    Polecenie z arkusza

    Poniżej przycisk o treści „Sprawdź cenę”. Poniżej wyniki działania skryptu

    <button type="button"> z identyfikatorem check - bez atrybutu onclick, skrypt sam się do niego podłączy. Pusty akapit result czeka na wynik; aria-live="polite" sprawia, że czytnik ekranu odczyta wynik, gdy się pojawi. Cztery pola i przycisk to R.2.8.

    twarz.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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
                <button type="button" id="check">Sprawdź cenę</button>
                <p id="result" aria-live="polite"></p>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  23. Etap 4: Styl CSS

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

    Krok 23: Zmienne z kolorami i krój Garamond

    Kryteria:

    R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Garamond (dla selektora * lub body, lub html, lub kontenera całej strony)

    ok. 2 min
    Polecenie z arkusza

    Domyślne dla całej strony: krój czcionki Garamond

    Dwa kolory arkusza jako zmienne w :root - użyte będą sześć razy. font-family: Garamond, serif na body (R.4.1); serif to krój zapasowy, gdyby Garamonda nie było w systemie.

    styl.css CSS nowy plik
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Pierwszy blok lewy

    ok. 1 min
    Polecenie z arkusza

    Dla pierwszego lewego bloku: wysokość 500 px, szerokość 25%, kolor tła Lavender

    Wymiary i tło ze zmiennej --lavender.

    styl.css CSS zmienione: 5 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Drugi blok lewy

    ok. 1 min
    Polecenie z arkusza

    Dla drugiego lewego bloku: wysokość 300 px, szerokość 25%, kolor tła Lavender

    Lewe bloki razem mają 800 px.

    styl.css CSS zmienione: 5 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Pierwszy blok prawy

    ok. 1 min
    Polecenie z arkusza

    Dla pierwszego prawego bloku: wysokość 150 px, szerokość 75%, kolor tła Indigo, biały kolor czcionki, rozmiar czcionki 200%, wyrównanie tekstu do środka

    Ciemne tło i biały tekst.

    styl.css CSS zmienione: 8 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Drugi blok prawy

    Kryteria: , ,

    R.4.4 Ustawiono wysokość bloków lewych kolejno na 500px i 300px oraz bloków prawych kolejno na 150px i 650px

    R.4.5 Ustawiono szerokość bloków lewych 25% oraz prawych 75%

    R.4.7 Ustawiono rozmiar czcionki na 200% dla bloków prawych

    ok. 1 min
    Polecenie z arkusza

    Dla drugiego prawego bloku: wysokość 650 px, szerokość 75%, kolor tła Lavender, rozmiar czcionki 200%, wyrównanie tekstu do środka

    Prawe bloki razem też mają 800 px. Wysokości (R.4.4), szerokości (R.4.5) i rozmiar 200% (R.4.7) są kompletne.

    styl.css CSS zmienione: 7 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Stopka

    Kryteria: , ,

    R.4.2 Ustawiono kolor tła Indigo dla pierwszego bloku prawego i stopki oraz kolor Lavender dla pozostałych bloków

    R.4.3 Ustawiono biały kolor czcionki dla pierwszego bloku prawego i stopki

    R.4.6 Ustawiono wyrównanie tekstu do środka dla bloków prawych oraz wyrównanie tekstu do prawej dla bloku stopki

    ok. 1 min
    Polecenie z arkusza

    Dla stopki: kolor tła Indigo, biały kolor czcionki, wyrównanie tekstu do prawej strony

    Tła (R.4.2), biały tekst (R.4.3) i wyrównania (R.4.6) są kompletne. Reguła footer p { margin: 0; } zdejmuje domyślny margines akapitu - bez niej wychodzi on poza stopkę i między blokami a paskiem stopki zostaje biały pas 16 px (w wersji podstawowej zjada go clear). Klucz tego nie ocenia.

    styl.css CSS zmienione: 8 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    footer {
        background-color: var(--indigo);
        color: white;
        text-align: right;
    }
    footer p {
        margin: 0;
    }
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Układ: kontener flex w kolumnach

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest w pełni zgodny z Obrazem 2 w arkuszu egzaminacyjnym

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki: dwa bloki po lewej stronie i dwa po prawej, poniżej stopka.

    • display: flex z flex-direction: column - <main> układa bloki z góry na dół,
    • flex-wrap: wrap i height: 800px - po zapełnieniu 800 px (500 + 300 w lewej kolumnie) kolejny blok przechodzi do nowej kolumny obok; prawe bloki (150 + 650) wypełniają ją dokładnie,
    • szerokość kolumny wynika z szerokości bloków: 25% i 75% szerokości <main>.

    Stopka stoi pod kontenerem bez clear. Zmierzone w Chrome przy oknie 1280 px: bloki lewe w kolumnie o szerokości 25%, prawe obok w 75%, stopka zaczyna się 800 px niżej (R.3.1).

    styl.css CSS zmienione: 6 linii
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    footer {
        background-color: var(--indigo);
        color: white;
        text-align: right;
    }
    footer p {
        margin: 0;
    }
    .layout {
        display: flex;
        flex-direction: column;
        flex-wrap: wrap;
        height: 800px;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Kwadratowe punktory

    Kryteria:

    R.4.8 Ustawiono styl dla listy punktowanej: punktor to kwadrat

    ok. 1 min
    Polecenie z arkusza

    Dla listy punktowanej (nieuporządkowanej): kwadrat jako punktor

    list-style-type: square na ul (R.4.8); podlista <ol> zostaje numerowana.

    styl.css CSS zmienione: 3 linie
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    footer {
        background-color: var(--indigo);
        color: white;
        text-align: right;
    }
    footer p {
        margin: 0;
    }
    .layout {
        display: flex;
        flex-direction: column;
        flex-wrap: wrap;
        height: 800px;
    }
    ul {
        list-style-type: square;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Obraz: marginesy

    Kryteria:

    R.4.9 Ustawiono styl dla obrazu: marginesy wewnętrzne (padding) 5px, marginesy zewnętrzne (margin) 10px

    ok. 1 min
    Polecenie z arkusza

    Dla obrazu: marginesy wewnętrzne 5 px, marginesy zewnętrzne 10 px

    padding i margin (R.4.9).

    styl.css CSS zmienione: 4 linie
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    footer {
        background-color: var(--indigo);
        color: white;
        text-align: right;
    }
    footer p {
        margin: 0;
    }
    .layout {
        display: flex;
        flex-direction: column;
        flex-wrap: wrap;
        height: 800px;
    }
    ul {
        list-style-type: square;
    }
    img {
        padding: 5px;
        margin: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Obraz pod kursorem

    Kryteria:

    R.4.10 Ustawiono styl dla obrazu z pseudoklasą hover: marginesy wewnętrzne (padding) 4 px oraz obramowanie linią ciągłą o szerokości 1 px i kolorze Indigo

    ok. 1 min
    Polecenie z arkusza

    W momencie, gdy kursor znajduje się na obrazie, styl obrazu zmienia się na: marginesy wewnętrzne 4 px oraz obramowanie linią ciągłą o szerokości 1 px i kolorze Indigo (efekt ten jest widoczny na Obrazie 2)

    :hover zmniejsza padding o 1 px dokładnie o grubość ramki - obraz z ramką zajmuje tyle samo miejsca, więc nic na stronie nie drga (R.4.10).

    styl.css CSS zmienione: 4 linie
    :root {
        --indigo: Indigo;
        --lavender: Lavender;
    }
    body {
        font-family: Garamond, serif;
    }
    #left1 {
        height: 500px;
        width: 25%;
        background-color: var(--lavender);
    }
    #left2 {
        height: 300px;
        width: 25%;
        background-color: var(--lavender);
    }
    #right1 {
        height: 150px;
        width: 75%;
        background-color: var(--indigo);
        color: white;
        font-size: 200%;
        text-align: center;
    }
    #right2 {
        height: 650px;
        width: 75%;
        background-color: var(--lavender);
        font-size: 200%;
        text-align: center;
    }
    footer {
        background-color: var(--indigo);
        color: white;
        text-align: right;
    }
    footer p {
        margin: 0;
    }
    .layout {
        display: flex;
        flex-direction: column;
        flex-wrap: wrap;
        height: 800px;
    }
    ul {
        list-style-type: square;
    }
    img {
        padding: 5px;
        margin: 10px;
    }
    img:hover {
        padding: 4px;
        border: 1px solid var(--indigo);
    }
    Podgląd strony po tym kroku (index.html)
  33. Etap 5: Skrypt JavaScript

    Kroki 33-36 · po tym etapie masz 33 z 33 kryteriów (pkt)

    Krok 33: Plik skrypt.js podpięty z defer

    Kryteria:

    R.5.1 Skrypt napisano w języku uruchamianym po stronie przeglądarki i zawiera on co najmniej jedną instrukcję tego języka zapisaną zgodnie ze składnią

    ok. 2 min
    Polecenie z arkusza

    Napisany w języku wykonywanym po stronie przeglądarki

    Skrypt w osobnym pliku skrypt.js, podpiętym w <head> strony twarz.html przez <script src="skrypt.js" defer>. defer każe wykonać go dopiero po wczytaniu całego HTML-a, więc przycisk i akapit już istnieją, gdy skrypt ich szuka (R.5.1).

    Na początek dwie stałe (const) z elementami, których skrypt użyje: przycisk i akapit na wynik.

    skrypt.js JavaScript nowy plik
    const button = document.getElementById('check');
    const result = document.getElementById('result');
    twarz.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>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
                <button type="button" id="check">Sprawdź cenę</button>
                <p id="result" aria-live="polite"></p>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  34. Krok 34: Nasłuchiwanie kliknięcia

    Kryteria:

    R.3.4 Po wciśnięciu przycisku wywoływana jest funkcja zapisana skryptem

    ok. 2 min
    Polecenie z arkusza

    Uruchamia się po wciśnięciu przycisku na stronie twarz.html

    addEventListener('click', ...) podłącza funkcję strzałkową do przycisku - HTML nie zawiera kodu skryptu, a skrypt nie zależy od nazwy funkcji w atrybucie (R.3.4). Na starcie każdego kliknięcia suma wynosi 0 - let, bo będzie rosła.

    skrypt.js JavaScript zmienione: 4 linie
    const button = document.getElementById('check');
    const result = document.getElementById('result');
    
    button.addEventListener('click', () => {
        let sum = 0;
    });
    twarz.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
                <button type="button" id="check">Sprawdź cenę</button>
                <p id="result" aria-live="polite"></p>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  35. Krok 35: Suma zaznaczonych: pętla i if

    Kryteria: ,

    R.5.2 Skrypt pobiera wartości z przynajmniej jednego pola checkbox i sprawdza jego stan za pomocą instrukcji warunkowej lub wyboru

    R.5.3 Skrypt liczy sumę jedynie wszystkich zaznaczonych pól checkbox zgodnie z cenami podanymi w tabeli w arkuszu

    ok. 3 min
    Polecenie z arkusza

    Oblicza łączną cenę zabiegów wybranych za pomocą pól checkbox zgodnie z cennikiem w tabeli

    • querySelectorAll zwraca wszystkie pola checkbox z drugiego bloku prawego, a for...of przechodzi po nich po kolei,
    • if (box.checked) - instrukcja warunkowa sprawdza stan pola (R.5.2),
    • box.dataset.price to wartość atrybutu data-price - tekst, więc Number() zamienia go na liczbę; bez tego += sklejałby napisy („04530”).

    Cennik jest w jednym miejscu - przy polach. Nowy zabieg to nowa linia HTML, bez zmiany skryptu (R.5.3).

    skrypt.js JavaScript zmienione: 5 linii
    const button = document.getElementById('check');
    const result = document.getElementById('result');
    
    button.addEventListener('click', () => {
        let sum = 0;
        for (const box of document.querySelectorAll('#right2 input[type="checkbox"]')) {
            if (box.checked) {
                sum += Number(box.dataset.price);
            }
        }
    });
    twarz.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
                <button type="button" id="check">Sprawdź cenę</button>
                <p id="result" aria-live="polite"></p>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  36. Krok 36: Wynik przez textContent

    Kryteria:

    R.5.4 Skrypt wypisuje wynik pod przyciskiem według wzoru: "Cena zabiegów: <suma>”, gdzie <suma> oznacza sumę wyliczoną przez skrypt

    ok. 2 min
    Polecenie z arkusza

    Wyświetla wynik działania pod przyciskiem według wzoru: „Cena zabiegów: <suma>”, gdzie <suma> oznacza całkowitą cenę wybranych zabiegów

    Szablon tekstowy w odwrotnych apostrofach wstawia sumę w miejsce ${sum}, a textContent wpisuje do akapitu zwykły tekst - nic z niego nie zostanie potraktowane jako HTML (R.5.4). Sprawdzone w Chrome dla wszystkich 16 kombinacji zaznaczeń.

    skrypt.js JavaScript zmienione: 1 linia
    const button = document.getElementById('check');
    const result = document.getElementById('result');
    
    button.addEventListener('click', () => {
        let sum = 0;
        for (const box of document.querySelectorAll('#right2 input[type="checkbox"]')) {
            if (box.checked) {
                sum += Number(box.dataset.price);
            }
        }
        result.textContent = `Cena zabiegów: ${sum}`;
    });
    twarz.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Usługi kosmetyczne</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <main class="layout">
            <section id="left1">
                <h2>W ofercie</h2>
                <ul>
                    <li><a href="twarz.html">Zabiegi na twarz</a>
                        <ol>
                            <li>Piling</li>
                            <li>Maska</li>
                            <li>Regulacja brwi</li>
                        </ol>
                    </li>
                    <li>Masaż</li>
                    <li>Diety oczyszczające</li>
                </ul>
                <a href="index.html">Do strony głównej</a>
            </section>
            <section id="left2">
                <img src="obraz1.jpg" alt="Kosmetyczka" width="200" height="250">
            </section>
            <section id="right1">
                <h1>Salon Kosmetyczny</h1>
            </section>
            <section id="right2">
                <h2>Sprawdź cenę swojej wizyty</h2>
                <div><input type="checkbox" id="piling" data-price="45"> <label for="piling">Piling</label></div>
                <div><input type="checkbox" id="mask" data-price="30"> <label for="mask">Maska</label></div>
                <div><input type="checkbox" id="massage" data-price="20"> <label for="massage">Masaż twarzy</label></div>
                <div><input type="checkbox" id="brows" data-price="5"> <label for="brows">Regulacja brwi</label></div>
                <button type="button" id="check">Sprawdź cenę</button>
                <p id="result" aria-live="polite"></p>
            </section>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (twarz.html)
  37. Etap 6: Porównanie z wersją podstawową

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

    Krok 37: Co daje druga wersja

    ok. 3 min

    Obie wersje dają ten sam wygląd i ten sam wynik, i obie spełniają wszystkie 33 kryteria. Różnice:

    wersja podstawowawersja nowoczesna
    układfloat i clear, bloki w kolejności lewy-prawy-prawy-lewy<main> z flex w kolumnach, bloki w kolejności kolumn
    kolorywpisane w każdej regulezmienne CSS
    polapodpis za polem, <br><label for> w osobnych <div>
    cenycztery osobne if z liczbami w skrypciedata-price przy polach, jedna pętla
    skryptw <script> na stronie, onclick w HTML-uskrypt.js z defer, addEventListener
    wynikinnerHTMLtextContent

    Na egzaminie wystarczy wersja podstawowa - arkusz podaje w tabeli getElementById, checked i innerHTML, a klucz sprawdza wynik, nie sposób. Nowoczesna pokazuje, jak pisze się kod łatwy do rozbudowy: dodanie piątego zabiegu nie wymaga zmiany skryptu.

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

  38. Etap 7: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nazwij plik przeglądarka.txt i zapisz go w folderze z numerem PESEL. Nagraj płytę z rezultatami pracy.

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

    W folderze z numerem PESEL muszą być: index.html, twarz.html, egzamin.jpg, kw1.png - kw4.png, kwerendy.txt, obraz1.jpg, obraz2.jpg, przeglądarka.txt, skrypt.js i styl.css. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem PESEL - zapakowana w pudełko zostaje na stanowisku razem z arkuszem.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

Podgląd

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

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

Potwierdzenie

Informacja