Przejdź do głównej treści
INF.03-06-24.06-SGCzerwiec 2024 · 35 kroków · ok. 72 min · 39 kryteriów z klucza

Rozwiązanie krok po kroku: Formularz rejestracji konferencji (Nowoczesny kod (grid, flex, JS))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza konferencja z czterema zapytaniami, rozmyte tulipany i strona rejestracja.html z formularzem w trzech kartach przełączanych skryptem, filmem, planem i odnośnikiem w czterech blokach stopki - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS na całej stronie: cztery kolumny po 25% (klucz R.4.5 przyjmuje grid-template-columns), baner i blok główny przez całą szerokość - zamiast float stopek,
  • karty formularza w kontenerze flex zamiast float - w wąskim oknie zwężają się, zamiast spadać pod blok główny,
  • stan karty w klasie CSS: skrypt tylko przekłada klasę active z karty na kartę, a wygląd (visibility) zostaje w arkuszu stylów,
  • skrypt w <script> na końcu <body> (klucz sprawdza go „w kodzie strony”), nasłuchiwacze zdarzeń zamiast onclick, jedna funkcja dla obu przycisków „Następna karta”, const i szablony tekstowe,
  • formularz przyjazny: grupy pól w <fieldset>, opisy pól dla czytników ekranu (aria-label) i podpowiedzi autouzupełniania (autocomplete).

Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza, zdjęcie i film pochodzą z prawdziwego archiwum pliki6, zapytania zostały wykonane na tej bazie w MariaDB z XAMPP-a, a skrypt sprawdzony w prawdziwej przeglądarce: przełączanie kart, okienko z komunikatem i napis w konsoli. Podgląd jest interaktywny.

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

  1. Etap 1: Baza danych

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

    Krok 1: Baza danych konferencja

    ok. 2 min
    Polecenie z arkusza

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

    Archiwum pliki6.zip rozpakuj hasłem ^konfErEncja& (daszek na początku, dwa wielkie E, ampersand na końcu) do folderu z numerem zdającego. W phpMyAdmin Nowa → konferencja, porównywanie utf8_unicode_ci, albo zapytaniem:

    CREATE DATABASE konferencja CHARACTER SET utf8 COLLATE utf8_unicode_ci;
    
  2. Krok 2: Import tabel z pliku baza.sql

    ok. 2 min
    Polecenie z arkusza

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

    Import → baza.sql. Dwie tabele z obrazu 1: uczestnicy (7 osób, klucz obcy wyklady_id) i wyklady (3 wykłady). Pole zaplacono typu TINYINT(1): 1 - zapłacił, 0 - jeszcze nie.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Cały ekran z paskiem zadań, zapis jako import.png. Zrzuty zapytań idą do JPEG.

    Typowe błędy

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

  4. Krok 4: Zapytanie 1: uczestnicy, którzy nie zapłacili

    Kryteria: ,

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

    R.1.3 Wykonano zapytanie 1 wybierające jedynie imię, nazwisko i koszt konferencji dla uczestników, którzy jeszcze nie zapłacili za konferencję. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, koszt FROM uczestnicy WHERE zaplacono = FALSE; (lub zaplacono=0) oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 5 rekordów z danymi: Piotr Górski 100, Marcin Szpak 150, Adam Binder 120, Robert Halicki 90, Alicja Warkowska 120

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie imię, nazwisko i koszt konferencji dla uczestników, którzy jeszcze nie zapłacili za konferencję

    „Jeszcze nie zapłacił” to 0 w polu TINYINT(1) (klucz uznaje też = FALSE). Wynik: 5 wierszy - Górski 100, Szpak 150, Binder 120, Halicki 90, Warkowska 120, jak w kluczu. Zapytania trafiają do kwerendy.txt, zrzut do kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, nazwisko, koszt
    FROM uczestnicy
    WHERE zaplacono = 0;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: średnia, suma i liczba z aliasami

    Kryteria:

    R.1.4 Wykonano zapytanie 2 : liczące dla wszystkich uczestników: średni koszt konferencji pod nazwą kolumny „Średni koszt”, sumę kosztów pod nazwą kolumny „Całkowity koszt”, liczbę zapisanych w bazie uczestników pod nazwą kolumny „Liczba uczestników”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT AVG(koszt) AS "Średni koszt", SUM(koszt) AS "Całkowity koszt", COUNT(*) AS "Liczba uczestników" FROM uczestnicy; oraz wynik działania udokumentowano zrzutem, na którym są widoczne wartości: 117.1429 (dowolne dokładność); 820; 7. Kolumny są podpisane (nadano aliasy)

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: liczące dla wszystkich uczestników: średni koszt konferencji z nazwą kolumny (alias) „Średni koszt”, sumę kosztów z nazwą kolumny (alias) „Całkowity koszt”, liczbę zapisanych w bazie uczestników z nazwą kolumny (alias) „Liczba uczestników”

    Trzy funkcje agregujące, każda w osobnej linii. Alias ze spacją i polskimi literami stoi w odwrotnych apostrofach - to w MySQL i MariaDB znak nazwy (identyfikatora); cudzysłowy z przykładu w kluczu też działają, ale formalnie oznaczają tekst. Wynik: 117.1429, 820, 7 z podpisanymi kolumnami. Zrzut: kw2.jpg.

    Typowe błędy

    Alias bez cudzysłowów albo odwrotnych apostrofów (AS Średni koszt) to błąd składni - spacja kończy nazwę.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT imie, nazwisko, koszt
    FROM uczestnicy
    WHERE zaplacono = 0;
    
    -- Zapytanie 2
    SELECT AVG(koszt) AS `Średni koszt`,
           SUM(koszt) AS `Całkowity koszt`,
           COUNT(*) AS `Liczba uczestników`
    FROM uczestnicy;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: wykład i dane uczestników, którzy zapłacili

    Kryteria:

    R.1.5 Wykonano zapytanie 3 wybierające jedynie nazwę wykładu i przypisane jej nazwiska i e- maile uczestników, dla tych uczestników, którzy zapłacili za konferencję. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, nazwisko, email FROM uczestnicy JOIN wyklady ON wyklady_id = wyklady.id WHERE zaplacono=TRUE; (lub zaplacono=1, możliwe również INNER JOIN lub bez JOIN i porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym są widoczne dokładnie 2 rekordy dla nazwiska Nowak i Rutkowski, jedynie pola nazwa, nazwisko, email

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie nazwę wykładu i przypisane jej nazwiska i e-maile uczestników, dla tych uczestników, którzy zapłacili za konferencję. Należy posłużyć się relacją

    Aliasy u (uczestnicy) i w (wykłady), JOIN ... ON w.id = u.wyklady_id - relacja: klucz obcy uczestnika wskazuje wykład. Wynik: 2 wiersze - Nowak i Rutkowski z nazwami wykładów i e-mailami. Zrzut: kw3.jpg.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT imie, nazwisko, koszt
    FROM uczestnicy
    WHERE zaplacono = 0;
    
    -- Zapytanie 2
    SELECT AVG(koszt) AS `Średni koszt`,
           SUM(koszt) AS `Całkowity koszt`,
           COUNT(*) AS `Liczba uczestników`
    FROM uczestnicy;
    
    -- Zapytanie 3
    SELECT w.nazwa, u.nazwisko, u.email
    FROM uczestnicy AS u
    JOIN wyklady AS w ON w.id = u.wyklady_id
    WHERE u.zaplacono = 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: usunięcie kolumny haslo

    Kryteria:

    R.1.6 Wykonano zapytanie 4 usuwające kolumnę z hasłem uczestnika. W pliku z kwerendami lub na zrzucie istnieje zapis np.: ALTER TABLE uczestnicy DROP COLUMN haslo; (COLUMN jest opcjonalne) oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie lub struktura tabeli uczestnicy bez kolumny haslo

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: usuwające kolumnę z hasłem uczestnika

    ALTER TABLE ... DROP COLUMN zmienia strukturę tabeli: kolumna znika razem z zawartością. Hasła nie powinny zresztą leżeć w bazie jawnym tekstem - w prawdziwej aplikacji zapisuje się tylko ich skrót (np. password_hash() w PHP). Zrzut kw4.jpg: komunikat o wykonaniu albo struktura tabeli bez haslo.

    Typowe błędy

    DELETE FROM uczestnicy usuwa wiersze (uczestników), a nie kolumnę.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, nazwisko, koszt
    FROM uczestnicy
    WHERE zaplacono = 0;
    
    -- Zapytanie 2
    SELECT AVG(koszt) AS `Średni koszt`,
           SUM(koszt) AS `Całkowity koszt`,
           COUNT(*) AS `Liczba uczestników`
    FROM uczestnicy;
    
    -- Zapytanie 3
    SELECT w.nazwa, u.nazwisko, u.email
    FROM uczestnicy AS u
    JOIN wyklady AS w ON w.id = u.wyklady_id
    WHERE u.zaplacono = 1;
    
    -- Zapytanie 4
    ALTER TABLE uczestnicy
    DROP COLUMN haslo;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-21 · po tym etapie masz 20 z 39 kryteriów (pkt)

    Krok 8: tulipany.jpg: rozmycie Gaussa 3,5 px

    Kryteria:

    R.2.1 Plik tulipany.jpg jest rozmyty w takim stopniu że można rozpoznać kwiaty na obrazie. Czynność rozmycia udokumentowano zrzutem na którym jest widoczne okno filtra rozmycie

    ok. 3 min
    Polecenie z arkusza

    Na grafice tulipany.jpg należy zastosować filtr rozmycia Gaussa. Rozmycie ma być niewielkie, tak aby można było dalej rozpoznać kwiaty na obrazie. Dla grafiki na obrazie 2 zastosowano rozmiar rozmycia 3,5 w obu osiach. Należy wykonać zrzut ekranu potwierdzający zastosowanie filtru i nazwać go rozmycie.png. Na zrzucie ma być widoczne okno dialogowe służące do podania parametrów rozmycia.

    W GIMP-ie Filtry → Rozmycie → Rozmycie Gaussa, rozmiar X i Y po 3,5. Przy otwartym oknie filtru zrzut ekranu jako rozmycie.png - okno z parametrami musi być widoczne. Potem OK i Plik → Nadpisz tulipany.jpg. Grafika ma 1343 × 500 px - wysokość równa wysokości bloku głównego. Podgląd: wycinek przed i po rozmyciu.

    Typowe błędy

    Zrzut zrobiony po zamknięciu okna filtru nie dokumentuje parametrów - klucz wymaga widocznego okna rozmycia.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik rejestracja.html: HTML5, język, kodowanie

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie rejestracja.html zapisanej w języku HTML5. Ustawiony język zawartości strony na polski. Jawnie zastosowany właściwy standard kodowania polskich znaków

    Plik rejestracja.html (bez PHP - otwiera się wprost z dysku): <!DOCTYPE html>, <html lang="pl">, <meta charset="UTF-8"> jako pierwszy element <head> i <body> (R.2.2).

    rejestracja.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  10. Krok 10: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł stronie: Rejestracja

    ok. 1 min
    Polecenie z arkusza

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

    <title> (R.2.3) i viewport, żeby telefon nie pomniejszał strony.

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

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    <link> do styl.css - całe formatowanie z tego pliku, bez atrybutów style w HTML-u (R.3.6).

    Typowe błędy

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

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  12. Krok 12: Bloki: baner, blok główny, cztery bloki stopki

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Baner <header>, blok główny <main> i cztery <footer> (klucz R.2.4: „stopki - footer”). <footer> może wystąpić kilka razy - w odróżnieniu od <main>, który na stronie jest jeden. Wszystkie stopki wyglądają tak samo, więc obsłuży je jeden selektor.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <main>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  13. Krok 13: Baner: nagłówek z uwypukloną nazwą

    Kryteria:

    R.2.10 Fraza „Nasze Kwiaty” jest zapisana w znaczniku semantycznym <em>

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Formularz rejestracyjny konferencji Nasze Kwiaty”. Fraza „Nasze Kwiaty” jest zapisana w znaczniku semantycznym, który jest pochylony i oznacza tekst uwypuklony

    Uwypuklenie to <em> - przeglądarka pisze je kursywą (R.2.10). <i> daje tę samą kursywę, ale nic nie znaczy.

    Typowe błędy

    <i>Nasze Kwiaty</i> wygląda tak samo, ale klucz wymaga <em>.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  14. Krok 14: Blok główny: formularz

    Kryteria:

    R.2.6 W bloku głównym umieszczono formularz, zastosowano znacznik <form>

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku głównego: formularz złożony z trzech bloków, które zawierają kolejno:

    <form> obejmuje wszystkie karty (R.2.6). Danych nigdzie się nie wysyła - obsługuje je skrypt - więc formularz nie ma action ani method.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
            </form>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  15. Krok 15: Blok 1: karta z danymi osobowymi

    ok. 3 min
    Polecenie z arkusza

    Blok 1: Nagłówek drugiego stopnia o treści „Dane osobowe”. Pole edycyjne z podpowiedzią „Wpisz imię...”, pole jest wymagane. Pole edycyjne z podpowiedzią „Wpisz nazwisko...”, pole jest wymagane

    • karta to <fieldset> - znacznik grupy pól formularza (<div> niczego nie mówi o treści); klasa card daje wspólny wygląd, a active oznacza kartę widoczną - przy starcie pierwszą,
    • placeholder - podpowiedź w polu, required - pole wymagane,
    • aria-label - podpowiedź znika po wpisaniu pierwszej litery i nie zastępuje etykiety; czytnik ekranu przeczyta „Imię”, choć na stronie (zgodnie z obrazem 2) nie ma widocznego napisu przy polu,
    • autocomplete="given-name" i family-name - przeglądarka podpowie zapisane imię i nazwisko.
    rejestracja.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                </fieldset>
            </form>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  16. Krok 16: Blok 1: przycisk „Następna karta”

    ok. 2 min
    Polecenie z arkusza

    Przycisk o treści „Następna karta”, którego kliknięcie powoduje wywołanie funkcji skryptu

    • type="button" - przycisk w <form> bez typu jest submit i przeładowałby stronę,
    • data-next="contact" - własny atrybut danych z identyfikatorem karty, która ma się pokazać. Skrypt odczyta go jako button.dataset.next, więc jedna funkcja obsłuży oba przyciski „Następna karta” - wiadomość „dokąd dalej” stoi w HTML-u przy przycisku.

    Funkcję przypisze skrypt w etapie JavaScript.

    Typowe błędy

    <button> bez type="button" w formularzu przeładowuje stronę - karta 2 mignie i zniknie.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
            </form>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  17. Krok 17: Blok 2: dane kontaktowe

    ok. 2 min
    Polecenie z arkusza

    Blok 2: Nagłówek drugiego stopnia o treści „Dane kontaktowe”. Pole edycyjne z podpowiedzią „Twój e-mail...”, pole typu dedykowanego do wpisania adresu e-mail. Pole edycyjne z podpowiedzią „Twój numer telefonu...”, pole typu dedykowanego do wpisania telefonu. Przycisk o treści „Następna karta”, którego kliknięcie powoduje wywołanie funkcji skryptu

    Druga karta (bez klasy active, czyli ukryta): pole type="email" (przeglądarka sprawdza budowę adresu, telefon pokazuje klawiaturę z „@”) i type="tel" (format numeru nie jest sprawdzany, ale telefon otwiera klawiaturę numeryczną). Przycisk prowadzi do karty login.

    rejestracja.html HTML zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
            </form>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  18. Krok 18: Blok 3: hasło, powtórzenie i „Zatwierdź”

    Kryteria: , ,

    R.2.7 Na stronie zdefiniowano 6 pól edycyjnych i trzy przyciski

    R.3.2 W bloku głównym zdefiniowano trzy bloki (mogą być widoczne wszystkie trzy, lub tylko jeden, lub żaden)

    R.3.3 Przynajmniej jedna kontrolka ma podpowiedź (placeholder), kontrolki do wpisania imienia i nazwiska są wymagane (required), kontrolka do wpisania maila jest typu email, do wpisania telefonu typu tel i obie do wpisania hasła typu password

    ok. 3 min
    Polecenie z arkusza

    Blok 3: Nagłówek drugiego stopnia o treści „Hasło do logowania”. Pole edycyjne z podpowiedzią „Podaj hasło”, pole ukrywa wpisywane hasło. Pole edycyjne z podpowiedzią „Powtórz hasło”, pole ukrywa wpisywane hasło. Przycisk o treści „Zatwierdź”, którego kliknięcie powoduje wywołanie funkcji skryptu

    Dwa pola type="password" - zamiast znaków kropki. autocomplete="new-password" mówi przeglądarce, że to nowe hasło: zaproponuje wygenerowanie silnego, zamiast wpisywać zapamiętane.

    „Zatwierdź” to też type="button", choć kusi submit: formularz z polami wymaganymi w ukrytych kartach nie dałby się wysłać - przeglądarka chce pokazać dymek przy pustym polu, nie może skupić ukrytego pola i po cichu przerywa wysyłanie. Wtedy nie pojawiłby się ani komunikat o hasłach, ani powitanie.

    Formularz ma trzy bloki (R.3.2), sześć pól i trzy przyciski (R.2.7); podpowiedzi, pola wymagane i typy email, tel, password to R.3.3.

    rejestracja.html HTML zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  19. Krok 19: Stopka 1: film z kontrolkami

    Kryteria:

    R.2.8 W pierwszym bloku stopki umieszczono video motyl.mp4 z widocznymi kontrolkami

    ok. 1 min
    Polecenie z arkusza

    Zawartość pierwszego bloku stopki: Film motyl.mp4, z kontrolkami umożliwiającymi sterowanie filmem. W przypadku problemów z odtworzeniem filmu pojawia się tekst: „Przeglądarka nie obsługuje tego formatu”

    <video> z atrybutem controls (odtwarzanie, pasek postępu, głośność). Tekst w środku znacznika wyświetli tylko przeglądarka, która filmu nie odtworzy (R.2.8).

    Typowe błędy

    <video> bez controls - filmu nie da się uruchomić, a R.2.8 wymaga widocznych kontrolek.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  20. Krok 20: Stopka 2: plan konferencji

    Kryteria:

    R.2.9 W drugim bloku stopki umieszczono tabelę z dwiema kolumnami i dwoma wierszami, zastosowano znaczniki <table>, <tr>, <td>

    ok. 2 min
    Polecenie z arkusza

    Zawartość drugiego bloku stopki: Nagłówek trzeciego stopnia o treści: „Plan konferencji”. Tabela o dwóch wierszach i dwóch kolumnach. Dane to tabeli przedstawiono w Tabeli 1

    <h3> i tabela: dwa wiersze <tr>, po dwie komórki <td> (R.2.9). Godziny w znaczniku <time> - tekst się nie zmienia, ale przeglądarka, wyszukiwarka czy kalendarz rozpoznają w nim godzinę.

    rejestracja.html HTML zmienione: 11 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
            <h3>Plan konferencji</h3>
            <table>
                <tr>
                    <td><time>9:00</time> - <time>12:00</time></td>
                    <td>Pielęgnacja roślin</td>
                </tr>
                <tr>
                    <td><time>13:00</time> - <time>15:00</time></td>
                    <td>Targi kwiatowe</td>
                </tr>
            </table>
        </footer>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  21. Krok 21: Stopki 3 i 4: odnośnik i autor

    Kryteria: ,

    R.2.5 W bloku banera zapisano nagłówek h1 "Formularz rejestracyjny konferencji Nasze Kwiaty" , w bloku głównym przynajmniej jeden h2 z: "Dane osobowe", "Dane kontaktowe" lub "Hasło do logowania" , w drugim bloku stopki h3 "Plan konferencji" oraz paragrafy w trzecim i czwartym bloku stopki

    R.3.4 Na stronie umieszczono odnośnik którego kliknięcie inicjuje otwarcie strony https://kwiaty.pl/

    ok. 2 min
    Polecenie z arkusza

    Zawartość trzeciego bloku stopki: paragraf (akapit) z odnośnikiem do adresu https://kwiaty.pl/ o treści „Internetowa kwiaciarnia”. Zawartość czwartego bloku stopki: paragraf o treści: „Formularz wykonał: ”, dalej wstawiony numer zdającego.

    Odnośnik z https:// w akapicie (R.3.4). Na egzaminie po „Formularz wykonał:” wpisujesz swój numer zdającego (PESEL); tu stoi autor rozwiązania, Bartosz Bryniarski. Komplet nagłówków i akapitów z R.2.5.

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
            <h3>Plan konferencji</h3>
            <table>
                <tr>
                    <td><time>9:00</time> - <time>12:00</time></td>
                    <td>Pielęgnacja roślin</td>
                </tr>
                <tr>
                    <td><time>13:00</time> - <time>15:00</time></td>
                    <td>Targi kwiatowe</td>
                </tr>
            </table>
        </footer>
        <footer>
            <p><a href="https://kwiaty.pl/">Internetowa kwiaciarnia</a></p>
        </footer>
        <footer>
            <p>Formularz wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  22. Etap 3: Styl CSS

    Kroki 22-30 · po tym etapie masz 31 z 39 kryteriów (pkt)

    Krok 22: Plik styl.css: zmienne i krój Cambria

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (dla *): krój czcionki Cambria

    ok. 2 min
    Polecenie z arkusza

    Domyślne formatowanie wszystkich selektorów: krój czcionki Cambria

    Kolor #C2185B występuje w banerze, stopkach i przyciskach - zapisany raz jako zmienna --accent (zapis #c2185b z arkusza to ten sam kolor; wielkość liter w zapisie szesnastkowym nie ma znaczenia). Selektor * z Cambrią i zapasowym krojem szeryfowym (R.4.1) - krój dostają też pola i przyciski.

    styl.css CSS nowy plik
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  23. Krok 23: Układ strony na siatce

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu egzaminacyjnym, nie należy brać pod uwagę zawartości bloku głównego (prawidłowo zastosowano właściwości CSS decydujące o układzie strony, np. float i clear albo display flex albo grid)

    ok. 3 min
    Polecenie z arkusza

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

    <body> to siatka o czterech kolumnach po 25% - to szerokość bloków stopki z arkusza (klucz R.4.5 przyjmuje grid-template-columns). Baner i blok główny dostają grid-column: 1 / -1 - od pierwszej do ostatniej linii siatki, czyli całą szerokość; -1 znaczy „ostatnia linia”, więc zapis działa przy każdej liczbie kolumn. Cztery stopki same zajmują kolejne pola w czwartym rzędzie (R.3.1).

    W wersji z float stopki nie mogą mieć marginesu ani ramki, bo czwarta spadłaby do nowego wiersza. W siatce każda ma swoje pole.

    styl.css CSS zmienione: 10 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  24. Krok 24: Baner i blok główny

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Dla banera: kolor tła #C2185B, biały kolor czcionki, wyrównanie tekstu do środka, marginesy wewnętrzne 15 px. Dla bloku głównego: tło stanowi obraz tulipany.jpg, wysokość 500 px

    Baner z kolorem ze zmiennej i padding: 15px (R.4.6). Tło bloku głównego: background-image: url("tulipany.jpg") - ścieżka liczona od pliku CSS. Obraz ma 500 px wysokości, tyle co blok; w szerokości powtarza się, stąd szew po prawej, jak na obrazie 2.

    styl.css CSS zmienione: 12 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  25. Krok 25: Bloki stopki: kolory i wysokość

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla wszystkich bloków stopki: kolor tła #C2185B, biały kolor czcionki, szerokość 25%, wysokość 240 px

    Jeden selektor dla czterech stopek. Szerokość 25% dają kolumny siatki - width: 25% liczyłby się od kolumny i zwęził stopkę do 1/16 strony.

    Typowe błędy

    Procentowa szerokość elementu siatki liczy się od jego pola, nie od strony - szerokości stopek zostają w grid-template-columns.

    styl.css CSS zmienione: 6 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  26. Krok 26: Karty formularza obok siebie: kontener flex

    Kryteria:

    R.4.8 Ustawiono styl dla przynajmniej jednego bloku w formularzu: kolor tła #FCE4EC, szerokość 25%, wysokość 300px, marginesy zewnętrzne 25px, wewnętrzne 16px

    ok. 3 min
    Polecenie z arkusza

    Wspólne dla trzech bloków w formularzu: bloki umieszczone obok siebie, kolor tła #FCE4EC, szerokość 25%, wysokość 300 px, marginesy zewnętrzne 25 px, wewnętrzne 16 px

    • form { display: flex; } ustawia karty obok siebie. Szerokość 25% z klasy .card liczy się od formularza, czyli od bloku głównego - tak jak w arkuszu (R.4.8),
    • w wersji z float trzy karty mieszczą się w wierszu dopiero od ok. 1000 px szerokości okna, a w węższym trzecia spada niżej i wystaje z bloku głównego. W kontenerze flex karty, które się nie mieszczą, zwężają się i zostają w jednym rzędzie,
    • border: none zdejmuje ramkę, którą <fieldset> ma domyślnie - na obrazie 2 karty jej nie mają.

    Siatka (grid) nie pasowałaby tu tak dobrze: width: 25% liczyłby się od kolumny siatki, a nie od bloku.

    styl.css CSS zmienione: 13 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    
    form {
        display: flex;
    }
    
    .card {
        width: 25%;
        height: 300px;
        margin: 25px;
        padding: 16px;
        border: none;
        background-color: var(--card-bg);
    }
    Podgląd strony po tym kroku (rejestracja.html)
  27. Krok 27: Widoczna tylko karta aktywna

    Kryteria:

    R.4.9 Ustawiono dla drugiego i trzeciego bloku cechę visibility: hidden;

    ok. 2 min
    Polecenie z arkusza

    Dodatkowo pierwszy blok jest widoczny, pozostałe dwa są ukryte. Należy zastosować właściwość CSS, która jedynie ukrywa blok, a nie usuwa go

    „Jedynie ukrywa” to visibility: hidden - karta jest niewidoczna, ale zajmuje swoje miejsce; dlatego druga karta pojawi się na środku, a trzecia po prawej, jak na obrazach 3 i 4. display: none usunąłby kartę z układu.

    Stan karty siedzi w klasie active: każda karta jest ukryta, a widoczna jest tylko ta z klasą active - przy starcie pierwsza, więc druga i trzecia mają visibility: hidden (R.4.9). Skrypt nie będzie zmieniał stylów; przełoży tylko klasę z karty na kartę, a wygląd zostaje w arkuszu stylów.

    styl.css CSS zmienione: 8 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    
    form {
        display: flex;
    }
    
    .card {
        width: 25%;
        height: 300px;
        margin: 25px;
        padding: 16px;
        border: none;
        background-color: var(--card-bg);
    }
    
    .card {
        visibility: hidden;
    }
    
    .card.active {
        visibility: visible;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  28. Krok 28: Akapity i odnośnik

    ok. 1 min
    Polecenie z arkusza

    Dla selektora paragrafu: margines wewnętrzny górny 20 px. Dla odnośnika: biały kolor czcionki

    Selektor znacznika p (uwaga arkusza) z padding-top: 20px; biały odnośnik - niebieski byłby słabo widoczny na tle #C2185B.

    styl.css CSS zmienione: 8 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    
    form {
        display: flex;
    }
    
    .card {
        width: 25%;
        height: 300px;
        margin: 25px;
        padding: 16px;
        border: none;
        background-color: var(--card-bg);
    }
    
    .card {
        visibility: hidden;
    }
    
    .card.active {
        visibility: visible;
    }
    
    p {
        padding-top: 20px;
    }
    
    a {
        color: var(--light-text);
    }
    Podgląd strony po tym kroku (rejestracja.html)
  29. Krok 29: Pola edycyjne i przyciski

    Kryteria: , , ,

    R.4.2 Ustawiono kolor tła #C2185B dla bloków banera, wszystkich bloków stopki i przycisków oraz blok główny ma tło w postaci obrazu tulipany.jpg (formatowanie przycisku za pomocą id jest błędem)

    R.4.3 Ustawiono biały kolor czcionki dla banera, wszystkich bloków stopki, odnośnika i przycisków

    R.4.7 Ustawiono marginesy wewnętrzne (padding) 15px dla banera, 20px dla przycisków, górny 20px dla selektora p oraz zewnętrzne (margin) 10px dla przynajmniej jednego pola edycyjnego, górny 50px i lewy 60% dla przycisków

    R.4.10 Ustawiono brak obramowania dla przycisków

    ok. 2 min
    Polecenie z arkusza

    Dla wszystkich pól edycyjnych oprócz przycisków: szerokość 80%, wysokość 30 px, marginesy zewnętrzne 10 px. Dla wszystkich przycisków: kolor tła #c2185b, biały kolor czcionki, margines zewnętrzny górny 50 px, margines zewnętrzny lewy 60%, marginesy wewnętrzne 20 px, brak obramowania

    Przyciski to <button>, pola - <input>, więc selektor input spełnia „oprócz przycisków”. Przyciski formatuje selektor znacznika button (klucz przy R.4.2: id byłby błędem): margin-left: 60% liczy się od szerokości karty, border: none zdejmuje ramkę (R.4.10).

    Komplet kryteriów: tła #C2185B i obraz w bloku głównym (R.4.2), biały tekst banera, stopek, odnośnika i przycisków (R.4.3), marginesy wewnętrzne i zewnętrzne (R.4.7).

    styl.css CSS zmienione: 15 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    
    form {
        display: flex;
    }
    
    .card {
        width: 25%;
        height: 300px;
        margin: 25px;
        padding: 16px;
        border: none;
        background-color: var(--card-bg);
    }
    
    .card {
        visibility: hidden;
    }
    
    .card.active {
        visibility: visible;
    }
    
    p {
        padding-top: 20px;
    }
    
    a {
        color: var(--light-text);
    }
    
    input {
        width: 80%;
        height: 30px;
        margin: 10px;
    }
    
    button {
        margin-top: 50px;
        margin-left: 60%;
        padding: 20px;
        border: none;
        background-color: var(--accent);
        color: var(--light-text);
    }
    Podgląd strony po tym kroku (rejestracja.html)
  30. Krok 30: Film na cały blok stopki

    Kryteria: ,

    R.4.4 Ustawiono wysokość bloku głównego 500px, wszystkich stopek 240px, przynajmniej jednego pola edycyjnego 30px oraz video 100%

    R.4.5 Ustawiono szerokość wszystkich bloków stopki 25% (width lub grid-template-columns lub flex), przynajmniej jednego pola edycyjnego 80% oraz video 100%

    ok. 1 min
    Polecenie z arkusza

    Dla video: szerokość i wysokość 100%

    Film wypełnia pierwszą stopkę; przeglądarka zachowuje proporcje filmu (16:9), więc nad nim i pod nim zostają przezroczyste pasy, przez które widać tło stopki. Komplet wysokości (R.4.4) i szerokości (R.4.5).

    styl.css CSS zmienione: 5 linii
    :root {
        --accent: #C2185B;
        --card-bg: #FCE4EC;
        --light-text: white;
    }
    
    * {
        font-family: Cambria, serif;
    }
    
    body {
        display: grid;
        grid-template-columns: repeat(4, 25%);
    }
    
    header,
    main {
        grid-column: 1 / -1;
    }
    
    header {
        background-color: var(--accent);
        color: var(--light-text);
        text-align: center;
        padding: 15px;
    }
    
    main {
        background-image: url("tulipany.jpg");
        height: 500px;
    }
    
    footer {
        background-color: var(--accent);
        color: var(--light-text);
        height: 240px;
    }
    
    form {
        display: flex;
    }
    
    .card {
        width: 25%;
        height: 300px;
        margin: 25px;
        padding: 16px;
        border: none;
        background-color: var(--card-bg);
    }
    
    .card {
        visibility: hidden;
    }
    
    .card.active {
        visibility: visible;
    }
    
    p {
        padding-top: 20px;
    }
    
    a {
        color: var(--light-text);
    }
    
    input {
        width: 80%;
        height: 30px;
        margin: 10px;
    }
    
    button {
        margin-top: 50px;
        margin-left: 60%;
        padding: 20px;
        border: none;
        background-color: var(--accent);
        color: var(--light-text);
    }
    
    video {
        width: 100%;
        height: 100%;
    }
    Podgląd strony po tym kroku (rejestracja.html)
  31. Etap 4: JavaScript

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

    Krok 31: Skrypt w pliku strony: jedna funkcja dla obu przycisków „Następna karta”

    Kryteria: , , ,

    R.3.5 Dla dowolnego przycisku zdefiniowano zdarzenie związane z jego kliknięciem , które odwołuje się do funkcji w skrypcie (atrybut onClick lub słuchacz zdarzenia click lub właściwość onclick obiektu DOM)

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

    R.5.2 Po wciśnięciu przycisku w pierwszym bloku, jest ukrywany blok 1, blok 2 staje się widoczny

    R.5.3 Po wciśnięciu przycisku w drugim bloku, jest ukrywany blok 2, blok 3 staje się widoczny

    ok. 4 min
    Polecenie z arkusza

    Działanie funkcji dla kliknięcia przycisku z pierwszego bloku (obraz 3): Ukrywany jest blok 1. Blok 2 staje się widoczny. Działanie funkcji dla kliknięcia przycisku z drugiego bloku (obraz 4): Ukrywany jest blok 2. Blok 3 staje się widoczny

    Skrypt stoi w znaczniku <script> na końcu <body> pliku rejestracja.html. Klucz każe sprawdzać R.5.1, R.5.4 i R.5.7 „w kodzie strony”, więc kod jest tam, gdzie egzaminator będzie go szukał. Przeglądarka wykonuje skrypt dopiero po przeczytaniu całego HTML-u nad nim, więc karty i przyciski już istnieją.

    • na górze const z polami formularza - wyszukane raz, przydadzą się przy zatwierdzaniu (R.5.4 - getElementById),
    • showCard(currentCard, nextCard) zdejmuje klasę active z bieżącej karty i dodaje ją następnej - widoczność zmienia arkusz stylów,
    • pętla po przyciskach z atrybutem data-next dodaje addEventListener("click", ...) (R.3.5): bieżącą kartę znajduje closest(".card") (najbliższy przodek z tą klasą), następną - identyfikator z button.dataset.next.

    Obsługa obu przycisków to ten sam kod (R.5.1). W podglądzie „Następna karta” działa: karta 2 pojawia się na środku (obraz 3, R.5.2), potem karta 3 po prawej (obraz 4, R.5.3).

    Typowe błędy

    Ten sam kod w <head> bez defer nie zadziała: wykona się, zanim przeglądarka utworzy pola i przyciski, a getElementById zwróci null.

    rejestracja.html HTML zmienione: 17 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
            <h3>Plan konferencji</h3>
            <table>
                <tr>
                    <td><time>9:00</time> - <time>12:00</time></td>
                    <td>Pielęgnacja roślin</td>
                </tr>
                <tr>
                    <td><time>13:00</time> - <time>15:00</time></td>
                    <td>Targi kwiatowe</td>
                </tr>
            </table>
        </footer>
        <footer>
            <p><a href="https://kwiaty.pl/">Internetowa kwiaciarnia</a></p>
        </footer>
        <footer>
            <p>Formularz wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const firstNameInput = document.getElementById("firstName");
            const lastNameInput = document.getElementById("lastName");
            const passwordInput = document.getElementById("password");
            const repeatPasswordInput = document.getElementById("repeatPassword");
    
            function showCard(currentCard, nextCard) {
                currentCard.classList.remove("active");
                nextCard.classList.add("active");
            }
    
            for (const button of document.querySelectorAll("[data-next]")) {
                button.addEventListener("click", () => {
                    showCard(button.closest(".card"), document.getElementById(button.dataset.next));
                });
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  32. Krok 32: Zatwierdzenie: porównanie haseł

    Kryteria:

    R.5.5 Po wciśnięciu przycisku w trzecim oknie, w przypadku, gdy wpisane do pól edycyjnych hasła nie są identyczne, wyświetlane jest okienko popup z komunikatem „Podane hasła różnią się”, w przeciwnym wypadku okienko nie jest wyświetlane

    ok. 2 min
    Polecenie z arkusza

    Działanie funkcji dla kliknięcia przycisku z trzeciego bloku: W przypadku, gdy wpisane do pól edycyjnych hasła nie są identyczne wyświetlane jest okienko popup z komunikatem „Podane hasła różnią się” (obraz 5)

    Porównanie !== - ścisłe, bez zamiany typów (wartości pól to zawsze napisy, ale nawyk === / !== chroni przed niespodziankami w innych miejscach). Przy różnych hasłach alert pokazuje okienko (obraz 5), przy zgodnych - nic (R.5.5). Funkcję przypina nasłuchiwacz na przycisku confirm.

    rejestracja.html HTML zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
            <h3>Plan konferencji</h3>
            <table>
                <tr>
                    <td><time>9:00</time> - <time>12:00</time></td>
                    <td>Pielęgnacja roślin</td>
                </tr>
                <tr>
                    <td><time>13:00</time> - <time>15:00</time></td>
                    <td>Targi kwiatowe</td>
                </tr>
            </table>
        </footer>
        <footer>
            <p><a href="https://kwiaty.pl/">Internetowa kwiaciarnia</a></p>
        </footer>
        <footer>
            <p>Formularz wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const firstNameInput = document.getElementById("firstName");
            const lastNameInput = document.getElementById("lastName");
            const passwordInput = document.getElementById("password");
            const repeatPasswordInput = document.getElementById("repeatPassword");
    
            function showCard(currentCard, nextCard) {
                currentCard.classList.remove("active");
                nextCard.classList.add("active");
            }
    
            for (const button of document.querySelectorAll("[data-next]")) {
                button.addEventListener("click", () => {
                    showCard(button.closest(".card"), document.getElementById(button.dataset.next));
                });
            }
    
            function confirmRegistration() {
                if (passwordInput.value !== repeatPasswordInput.value) {
                    alert("Podane hasła różnią się");
                }
            }
    
            document.getElementById("confirm").addEventListener("click", confirmRegistration);
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  33. Krok 33: Zatwierdzenie: powitanie w konsoli

    Kryteria: , ,

    R.5.4 Oba hasła oraz imię i nazwisko pobrano za pomocą odpowiedniej funkcji obiektu document (np. getElementById)

    R.5.6 Po wciśnięciu przycisku w trzecim oknie, wyświetlany jest w konsoli komunikat o treści: „Witaj <imie> <nazwisko>”, gdzie wartości w nawiasach są pobrane z pól edycyjnych

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

    ok. 2 min
    Polecenie z arkusza

    Imię i nazwisko wpisane w pierwszym bloku są pobrane i wyświetlone w konsoli jako napis o treści „Witaj <imie> <nazwisko>”, gdzie wartości w nawiasach są pobrane z pól edycyjnych (obraz 6)

    Szablon tekstowy w odwrotnych apostrofach: wartości wchodzą w ${...}, a spacje stoją tam, gdzie w gotowym napisie - łatwiej o poprawny tekst niż przy sklejaniu +. console.log wypisuje go w konsoli narzędzi deweloperskich (F12), jak na obrazie 6: „Witaj Alicja Kowalska” (R.5.6). Pola z karty 1 są tylko ukryte, więc ich wartości nadal są dostępne.

    Arkusz nie uzależnia powitania od haseł, więc pojawia się zawsze - tak też je ocenia klucz. Nazwy funkcji i stałych mówią, co robią i co przechowują (R.5.7).

    rejestracja.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>Rejestracja</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Formularz rejestracyjny konferencji <em>Nasze Kwiaty</em></h1>
        </header>
        <main>
            <form>
                <fieldset class="card active" id="personal">
                    <h2>Dane osobowe</h2>
                    <input type="text" id="firstName" placeholder="Wpisz imię..." aria-label="Imię" autocomplete="given-name" required>
                    <input type="text" id="lastName" placeholder="Wpisz nazwisko..." aria-label="Nazwisko" autocomplete="family-name" required>
                    <button type="button" data-next="contact">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="contact">
                    <h2>Dane kontaktowe</h2>
                    <input type="email" id="email" placeholder="Twój e-mail..." aria-label="E-mail" autocomplete="email">
                    <input type="tel" id="phone" placeholder="Twój numer telefonu..." aria-label="Numer telefonu" autocomplete="tel">
                    <button type="button" data-next="login">Następna karta</button>
                </fieldset>
                <fieldset class="card" id="login">
                    <h2>Hasło do logowania</h2>
                    <input type="password" id="password" placeholder="Podaj hasło" aria-label="Hasło" autocomplete="new-password">
                    <input type="password" id="repeatPassword" placeholder="Powtórz hasło" aria-label="Powtórzenie hasła" autocomplete="new-password">
                    <button type="button" id="confirm">Zatwierdź</button>
                </fieldset>
            </form>
        </main>
        <footer>
            <video src="motyl.mp4" controls>Przeglądarka nie obsługuje tego formatu</video>
        </footer>
        <footer>
            <h3>Plan konferencji</h3>
            <table>
                <tr>
                    <td><time>9:00</time> - <time>12:00</time></td>
                    <td>Pielęgnacja roślin</td>
                </tr>
                <tr>
                    <td><time>13:00</time> - <time>15:00</time></td>
                    <td>Targi kwiatowe</td>
                </tr>
            </table>
        </footer>
        <footer>
            <p><a href="https://kwiaty.pl/">Internetowa kwiaciarnia</a></p>
        </footer>
        <footer>
            <p>Formularz wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const firstNameInput = document.getElementById("firstName");
            const lastNameInput = document.getElementById("lastName");
            const passwordInput = document.getElementById("password");
            const repeatPasswordInput = document.getElementById("repeatPassword");
    
            function showCard(currentCard, nextCard) {
                currentCard.classList.remove("active");
                nextCard.classList.add("active");
            }
    
            for (const button of document.querySelectorAll("[data-next]")) {
                button.addEventListener("click", () => {
                    showCard(button.closest(".card"), document.getElementById(button.dataset.next));
                });
            }
    
            function confirmRegistration() {
                if (passwordInput.value !== repeatPasswordInput.value) {
                    alert("Podane hasła różnią się");
                }
                console.log(`Witaj ${firstNameInput.value} ${lastNameInput.value}`);
            }
    
            document.getElementById("confirm").addEventListener("click", confirmRegistration);
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (rejestracja.html)
  34. Etap 5: Porównanie z wersją podstawową

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

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

    ok. 2 min

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

    wersja podstawowawersja nowoczesna
    układ stronyfloat: left stopek, width: 25%siatka repeat(4, 25%), grid-column: 1 / -1
    karty w rzędziefloat: left - w wąskim oknie trzecia spadadisplay: flex - w wąskim oknie karty się zwężają
    karta<div class="card"><fieldset class="card">, aria-label, autocomplete
    ukrywanie kart#contact, #login { visibility: hidden } + style.visibility w skrypcie.card ukryta, .card.active widoczna, skrypt przekłada klasę
    skrypt<script> w HTML-u, onclick w przyciskach, dwie funkcje kart<script> na końcu <body>, addEventListener, jedna funkcja i data-next
    napisysklejanie +szablon tekstowy `Witaj ${...}`

    Na egzaminie wersja podstawowa trzyma się tabeli 2 arkusza (getElementById, onclick, element.style) i jest szybsza do napisania. Nowoczesna rozdziela role plików - HTML opisuje treść, CSS wygląd (także stan „aktywna karta”), a skrypt tylko zachowanie - i trzeci przycisk „Następna karta” byłby w niej jednym atrybutem data-next. Poza egzaminem taki skrypt zwykle wydziela się do osobnego pliku .js dołączonego z defer - tu zostaje w rejestracja.html, bo klucz sprawdza go „w kodzie strony”. Sprawdzania pól wymaganych przed przejściem dalej (jak w dobrych praktykach wersji podstawowej) celowo tu nie ma: egzaminator klika „Następna karta” na pustym formularzu i karta musi się przełączyć (R.5.2).

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

  35. Etap 6: Oddanie pracy

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

    Krok 35: 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 nazwa przeglądarki, w której była sprawdzana strona. W folderze z numerem zdającego: import.png, kw1.jpg - kw4.jpg, kwerendy.txt, motyl.mp4, przeglądarka.txt, rejestracja.html, rozmycie.png, styl.css, tulipany.jpg (rozmyty). 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 33.

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.