INF.03-01-25.01-SGStyczeń 2025 · 48 kroków · ok. 94 min · 40 kryteriów z klucza
Rozwiązanie krok po kroku: Witryna firmy szkoleniowej (Nowoczesny kod (grid, osobny skrypt))
To drugi sposób rozwiązania tego samego arkusza: baza obuwie z czterema zapytaniami, baner wycięty ze zdjęcia klawiatury, strony index.html z tabelą kursów i raty.html z kalkulatorem rat oraz style w style.css. Obie wersje spełniają wszystkie 40 kryteriów klucza - różni je sposób pisania kodu, nie wynik.
Czym ta wersja różni się od podstawowej:
kolory z arkusza w zmiennych CSS (--color-dark, --color-light) - każdy kolor jest wpisany raz,
tabela z częścią nagłówkową <thead> i treścią <tbody>, odnośniki menu reagują także na klawiaturę (:focus-visible) i nie przesuwają się, gdy pojawia się ramka,
kalkulator ułożony siatką CSS (display: grid) zamiast znaczników <br>, pola wyboru razem z etykietami w znaczniku <label>,
skrypt w osobnym pliku raty.js dołączonym z defer, podpięty przez addEventListener - w HTML nie ma onclick,
ceny kursów w obiekcie zamiast osobnych warunków, sprawdzenie liczby rat i zaznaczonych kursów od pierwszej linii oraz kwoty w polskim formacie (2666,67 zamiast 2666.6666666666665).
Kroki nadal idą zdanie po zdaniu za treścią arkusza. Baza i zdjęcie pochodzą z prawdziwego archiwum pliki10, zapytania są sprawdzone na MariaDB, a kalkulator w podglądzie działa naprawdę - skrypt jest też sprawdzony w prawdziwej przeglądarce Chrome (oba kursy, jeden kurs, żaden, puste i ujemne pole liczby rat).
Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 40 kryteriów (pkt)
Krok 1: Baza danych obuwie
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie obuwie, z zestawem polskich znaków (np. utf8_unicode_ci).
Archiwum pliki10.7z ma hasło KuRsyKompuTerow3& (z ampersandem na końcu); zawiera baza.sql i klawiatura.jpg. W phpMyAdmin: Nowa, nazwa obuwie i porównywanie z polskimi znakami - arkusz podaje przykład utf8_unicode_ci, a dziś częściej wybiera się utf8mb4_polish_ci (utf8mb4 mieści każdy znak Unicode, polish sortuje „ł” po „l”).
Tabele z baza.sql mają zestaw znaków i porównywanie zapisane we własnej definicji (utf8_polish_ci), więc wybór dla bazy ich nie zmienia - dziedziczyłyby go dopiero tabele zakładane później bez własnego ustawienia.
Krok 2: Import tabel z pliku baza.sql
ok. 2 min
Polecenie z arkusza
Do utworzonej bazy zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum.
Zaznaczona baza obuwie, potem Import → baza.sql → Wykonaj. Powstają trzy tabele z ilustracji 1: kategorie, buty (model, kategoria, nazwa, cena) i produkt (kolor, materiał, wysokość buta). Relacje: buty.id_kat → kategorie.id_kat i produkt.model → buty.model.
Typowe błędy
Import bez zaznaczonej bazy obuwie kończy się błędem „Nie wybrano bazy danych” - plik nie zawiera polecenia USE.
Krok 3: Zrzut ekranu import.jpg
Kryteria:
R.1.1 Wykonany import tabel do bazy danych obuwie , co jest udokumentowane w pliku import w formacie JPEG
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie JPEG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.
Print Screen, wklejenie do edytora grafiki i zapis jako import.jpg - import w JPEG, a zrzuty zapytań w PNG. Na zrzucie widać komunikat o udanym imporcie i trzy tabele w drzewie bazy.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: kolor i materiał wysokich butów
Kryteria: ,
R.1.2 Zapisany plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonane zapytanie 1 wybierające jedynie kolor i materiał produktów, których wysokość buta jest większa niż 10. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT kolor, material FROM produkt WHERE wysokosc_buta > 10; oraz wynik działania udokumentowany zrzutem, na którym widoczne są dokładnie 2 wiersze dla koloru brązowego i szarego
ok. 2 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie kolor i materiał produktów, których wysokość buta jest większa niż 10.
Każda klauzula w osobnej linii - przy dłuższych zapytaniach od razu widać, co jest wybierane, skąd i z jakim warunkiem:
SELECT kolor, material - „jedynie kolor i materiał”, dwie kolumny zamiast *,
FROM produkt - tabela z tymi polami,
WHERE wysokosc_buta > 10 - „większa niż 10”, ostra nierówność.
Wynik: dwa wiersze - brązowy i szary, jak w kluczu. Zapytanie trafia do kwerendy.txt, zrzut do kw1.png.
R.1.4 Wykonane zapytanie 2 wybierające jedynie nazwę i cenę buta oraz odpowiadającą im nazwę kategorii. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT nazwa, cena, nazwa_kat FROM buty JOIN kategorie USING(id_kat); (możliwe też porównanie kluczy po ON lub WHERE ) oraz wynik działania udokumentowany zrzutem, na którym widoczne są dokładnie 4 rekordy dla nazw kategorii Półbuty, Trzewiki, Trampki, Obuwie sportowe
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie nazwę i cenę buta oraz odpowiadającą im nazwę kategorii. Należy posłużyć się relacją.
Tabele dostają krótkie aliasy: buty AS b, kategorie AS k. Każda kolumna ma przed sobą alias tabeli, więc od razu widać, skąd pochodzi, a dopisanie później kolumny o tej samej nazwie w drugiej tabeli nie zepsuje zapytania.
SELECT b.nazwa, b.cena, k.nazwa_kat - nazwa i cena buta, nazwa kategorii,
JOIN kategorie AS k ON k.id_kat = b.id_kat - warunek relacji zapisany wprost; klucz uznaje też USING(id_kat).
Wynik: cztery wiersze dla kategorii Półbuty, Trzewiki, Trampki i Obuwie sportowe. Zrzut: kw2.png.
Typowe błędy
FROM buty, kategorie bez warunku złączenia daje iloczyn kartezjański: 16 wierszy zamiast 4.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT kolor, materialFROM produktWHERE wysokosc_buta > 10;-- Zapytanie 2SELECT b.nazwa, b.cena, k.nazwa_katFROM buty AS bJOIN kategorie AS k ON k.id_kat = b.id_kat;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: konto Marek
Kryteria:
R.1.5 Wykonane zapytanie 3 tworzące konto użytkownika Marek na localhost z hasłem M@reK W pliku z kwerendami lub na zrzucie istnieje zapis np. CREATE USER 'Marek'@'localhost' IDENTIFIED BY 'M@reK'; oraz wynik działania udokumentowany zrzutem, na którym jest widoczny komunikat o poprawnie wykonanym zapytaniu, dopuszczalny jest błąd informujący o niewybraniu bazy
ok. 2 min
Polecenie z arkusza
Zapytanie 3: tworzące konto użytkownika Marek na localhost z hasłem M@reK.
Konto to para nazwa i host: 'Marek'@'localhost' może łączyć się tylko z tego samego komputera. Hasło po IDENTIFIED BY, z zachowaniem wielkości liter. Wynik to komunikat o poprawnym wykonaniu; klucz dopuszcza też błąd o niewybranej bazie. Zrzut: kw3.png.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT kolor, materialFROM produktWHERE wysokosc_buta > 10;-- Zapytanie 2SELECT b.nazwa, b.cena, k.nazwa_katFROM buty AS bJOIN kategorie AS k ON k.id_kat = b.id_kat;-- Zapytanie 3CREATE USER 'Marek'@'localhost' IDENTIFIED BY 'M@reK';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: przeglądanie i aktualizacja tabeli produkt
Kryteria:
R.1.6 Wykonane zapytanie 4 nadające dla konta Marek prawa jedynie do przeglądania i aktualizacji danych jedynie w bazie danych obuwie, w tabeli produkt. W pliku z kwerendami lub na zrzucie istnieje zapis np. GRANT SELECT, UPDATE ON obuwie.produkt TO 'Marek'@'localhost'; oraz wynik działania udokumentowany zrzutem, na którym jest widoczny komunikat o poprawnie wykonanym zapytaniu
ok. 2 min
Polecenie z arkusza
Zapytanie 4: nadające kontu Marek prawa jedynie do przeglądania i aktualizacji danych jedynie w bazie danych obuwie, w tabeli produkt.
Zasada najmniejszych uprawnień: konto dostaje dokładnie to, czego potrzebuje. SELECT (przeglądanie) i UPDATE (aktualizacja), tylko na obuwie.produkt, dla tego samego konta 'Marek'@'localhost'. Zrzut z komunikatem: kw4.png.
Typowe błędy
ON obuwie.* daje prawa do wszystkich tabel bazy, a GRANT ALL także do usuwania - arkusz mówi „jedynie” dwa razy.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT kolor, materialFROM produktWHERE wysokosc_buta > 10;-- Zapytanie 2SELECT b.nazwa, b.cena, k.nazwa_katFROM buty AS bJOIN kategorie AS k ON k.id_kat = b.id_kat;-- Zapytanie 3CREATE USER 'Marek'@'localhost' IDENTIFIED BY 'M@reK';-- Zapytanie 4GRANT SELECT, UPDATE ON obuwie.produkt TO 'Marek'@'localhost';
Podgląd strony po tym kroku
Etap 2: Grafika i strony HTML
Kroki 8-29 · po tym etapie masz 21 z 40 kryteriów (pkt)
Krok 8: Kadr klawiatura.jpg: 1000 × 100 px
Kryteria:
R.2.1 Grafika baner.png ma szerokość 1000 px i wysokość 100 px, jest skadrowana tak, że po lewej stronie klawiatury nie widać cyfry 8, a po prawej stronie widać jedynie klawisze Insert i Delete
ok. 4 min
Polecenie z arkusza
Na potrzeby witryny internetowej należy przygotować grafikę baner.png utworzoną na podstawie pliku klawiatura.jpg, który należy wykadrować do szerokości 1000 px i wysokości 100 px, zgodnie z kadrem przedstawionym na ilustracji 2.
Zdjęcie ma 1500 × 300 px. W GIMP-ie Zaznaczenie prostokątne z opcją Stały: Rozmiar1000 × 100 - zaznaczenie ma wtedy zawsze właściwy rozmiar i przesuwa się je tylko na miejsce z ilustracji 2 (około 37 px od lewej i 51 px od góry). Potem Obraz → Przytnij do zaznaczenia. Klucz sprawdza kadr po klawiszach: z lewej nie widać cyfry 8, z prawej widać tylko Insert i Delete (R.2.1).
Typowe błędy
Skalowanie zamiast kadrowania daje 1000 × 100, ale ze ściśniętą całą klawiaturą - kryterium R.2.1 nie jest spełnione.
Podgląd strony po tym kroku
Krok 9: Napis „Kursy komputerowe” i zapis baner.png
Kryteria:
R.2.2 W grafice jest widoczny napis "Kursy komputerowe" zapisany czcionką bezszeryfową, pochyloną, wypełnioną kolorem białym
ok. 4 min
Polecenie z arkusza
Na środku umieszczony napis "Kursy komputerowe" czcionką Arial pochyloną i pogrubioną, o rozmiarze 60, wypełnioną kolorem białym.
Narzędzie Tekst: Arial Bold Italic, rozmiar 60 px, kolor ffffff. Warstwę tekstu ustawia na środku narzędzie Wyrównanie (względem obrazu, środek w poziomie i w pionie). Plik → Eksportuj jakobaner.png (R.2.2).
Podgląd strony po tym kroku
Krok 10: Plik index.html w HTML5
Kryteria:
R.2.3 Witryna internetowa zapisana w plikach index.html i raty.html oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kursy komputerowe". Strona zawiera sekcje head i body
ok. 2 min
Polecenie z arkusza
Cechy witryny: Składa się z podstron o nazwach index.html, raty.html. Cechy wspólne dla stron: Zapisane w języku HTML5.
Najpierw powstaje cała strona index.html, a raty.html będzie jej kopią z innym blokiem głównym. <!DOCTYPE html> włącza w przeglądarce tryb standardów HTML5.
R.2.3 Witryna internetowa zapisana w plikach index.html i raty.html oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kursy komputerowe". Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Zadeklarowany polski język zawartości witryny.
lang="pl" w <html>: czytnik ekranu czyta stronę polską wymową, a przeglądarka nie proponuje tłumaczenia.
R.2.3 Witryna internetowa zapisana w plikach index.html i raty.html oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kursy komputerowe". Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Jawnie zastosowany właściwy standard kodowania polskich znaków.
<meta charset="UTF-8"> jako pierwszy element <head> - przeglądarka musi znać kodowanie, zanim przeczyta tytuł z polskimi literami.
R.2.3 Witryna internetowa zapisana w plikach index.html i raty.html oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kursy komputerowe". Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Tytuł strony widoczny na karcie przeglądarki: „Kursy komputerowe”.
<title> to napis na karcie. <meta name="viewport"> każe telefonowi pokazać stronę w jego prawdziwej szerokości zamiast pomniejszać ją jak ekran komputera - arkusz tego nie wymaga, ale bez tej linii żadna strona nie wygląda dobrze na telefonie.
R.3.6 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie style.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 style.css prawidłowo połączony z kodem strony.
<link> jest znacznikiem pustym - w HTML5 bez ukośnika />. Nazwa w tym arkuszu: style.css, z „e” na końcu.
Typowe błędy
styl.css zamiast style.css odcina wszystkie style - kryterium R.3.6, a rezultat R.4 jest wtedy oceniany tylko z kodu.
R.2.4 Zdefiniowany układ strony dzielący ją na bloki: nagłówkowy, menu, główny i stopki przy pomocy semantycznych znaczników sekcji języka HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, do stopki - footer. Dopuszcza się dodatkowe użycie bloków div lub section
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: nagłówkowy, poniżej menu, poniżej główny, na dole stopka. Podział zrealizowany 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 ilustracją 3.
<header>, <nav>, <main> i <footer> - każdy znacznik mówi, czym jest blok (R.2.4). Bloki stoją jeden pod drugim w kolejności z ilustracji 3, a to jest zwykły układ dokumentu: przeglądarka sama stawia elementy blokowe pod sobą, więc na tej stronie ani siatka, ani float nie są potrzebne - siatka przyda się dopiero przy kalkulatorze.
Zawartość menu: Odnośnik o treści „Strona główna” prowadzący do strony index.html. Odnośnik o treści „Koszt rat” prowadzący do strony raty.html. Odnośnik o treści „Nasz partner” prowadzący do strony https://moje-szkolenia.pl/.
Do własnych podstron prowadzą adresy względne, do serwisu partnera pełny adres z https:// (R.3.2). Atrybut aria-current="page" przy odnośniku do bieżącej strony mówi czytnikowi ekranu „jesteś tutaj”; na raty.html przejdzie na „Koszt rat”.
Typowe błędy
Adres partnera bez https:// przeglądarka traktuje jak plik w bieżącym folderze - odnośnik prowadzi donikąd.
R.2.5 W bloku głównym umieszczony przynajmniej jeden <h3>: "Kursy komputerowe - programowanie" lub "Adres do korespondencji" (główna), lub "Oblicz miesięczną ratę" (raty); w stopce umieszczony paragraf z numerem zdającego
ok. 1 min
Polecenie z arkusza
Zawartość stopki: paragraf o treści „Autor strony: ”, dalej wstawiony numer zdającego.
Akapit <p> w <footer>. Na egzaminie po dwukropku wpisuje się swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania.
R.2.5 W bloku głównym umieszczony przynajmniej jeden <h3>: "Kursy komputerowe - programowanie" lub "Adres do korespondencji" (główna), lub "Oblicz miesięczną ratę" (raty); w stopce umieszczony paragraf z numerem zdającego
ok. 1 min
Polecenie z arkusza
Zawartość bloku głównego strony index.html: Nagłówek trzeciego stopnia o treści „Kursy komputerowe - programowanie”.
R.2.7 Na stronie głównej w bloku głównym umieszczona tabela o 3 kolumnach i 3 wierszach, pierwszy wiersz zawiera komórki nagłówkowe, zastosowane znaczniki <table>, <tr>, <td>, <th>
ok. 3 min
Polecenie z arkusza
Tabela składająca się z 3 kolumn i 3 wierszy przedstawiona na ilustracji 4, pierwszy wiersz zawiera komórki nagłówkowe.
Te same trzy wiersze co w wersji podstawowej, ale podzielone na części: <thead> z wierszem komórek nagłówkowych i <tbody> z danymi. Przy wydruku długiej tabeli przeglądarka powtarza <thead> na każdej stronie, a CSS i skrypty mogą osobno wskazać nagłówek i dane. Atrybut scope="col" mówi czytnikowi ekranu, że „Cena” opisuje kolumnę - przy każdej liczbie przeczyta, czego dotyczy. Wygląd się nie zmienia, klucz liczy wiersze <tr> i znaczniki <th>/<td> (R.2.7).
R.2.5 W bloku głównym umieszczony przynajmniej jeden <h3>: "Kursy komputerowe - programowanie" lub "Adres do korespondencji" (główna), lub "Oblicz miesięczną ratę" (raty); w stopce umieszczony paragraf z numerem zdającego
ok. 1 min
Polecenie z arkusza
Nagłówek trzeciego stopnia o treści „Adres do korespondencji”.
R.2.8 Na stronie głównej w bloku głównym umieszczona jedna lista punktowana z trzema elementami, zastosowane znaczniki <ul> i <li>
R.3.3 Na stronie umieszczony odnośnik pocztowy „skontaktuj się” połączony z adresem mailto:[email protected]
ok. 2 min
Polecenie z arkusza
Lista punktowana (nieuporządkowana) wypełniona zawartością: „Adres: Katowice, ul. Mariacka 5”, „Telefon: 32 888 88 88” oraz odnośnik pocztowy o treści „skontaktuj się” prowadzący do adresu [email protected].
<ul> z trzema <li> (R.2.8). Odnośnik pocztowy ma w href przedrostek mailto: (R.3.3). W prawdziwym serwisie numer telefonu dostałby też odnośnik tel: (kliknięcie na telefonie wybiera numer), ale arkusz tego nie przewiduje - punkt ma zostać zwykłym tekstem.
Typowe błędy
href="[email protected]" bez mailto: przeglądarka traktuje jak nazwę pliku.
R.2.3 Witryna internetowa zapisana w plikach index.html i raty.html oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kursy komputerowe". Strona zawiera sekcje head i body
R.2.5 W bloku głównym umieszczony przynajmniej jeden <h3>: "Kursy komputerowe - programowanie" lub "Adres do korespondencji" (główna), lub "Oblicz miesięczną ratę" (raty); w stopce umieszczony paragraf z numerem zdającego
ok. 2 min
Polecenie z arkusza
Zawartość bloku głównego strony raty.html: Nagłówek trzeciego stopnia o treści „Oblicz miesięczną ratę”.
Kopia index.html jako raty.html: nagłówek, menu i stopka zostają, w <main> tylko nowy <h3>. Atrybut aria-current przechodzi na odnośnik „Koszt rat”.
R.2.9 Na stronie z ratami w bloku głównym umieszczone dwa pola wyboru (checkbox), pole edycyjne i przycisk, przynajmniej z jednym polem powiązana etykieta <label>
R.3.5 Na stronie z ratami klasa kontrolki jest przypisana do przynajmniej jednej kontrolki
ok. 2 min
Polecenie z arkusza
Pole wyboru z etykietą „Kurs React.js”.
Kontrolki stoją w bloku div.calculator - za chwilę ułoży je siatka CSS. Pole wyboru siedzi wewnątrz<label>: takie zagnieżdżenie samo wiąże etykietę z polem, bez pary for/id, i cały napis jest klikalny (R.2.9). Identyfikator react przyda się skryptowi, a klasa kontrolki jest od razu, bo arkusz przypisuje ją wszystkim kontrolkom strony (R.3.5).
R.2.9 Na stronie z ratami w bloku głównym umieszczone dwa pola wyboru (checkbox), pole edycyjne i przycisk, przynajmniej z jednym polem powiązana etykieta <label>
R.3.5 Na stronie z ratami klasa kontrolki jest przypisana do przynajmniej jednej kontrolki
ok. 1 min
Polecenie z arkusza
Pole wyboru z etykietą „Kurs JavaScript”.
Drugie pole wyboru z własnym identyfikatorem javascript. Bez <br> oba stoją na razie w jednej linii - etykiety są elementami liniowymi.
R.2.9 Na stronie z ratami w bloku głównym umieszczone dwa pola wyboru (checkbox), pole edycyjne i przycisk, przynajmniej z jednym polem powiązana etykieta <label>
R.3.4 Na stronie z ratami pole edycyjne jest typu number oraz jest zdefiniowane dla przycisku zdarzenie związane z jego wciśnięciem, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onClick lub w skrypcie np.addEventListener zmienna.onClick = …)
R.3.5 Na stronie z ratami klasa kontrolki jest przypisana do przynajmniej jednej kontrolki
ok. 2 min
Polecenie z arkusza
Pole edycyjne typu numerycznego poprzedzone etykietą: „Liczba rat: ”.
Tu etykieta stoi przed polem, więc wiąże je para for/id. Etykieta i pole są w jednym div, żeby siatka potraktowała je jak jeden wiersz. type="number" (R.3.4) z min="1" i step="1": strzałki nie zejdą poniżej jednej raty i nie dadzą ułamka. To tylko podpowiedź przeglądarki - wpisanej ręcznie liczby nie blokuje, dlatego skrypt sprawdzi ją jeszcze raz.
R.2.10 Na stronie z ratami w bloku głównym umieszczona jedna lista rozwijalna z 3 elementami, zastosowane znaczniki <select> i <option>
R.3.5 Na stronie z ratami klasa kontrolki jest przypisana do przynajmniej jednej kontrolki
ok. 2 min
Polecenie z arkusza
Lista rozwijana z danymi: „Warszawa”, „Katowice”, „Gdańsk”.
<select> z trzema <option> (R.2.10). Arkusz nie daje liście etykiety, więc opis dla czytnika ekranu niesie atrybut aria-label - bez niego lista byłaby ogłaszana jako „pole wyboru, Warszawa”, bez informacji, czego dotyczy.
R.2.9 Na stronie z ratami w bloku głównym umieszczone dwa pola wyboru (checkbox), pole edycyjne i przycisk, przynajmniej z jednym polem powiązana etykieta <label>
R.3.5 Na stronie z ratami klasa kontrolki jest przypisana do przynajmniej jednej kontrolki
ok. 1 min
Polecenie z arkusza
Przycisk o treści „Oblicz”, którego wybranie uruchamia skrypt.
<button type="button"> z identyfikatorem calculate - bez atrybutu onclick. Obsługę kliknięcia podepnie skrypt (klucz R.3.4 wymienia wprost addEventListener). Jawny type="button" mówi, że przycisk niczego nie wysyła - to zwykły przycisk uruchamiający skrypt.
Rozmieszczenie kontrolek zgodnie z ilustracją 5. Pusty paragraf do wyświetla wyniku działania skryptu.
Pusty <p id="result"> pod kalkulatorem. aria-live="polite" sprawia, że czytnik ekranu przeczyta nowy wynik sam, gdy skrypt go wpisze. Rozmieszczenie z ilustracji 5 (każda kontrolka w osobnym wierszu) zrobi CSS - na razie pola stoją obok siebie.
Kroki 30-40 · po tym etapie masz 32 z 40 kryteriów (pkt)
Krok 30: Zmienne z kolorami i krój czcionki
Kryteria:
R.4.1 Ustawiony styl domyślny dla wszystkich selektorów (*): krój czcionki Helvetica
ok. 2 min
Polecenie z arkusza
Domyślnie, dla wszystkich selektorów: krój czcionki Helvetica.
Na początku style.css blok :root z dwiema zmiennymi CSS: ciemny #625B5B i jasny #EAEAEA. Arkusz używa tych kolorów na zmianę w tle, tekście i ramkach - każdy wpisany jest raz, a w regułach stoi var(--color-dark). Zmiana odcienia to potem jedna linia. Selektor * ustawia krój Helvetica wszystkim elementom (R.4.1).
R.4.2 Ustawiony kolor tła #EAEAEA dla selektora body oraz #625B5B dla bloków menu i stopki
R.4.3 Ustawiony biały kolor czcionki dla bloków menu i stopki
R.4.6 Ustawione marginesy wewnętrzne (padding) 20px dla bloków menu i stopki oraz margines zewnętrzny lewy (margin-left) 40px dla listy punktowanej oraz tabeli
R.4.7 Ustawione wyrównanie tekstu do środka dla bloków menu, stopki i tabeli oraz obramowanie tabeli: 1px dashed #625B5B
ok. 2 min
Polecenie z arkusza
Wspólne dla bloków menu i stopki: kolor tła #625B5B, biały kolor czcionki, marginesy wewnętrzne 20 px, wyrównanie tekstu do środka.
Jedna reguła dla dwóch selektorów nav, footer (R.4.2, R.4.3, R.4.6, R.4.7).
R.4.5 Ustawiony typ punktora circle dla selektora ul
R.4.6 Ustawione marginesy wewnętrzne (padding) 20px dla bloków menu i stopki oraz margines zewnętrzny lewy (margin-left) 40px dla listy punktowanej oraz tabeli
ok. 1 min
Polecenie z arkusza
Dla selektora listy punktowanej: margines zewnętrzny lewy 40 px, typ punktora okrąg.
R.4.9 Dla odsyłaczy jedynie w bloku menu: czcionka pogrubiona, kolor tła #EAEAEA, kolor czcionki #625B5B, marginesy wewnętrzne 10px, marginesy zewnętrzne 50px, zaokrąglenie rogów 20px
ok. 2 min
Polecenie z arkusza
Dla odsyłaczy jedynie w bloku menu: czcionka pogrubiona, kolor tła #EAEAEA, kolor czcionki #625B5B, marginesy wewnętrzne 10 px, marginesy zewnętrzne 50 px, zaokrąglenie rogów 20 px.
Selektor potomka nav a - odnośnik pocztowy w bloku głównym zostaje zwykły (R.4.9). Jedna linia ponad arkusz: border: 1px solid transparent. Pod kursorem pojawi się ramka 1 px, a gdyby jej wcześniej nie było, przycisk urósłby o 2 px i odnośniki w menu przeskoczyłyby w bok. Przezroczysta ramka tej samej grubości rezerwuje na nią miejsce.
Typowe błędy
Sam selektor a zmienia też odnośnik „skontaktuj się” - arkusz mówi „jedynie w bloku menu”.
R.4.10 Gdy kursor myszy znajdzie się na odsyłaczu w menu, jego kolor tła zmienia się na #625B5B, czcionki na #EAEAEA oraz pojawia się obramowanie 1px solid #EAEAEA
ok. 2 min
Polecenie z arkusza
Gdy kursor myszy znajdzie się na odsyłaczu w menu jego kolor tła zmienia się na #625B5B, czcionki na #EAEAEA oraz pojawia się obramowanie linią ciągłą o szerokości 1 px i kolorze #EAEAEA.
:hover odwraca kolory i zmienia kolor ramki na jasny - grubość i styl (1px solid) są już w regule nav a, więc pod kursorem ramka 1px solid #EAEAEA jest widoczna (R.4.10). Ten sam wygląd dostaje :focus-visible: odnośnik wybrany klawiszem Tab wygląda jak wskazany myszą. Najedź na menu w podglądzie albo przejdź po nim Tabem.
R.4.4 Ustawiona szerokość 100% dla selektora img oraz 60% dla selektora table
R.4.6 Ustawione marginesy wewnętrzne (padding) 20px dla bloków menu i stopki oraz margines zewnętrzny lewy (margin-left) 40px dla listy punktowanej oraz tabeli
R.4.7 Ustawione wyrównanie tekstu do środka dla bloków menu, stopki i tabeli oraz obramowanie tabeli: 1px dashed #625B5B
ok. 2 min
Polecenie z arkusza
Dla selektora tabeli: obramowanie linią kreskową o grubości 1 px i kolorze #625B5B, szerokość 60%, margines zewnętrzny lewy 40 px, wyrównanie tekstu do środka.
Linia kreskowa to dashed. Ramka obejmuje samą tabelę, bez linii między komórkami - jak na ilustracji 4 (R.4.4, R.4.6, R.4.7).
R.4.8 Zdefiniowana klasa kontrolki o cechach: marginesy zewnętrzne 5px
ok. 1 min
Polecenie z arkusza
Dla klasy o nazwie kontrolki: marginesy zewnętrzne 5 px. Klasa jest przypisana do wszystkich kontrolek na stronie raty.html (pól wyboru, pola edycyjnego, listy rozwijalnej i przycisku).
Selektor klasy z kropką: .kontrolki (R.4.8). Nazwa po polsku, bo narzuca ją arkusz.
Krok 39: Kalkulator na siatce: każda kontrolka w osobnym wierszu
ok. 2 min
Polecenie z arkusza
Rozmieszczenie kontrolek zgodnie z ilustracją 5.
display: grid na bloku .calculator robi z każdego dziecka osobny wiersz siatki - dwa pola wyboru, wiersz z liczbą rat, lista i przycisk stają jedno pod drugim, jak na ilustracji 5. justify-items: start dosuwa je do lewej i nie rozciąga na całą szerokość (domyślnie element siatki zajmuje całą szerokość kolumny - przycisk byłby szeroki na pół ekranu).
W wersji podstawowej ten sam układ robią znaczniki <br>. Różnica: tu HTML opisuje tylko treść, a o układzie decyduje CSS - na przykład dwie kolumny na szerokim ekranie to jedna linia grid-template-columns, bez zmian w HTML.
R.3.1 Układ bloków po uruchomieniu w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym
ok. 2 min
Polecenie z arkusza
Uwaga: styl CSS ciała strony, obrazu, listy i tabeli należy zdefiniować wyłącznie przy pomocy selektora tych znaczników. Jest to uwarunkowane projektem późniejszej rozbudowy witryny.
Na index.html bloki stoją jeden pod drugim, jak na ilustracji 3 (R.3.1). Style body, img, ul i table są zapisane selektorami znaczników, bez klas i identyfikatorów - klucz uznaje R.4.2, R.4.4 i R.4.5 tylko w tej postaci. Zmienne CSS tego nie zmieniają: o selektorze decyduje lewa strona reguły, a var(...) stoi po prawej.
Typowe błędy
Styl tabeli zapisany jako klasa .tabela wygląda tak samo, ale klucz go nie uznaje (uwaga przy R.4).
Podgląd strony po tym kroku (index.html)
Etap 4: Skrypt JavaScript
Kroki 41-45 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 41: Plik raty.js z defer i obsługa kliknięcia
Kryteria: ,
R.3.4 Na stronie z ratami pole edycyjne jest typu number oraz jest zdefiniowane dla przycisku zdarzenie związane z jego wciśnięciem, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onClick lub w skrypcie np.addEventListener zmienna.onClick = …)
R.5.1 Skrypt jest napisany w języku JavaScript i zawiera on przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania
ok. 3 min
Polecenie z arkusza
Wykonywany po stronie klienta, na stronie raty.html po kliknięciu przycisku „Oblicz”.
Skrypt w osobnym pliku raty.js, dołączonym w <head> z atrybutem defer: przeglądarka pobiera go równolegle ze stroną i uruchamia dopiero, gdy cały HTML jest wczytany - querySelector na pewno znajdzie przycisk i pola.
Na początku pliku:
obiekt PRICES z cenami z tabeli na ilustracji 4 - klucz to identyfikator pola wyboru, wartość to cena,
stałe const z odnośnikami do pola liczby rat, listy miast i akapitu wyniku - wyszukane raz, a nie przy każdym kliknięciu,
addEventListener('click', calculateInstallment) podpina funkcję pod przycisk (R.3.4) - nazwa funkcji bez nawiasów, bo przekazuje się samą funkcję, a nie wynik jej wywołania.
Funkcja jest jeszcze pusta: kliknięcie „Oblicz” niczego nie robi (R.5.1).
R.5.2 Skrypt pobiera dane z przynajmniej jednej kontrolki, np. funkcja document.getElementById z parametrem, który zdefiniowany jest w kontrolce jako id
R.5.3 Skrypt ustala koszt wszystkich zaznaczonych w polu wyboru kursów np. poprzez sprawdzenie warunku zaznaczenia danego kursu (pole checked == true). Ceny: React.js - 5000, JavaScript 3000
ok. 3 min
Polecenie z arkusza
Pobiera dane z kontrolek. Ustala całkowitą kwotę za wybrane kursy na podstawie cen z tabeli z ilustracji 4.
Pętla for...of po Object.entries(PRICES) daje pary [identyfikator, cena]: ['react', 5000], potem ['javascript', 3000]. Dla każdej pary getElementById(id).checked sprawdza, czy pole jest zaznaczone (R.5.2), i jeśli tak - dolicza cenę do total (R.5.3).
W wersji podstawowej są dwa osobne warunki if. Tu nowy kurs to jedna linia w obiekcie PRICES i jedno pole wyboru w HTML - funkcja się nie zmienia.
R.5.4 Skrypt pobiera wpisaną w pole edycyjne liczbę rat i oblicza koszt jednej raty dzieląc koszt kursów przez liczbę rat
ok. 2 min
Polecenie z arkusza
Oblicza koszt jednej raty na podstawie kwoty całkowitej. Dla uproszczenia kwota całkowita jest dzielona przez podaną liczbę rat.
valueAsNumber pola type="number" oddaje od razu liczbę (dla pustego pola - NaN, „nie liczba”), a nie tekst jak value. Wysokość raty to kwota całkowita podzielona przez liczbę rat: 8000 / 10 = 800 (R.5.4).
Dwa warunki przed dzieleniem, każdy kończy funkcję komunikatem i return („wczesne wyjście”):
liczba rat musi być liczbą całkowitą większą od zera - Number.isInteger(NaN) to fałsz, więc puste pole też tu odpada. Bez tego puste pole dałoby „rat po Infinity zł”, a 0 lub -2 - ratę bez sensu,
trzeba zaznaczyć co najmniej jeden kurs - inaczej wynik brzmiałby „Koszt całkowity: 0 zł”.
Komunikaty trafiają do akapitu przez textContent: wpisuje zwykły tekst, którego przeglądarka nie interpretuje jako HTML. Klucz tego nie sprawdza, ale to pierwsze, co zgłosiłby użytkownik kalkulatora.
const PRICES = { react: 5000, javascript: 3000 };const installmentsInput = document.querySelector('#installments');const citySelect = document.querySelector('#city');const result = document.querySelector('#result');function calculateInstallment() {let total = 0;for (const [id, price] ofObject.entries(PRICES)) {if (document.getElementById(id).checked) { total += price; } }const installments = installmentsInput.valueAsNumber;if (!Number.isInteger(installments) || installments < 1) { result.textContent = 'Podaj liczbę rat - liczbę całkowitą większą od zera.';return; }if (total === 0) { result.textContent = 'Zaznacz co najmniej jeden kurs.';return; }const rate = total / installments;}document.querySelector('#calculate').addEventListener('click', calculateInstallment);
Podgląd strony po tym kroku (raty.html)
Krok 45: Zdanie z wynikiem pod przyciskiem
Kryteria: , , ,
R.5.5 Pod przyciskiem jest wyświetlany efekt działania skryptu, którego fragment dotyczący miasta zawiera nazwę miasta pobraną z listy rozwijalnej (wystarczy sprawdzić dwa razy dla różnych miast)
R.5.6 Pod przyciskiem jest wyświetlany efekt działania skryptu: obliczony w skrypcie koszt całkowity
R.5.7 Pod przyciskiem jest wyświetlany efekt działania skryptu: liczba rat oraz koszt jednej raty (sprawdzić dla dwóch różnych liczb )
R.5.8 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania
ok. 3 min
Polecenie z arkusza
Wyświetla pod przyciskiem w paragrafie treść: „Kurs odbędzie się w <miasto>. Koszt całkowity: <kwota> zł. Płacisz <liczba> rat po <rata> zł”, gdzie <miasto> oznacza wybór z listy rozwijalnej, <kwota> oznacza obliczoną kwotę całkowitą, <liczba> oznacza podaną liczbę rat, a <rata> oznacza wyliczoną ratę.
citySelect.value to tekst wybranej opcji, czyli nazwa miasta (R.5.5),
szablon tekstowy w odwrotnych apostrofach wstawia wartości w ${...} - zdanie czyta się jak gotowy tekst, bez plątaniny + i cudzysłowów,
Intl.NumberFormat('pl-PL') formatuje kwoty po polsku: przecinek dziesiętny i najwyżej dwa miejsca po przecinku. 8000 / 3 daje „2666,67 zł”, a nie „2666.6666666666665 zł” (R.5.6, R.5.7).
Zaznacz w podglądzie oba kursy, wpisz 10, wybierz Katowice i kliknij „Oblicz”: „Kurs odbędzie się w Katowice. Koszt całkowity: 8000 zł. Płacisz 10 rat po 800 zł” - jak na ilustracji 5. Nazwy mówią, co przechowują: PRICES, total, installments, rate, city, calculateInstallment (R.5.8).
const PRICES = { react: 5000, javascript: 3000 };const installmentsInput = document.querySelector('#installments');const citySelect = document.querySelector('#city');const result = document.querySelector('#result');const money = new Intl.NumberFormat('pl-PL', { maximumFractionDigits: 2 });function calculateInstallment() {let total = 0;for (const [id, price] ofObject.entries(PRICES)) {if (document.getElementById(id).checked) { total += price; } }const installments = installmentsInput.valueAsNumber;if (!Number.isInteger(installments) || installments < 1) { result.textContent = 'Podaj liczbę rat - liczbę całkowitą większą od zera.';return; }if (total === 0) { result.textContent = 'Zaznacz co najmniej jeden kurs.';return; }const rate = total / installments;const city = citySelect.value; result.textContent = `Kurs odbędzie się w ${city}. Koszt całkowity: ${money.format(total)} zł. Płacisz ${installments} rat po ${money.format(rate)} zł`;}document.querySelector('#calculate').addEventListener('click', calculateInstallment);
Podgląd strony po tym kroku (raty.html)
Etap 5: Porównanie z wersją podstawową
Kroki 46-47 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 46: Co jest inaczej i dlaczego
ok. 3 min
Polecenie z arkusza
Ocenie podlegać będzie 5 rezultatów: operacje na bazie danych, zawartość witryny internetowej, działanie witryny internetowej, styl CSS witryny internetowej oraz skrypt.
Obie wersje dają te same punkty. Różnice:
wersja podstawowa
ta wersja
SQL
JOIN ... USING(id_kat) w jednej linii
aliasy tabel, JOIN ... ON, klauzule w osobnych liniach
kolory
wpisane w każdej regule
zmienne w :root
tabela
same <tr>
<thead>, <tbody>, scope="col"
układ kalkulatora
<br> w HTML
siatka CSS na .calculator
zdarzenie
onclick w HTML
addEventListener w raty.js z defer
ceny kursów
dwa warunki if
obiekt PRICES i pętla
złe dane
„rat po Infinity zł”
komunikat i return
kwoty
2666.6666666666665
Intl.NumberFormat: 2666,67
menu
ramka pod kursorem przesuwa odnośniki
przezroczysta ramka rezerwuje miejsce, :focus-visible
Skrypt tej wersji jest sprawdzony w prawdziwym Chrome: oba kursy i 10 rat (800 zł, jak na ilustracji 5), 3 raty (2666,67 zł), jeden kurs, żaden kurs, puste i ujemne pole liczby rat.
Czas przeznaczony na wykonanie zadania wynosi 150 minut.
Wersja podstawowa, gdy liczy się czas: onclick, getElementById i innerHTML są w tabeli 1 arkusza, a cały skrypt to kilkanaście linii w jednym pliku.
Ta wersja, gdy addEventListener, szablony tekstowe i for...of pisze się z pamięci. Osobny plik raty.js trzeba nagrać na płytę razem z resztą - bez niego kalkulator przestaje działać, a punkty R.5 egzaminator sprawdzi już tylko w kodzie.
Mieszanie też daje pełne punkty: zmienne CSS i siatka z tej wersji, skrypt z podstawowej.
Krok 48 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 48: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Nagraj płytę z rezultatami pracy. W folderze z numerem zdającego powinny znajdować się pliki: baner.png, import.jpg, index.html, kw1.png, kw2.png, kw3.png, kw4.png, kwerendy.txt, raty.html, przeglądarka.txt, style.css, ewentualnie inne przygotowane pliki.
W przeglądarka.txt nazwa przeglądarki, w której strony były sprawdzane. Strony nie wymagają serwera - otwierają się wprost z dysku.
Do listy z arkusza dochodzi raty.js („ewentualnie inne przygotowane pliki”). Po nagraniu trzeba sprawdzić odczyt płyty i opisać ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
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: Bartosz Bryniarski. 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.