INF.03-12-26.06-SGCzerwiec 2026 · 40 kroków · ok. 90 min · 45 kryteriów z klucza
Rozwiązanie krok po kroku: Aplikacja salonu rowerowego (Nowoczesny kod (zdarzenia, walidacja))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza rowery z czterema zapytaniami, odwrócone i przeskalowane zdjęcie oraz strona index.html z kalkulatorem rozmiaru ramy - i tak samo spełnia każde kryterium klucza. Inna jest droga:
skrypt w osobnym plikuskrypt.js z atrybutem defer i nasłuchiwaczami zdarzeń zamiast atrybutów oninput, onclick i onload,
suwak i pole liczbowe zsynchronizowane w obie strony, wzrost spoza zakresu 100-220 cm daje komunikat zamiast bzdurnego wyniku, a współczynniki stoją w jednym obiekcie zamiast drabinki if,
data z toLocaleDateString('pl-PL') zamiast ręcznego dopisywania zer, w znaczniku <time>,
zmienne CSS, kontrolki wzrostu w osobnym wierszu bloku zamiast <br>, nazwy pól dla czytnika ekranu,
zapytania z aliasami i złączeniem JOIN ... ON.
Układ bloków zostaje na flexboksie - dlaczego nie siatka, wyjaśnia krok z układem. Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza i zdjęcia pochodzą z prawdziwego archiwum pliki22, zapytania zostały wykonane na tej bazie w MariaDB z XAMPP-a, a skrypty sprawdzone w prawdziwej przeglądarce. Strona w podglądzie działa - przesuń suwak, wybierz typ roweru i kliknij „Sprawdź”.
Jak liczą się punkty. Klucz ma 45 kryteriów (R.1.1 - R.5.10), każde za 1 punkt. Próg zdania to 75%, czyli 34 punkty. Przy każdym kroku jest napisane, które kryteria spełnia.
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 45 kryteriów (pkt)
Krok 1: Baza danych rowery
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie rowery, z zestawem polskich znaków (np. utf8_unicode_ci)
Archiwum pliki22.7z rozpakuj hasłem {Row3RY} (razem z nawiasami klamrowymi, cyfra 3 zamiast „e”) do folderu z numerem zdającego. W phpMyAdmin Nowa → rowery, porównywanie utf8_unicode_ci, albo:
CREATE DATABASE rowery CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Krok 2: Import tabel z pliku rowery.sql
ok. 2 min
Polecenie z arkusza
Do utworzonej bazy zaimportuj tabele z pliku rowery.sql
Import → rowery.sql. Dwie tabele: producenci i rowery - pole producent_id roweru wskazuje producenta (relacja jeden do wielu: producent ma wiele rowerów).
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonany import tabel do bazy danych rowery - plik import.png
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel
Cały ekran z paskiem zadań, zapis jako import.png.
Typowe błędy
Wykadrowany zrzut nie jest oceniany.
Krok 4: Zapytanie 1: górskie do 4500 zł
Kryteria: ,
R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonane zapytanie 1 wybierające jedynie pola model, rozmiar_ramy, rozmiar_kol, kolor i cena z tabeli rowery, których typ to górski oraz cena <= 4500. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT model, rozmiar_ramy, rozmiar_kol, kolor, cena FROM rowery WHERE typ = "górski" AND cena <= 4500; oraz na zrzucie widocznych jest dokładnie 9 rekordów z modelami: Fuse Comp 22, Rockhopper Comp 22, ..., Marlin 5, Roscoe 6
ok. 2 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie model, rozmiar ramy, rozmiar kół, kolor i cenę z tabeli rowery dla rowerów w typie górski, których cena jest mniejsza lub równa 4500
Pięć kolumn (nazwy z ilustracji 1: rozmiar_kol bez „ó”), dwa warunki połączone AND; „mniejsza lub równa” to <=. Wynik: 9 wierszy, od Fuse Comp 22 do Roscoe 6. Zapytania zapisuj w kwerendy.txt, zrzut jako kw1.png.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT model, rozmiar_ramy, rozmiar_kol, kolor, cenaFROM roweryWHERE typ = 'górski' AND cena <= 4500;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: ceny według producenta
Kryteria:
R.1.4 Wykonane zapytanie 2 wybierające jedynie nazwy producentów oraz minimalną, średnią i maksymalną cenę rowerów dla każdego producenta. Kolumny z cenami mają nazwy (aliasy): „najtańszy”, „średnia cena”, „najdroższy”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT producenci.nazwa, MIN(cena) AS 'najtańszy' , AVG(cena) AS 'średnia cena', MAX(cena) AS 'najdroższy' FROM rowery JOIN producenci ON producenci.id = rowery.producent_id GROUP BY producent_id; (poprawne również GROUP BY nazwa, możliwe też porównanie kluczy po WHERE, AS opcjonalnie) oraz na zrzucie widocznych jest dokładnie 6 wierszy z nazwami: Cup, Knife, Glass, Teaspoon, Spoon, Fork; z cenami z dowolną dokładnością
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie nazwy producentów oraz minimalną, średnią i maksymalną cenę rowerów zgrupowane dla każdego producenta. Kolumnom z cenami należy nadać nazwy (aliasy): „najtańszy”, „średnia cena”, „najdroższy”. Należy posłużyć się relacją
aliasy tabel r i p, złączenie po kluczu w ON,
trzy funkcje agregujące z aliasami kolumn w odwrotnych apostrofach - w MySQL i MariaDB to znak dla nazw; spacja i polskie litery w aliasie „średnia cena” są wtedy bezpieczne,
GROUP BY p.id, p.nazwa - grupowanie po kluczu producenta (dwóch producentów o tej samej nazwie nie skleiłoby się w jeden wiersz) i po kolumnie, którą zapytanie wybiera. W MySQL wystarczyłoby p.id, ale wymienienie wszystkich wybieranych kolumn bez funkcji agregującej działa w każdej bazie SQL.
Wynik: 6 wierszy - Cup, Knife, Glass, Teaspoon, Spoon, Fork. Siódmy producent nie ma rowerów, więc złączenie wewnętrzne go pomija. Zrzut: kw2.png.
Typowe błędy
Bez GROUP BY funkcje agregujące liczą całą tabelę - jeden wiersz zamiast sześciu.
kwerendy.txtTekstzmienione: 9 linii
-- Zapytanie 1SELECT model, rozmiar_ramy, rozmiar_kol, kolor, cenaFROM roweryWHERE typ = 'górski' AND cena <= 4500;-- Zapytanie 2SELECT p.nazwa, MIN(r.cena) AS `najtańszy`, AVG(r.cena) AS `średnia cena`, MAX(r.cena) AS `najdroższy`FROM rowery AS rJOIN producenci AS p ON p.id = r.producent_idGROUP BY p.id, p.nazwa;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: karbonowe w rozmiarze L
Kryteria:
R.1.5 Wykonane zapytanie 3 wybierające jedynie id, model, typ i rozmiar kół rowerów karbonowych w rozmiarze ramy L. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, model, typ, rozmiar_kol FROM rowery WHERE model LIKE "%carbon%" AND rozmiar_ramy = "L"; oraz na zrzucie widocznych jest dokładnie 7 wierszy z id: 5, 7, 13, 16, 18, 29, 52
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie id, model, typ i rozmiar kół rowerów karbonowych (w nazwie modelu zawierają słowo „Carbon”) w rozmiarze ramy L
LIKE '%Carbon%' - „Carbon” w dowolnym miejscu nazwy (porównywanie utf8_unicode_ci nie rozróżnia wielkości liter, więc wzorzec pisany jak w arkuszu złapie też „carbon”). Wynik: 7 wierszy - id 5, 7, 13, 16, 18, 29, 52. Zrzut: kw3.png.
kwerendy.txtTekstzmienione: 6 linii
-- Zapytanie 1SELECT model, rozmiar_ramy, rozmiar_kol, kolor, cenaFROM roweryWHERE typ = 'górski' AND cena <= 4500;-- Zapytanie 2SELECT p.nazwa, MIN(r.cena) AS `najtańszy`, AVG(r.cena) AS `średnia cena`, MAX(r.cena) AS `najdroższy`FROM rowery AS rJOIN producenci AS p ON p.id = r.producent_idGROUP BY p.id, p.nazwa;-- Zapytanie 3SELECT id, model, typ, rozmiar_kolFROM roweryWHERE model LIKE '%Carbon%' AND rozmiar_ramy = 'L';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: rowery gravelowe tańsze o 25%
Kryteria:
R.1.6 Wykonane zapytanie 4 aktualizujące cenę rowerów gravelowych obniżając ją o 25%. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE rowery SET cena=cena*0.75 WHERE typ="gravel"; oraz na zrzucie widoczny jest komunikat o poprawnie wykonanym zapytaniu, zmienionych zostało 5 wierszy, lub tabela ze zmienionymi wartościami
ok. 2 min
Polecenie z arkusza
Zapytanie 4: aktualizujące cenę rowerów gravelowych (typ: gravel) obniżając ją o 25%
Obniżka o 25% to 75% dawnej ceny: SET cena = cena * 0.75. Kolumna cena jest typu DECIMAL(10,2), więc wynik zostaje zapisany dokładnie do grosza (MySQL sam zaokrągla trzecie miejsce po przecinku). phpMyAdmin melduje 5 zmienionych wierszy. Zrzut z komunikatem albo z tabelą po zmianie: kw4.png.
Przed UPDATE na prawdziwej bazie dobrze jest uruchomić SELECT z tym samym WHERE - widać, które wiersze się zmienią, zanim się zmienią.
Typowe błędy
UPDATE bez WHERE obniża ceny wszystkich rowerów, a każde kolejne uruchomienie zapytania obniża ceny gravelowych o następne 25%.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT model, rozmiar_ramy, rozmiar_kol, kolor, cenaFROM roweryWHERE typ = 'górski' AND cena <= 4500;-- Zapytanie 2SELECT p.nazwa, MIN(r.cena) AS `najtańszy`, AVG(r.cena) AS `średnia cena`, MAX(r.cena) AS `najdroższy`FROM rowery AS rJOIN producenci AS p ON p.id = r.producent_idGROUP BY p.id, p.nazwa;-- Zapytanie 3SELECT id, model, typ, rozmiar_kolFROM roweryWHERE model LIKE '%Carbon%' AND rozmiar_ramy = 'L';-- Zapytanie 4UPDATE rowerySET cena = cena * 0.75WHERE typ = 'gravel';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-21 · po tym etapie masz 23 z 45 kryteriów (pkt)
Krok 8: Grafika 1.jpg: odwrócenie i szerokość 400 px
Kryteria:
R.2.1 Obraz z pliku 1.jpg został obrócony wzdłuż osi pionowej oraz przeskalowany do szerokości 400 px, odpowiadająca temu wysokość wynosi 306 px (±5 px)
ok. 3 min
Polecenie z arkusza
Plik 1.jpg należy obrócić wzdłuż osi pionowej oraz przeskalować z zachowaniem proporcji tak, aby jego szerokość wynosiła dokładnie 400 px. Zmodyfikowany obraz jest widoczny na ilustracji 2
Zdjęcie w archiwum leży kołami do góry, z przednim kołem po prawej (lewa połowa obrazu obok). Na ilustracji 2 rower stoi na kołach, a przód nadal jest po prawej - to daje tylko odwrócenie góra-dół. W GIMP-ie: Obraz → Przekształć → Odbij pionowo, potem Obraz → Skaluj obraz: szerokość 400 px przy zamkniętym łańcuchu proporcji, wysokość wychodzi sama - 306 px (klucz R.2.1: 306 ±5).
⚠️ Sprzeczność w arkuszu: „obrócić wzdłuż osi pionowej” dosłownie oznacza odbicie lewo-prawo, a wtedy rower nadal leżałby kołami do góry, a przód przeszedłby na lewo. Arkusz każe trzymać się ilustracji („zmodyfikowany obraz jest widoczny na ilustracji 2”), a klucz sprawdza tylko wymiar - dlatego odwrócenie góra-dół.
Typowe błędy
Obróć o 180° też stawia rower na kołach, ale przenosi przód na lewą stronę - to lustrzane odbicie zdjęcia z ilustracji 2.
Podgląd strony po tym kroku
Krok 9: Plik index.html w HTML5
ok. 1 min
Polecenie z arkusza
Składa się ze strony o nazwie index.html. Zapisana w języku HTML5
Pierwsza linia <!DOCTYPE html>. Strona nie korzysta z bazy (zapytania są tylko w phpMyAdmin), więc to zwykły plik .html.
R.2.2 W pliku index.html znajduje się deklaracja HTML5 <!DOCTYPE HTML>, deklaracja języka zawartości: polski np. <html lang="pl">
ok. 1 min
Polecenie z arkusza
Zadeklarowany polski język zawartości witryny
lang="pl" w <html> - razem z deklaracją HTML5 to R.2.2. Przyda się też skryptowi: to dzięki polskiemu językowi strony czytnik ekranu przeczyta datę po polsku.
Krok 13: Bloki: nagłówek, główny, boczny, dwie stopki
Kryteria:
R.2.4 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML 5: header, main, aside, footer, footer (dopuszcza się stosowanie bloków pomocniczych)
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: nagłówkowy, główny, boczny, dwa bloki stopki. Podział zrealizowany za pomocą semantycznych znaczników języka HTML 5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3
header, main, aside i dwa footer - dokładnie lista z klucza R.2.4. <footer> może wystąpić więcej niż raz: to stopka treści, w której stoi, a nie „jedyna stopka strony”.
Krok 15: Nagłówki i pole opcji „górski z kołami 29”
Kryteria: , ,
R.3.7 Co najmniej jedno pole ma powiązaną etykietę (label z for i id lub zagnieżdżenie kontrolki w label)
R.3.8 Przynajmniej jedna etykieta ma podpowiedź w postaci "dymku", np.: atrybut title
R.3.9 Przynajmniej jedna etykieta lub przycisk w bloku głównym mają przypisaną klasę klasa_etykiety
ok. 3 min
Polecenie z arkusza
Zawartość bloku głównego: Nagłówek pierwszego stopnia o treści „Dobierz rozmiar ramy roweru do wzrostu”. Nagłówek drugiego stopnia o treści „Wybierz rodzaj roweru”. Pole opcji, domyślnie zaznaczone, z etykietą „górski z kołami 29”. Znacznik etykiety ma przypisaną klasę klasa_etykiety i podpowiedź „górski z kołami 29” w postaci "dymku"
<h1> i <h2>, a pod nimi pole opcji z checked i etykieta powiązana przez for/id (R.3.7) - kliknięcie kafelka zaznacza pole. „Dymek” to atrybut title (R.3.8), a klasa klasa_etykiety zrobi z etykiety ciemny kafelek (R.3.9). Identyfikatory po angielsku (mountain, potem road, trekking) - skrypt użyje ich jako kluczy współczynników.
index.htmlHTMLzmienione: 4 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Salon rowerowy</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <imgsrc="1.jpg"alt="rower"> <imgsrc="2.jpg"alt="rower"> <imgsrc="3.jpg"alt="rower"> <imgsrc="4.jpg"alt="rower"> <imgsrc="5.jpg"alt="rower"> </header> <main> <h1>Dobierz rozmiar ramy roweru do wzrostu</h1> <h2>Wybierz rodzaj roweru</h2> <inputtype="radio"name="bike"id="mountain"checked> <labelfor="mountain"class="klasa_etykiety"title="górski z kołami 29">górski z kołami 29</label> </main> <aside> </aside> <footer> </footer> <footer> </footer></body></html>
Podgląd strony po tym kroku (index.html)
Krok 16: Pola opcji „szosa” i „trekking”, jedno zaznaczenie naraz
Kryteria:
R.3.4 Pierwsze pole opcji jest domyślnie zaznaczone. W jednym momencie można zaznaczyć tylko jedno pole opcji
ok. 2 min
Polecenie z arkusza
Pole opcji z etykietą „szosa”. Znacznik etykiety ma przypisaną klasę klasa_etykiety i podpowiedź „szosa” w postaci "dymku". Pole opcji z etykietą „trekking”. Znacznik etykiety ma przypisaną klasę klasa_etykiety i podpowiedź „trekking” w postaci "dymku". W jednym momencie można zaznaczyć tylko jedno pole opcji
Dwa kolejne pola na tym samym wzorze. Wszystkie trzy mają ten sam name="bike" - przeglądarka traktuje je jak jedną grupę, więc zaznaczenie jednego odznacza pozostałe; z pierwszym zaznaczonym na starcie to R.3.4.
Typowe błędy
Różne name w polach opcji - da się zaznaczyć wszystkie trzy naraz.
R.3.5 Pole typu range ma ustawione wartości min=100 oraz max=220 oraz value=150
R.3.6 Pole edycyjne jest typu number, z domyślną wartością 150
ok. 3 min
Polecenie z arkusza
Nagłówek drugiego stopnia o treści „Podaj swój wzrost”. Pole zakresu liczbowego z ustawionymi wartościami: domyślną 150, minimalną 100, maksymalną 220, zmiana wartości na suwaku powoduje wywołanie skryptu 1. Pole edycyjne typu numerycznego z wartością domyślną 150
<input type="range"> z min, max i value z arkusza (R.3.5), <input type="number"> z value="150" (R.3.6),
pole liczbowe dostaje te same min i max - strzałki pola nie wyjdą poza zakres, a przeglądarka zaznaczy wpisaną wartość spoza niego jako błędną,
aria-labelledby="height-title" - oba pola nie mają własnej etykiety, a nagłówek „Podaj swój wzrost” ją zastępuje: czytnik ekranu przeczyta go przy wejściu w pole,
oba pola stoją w <div> - blok zajmuje cały wiersz, więc przycisk dopisany pod nim stanie „poniżej” bez znacznika <br>.
R.2.6 W bloku głównym znajdują się kontrolki: trzy pola opcji, trzy etykiety (label) , pole zakresu liczbowego (type=range), pole edycyjne i przycisk "Sprawdź"
ok. 2 min
Polecenie z arkusza
Poniżej przycisk „Sprawdź” z przypisaną klasą klasa_etykiety, którego kliknięcie wywołuje skrypt 2. Paragraf z wynikiem działania skryptu 2
type="button" - przycisk niczego nie wysyła. Pusty akapit result czeka na wynik; aria-live="polite" każe czytnikowi ekranu przeczytać wynik, gdy się pojawi. Na stronie są wszystkie kontrolki z R.2.6: trzy pola opcji, trzy etykiety, suwak, pole i przycisk.
R.3.10 Przynajmniej jeden paragraf w bloku bocznym ma przypisane dwie klasy: logo1 i prawa lub logo1 i srodek lub logo2 i prawa (użycie dwa razy atrybutu class jest błędem)
ok. 2 min
Polecenie z arkusza
Zawartość bloku bocznego: nagłówek pierwszego stopnia o treści „Polecane firmy”, paragraf z przypisanymi klasami logo1 i prawa z zawartością „cup”, paragraf z przypisaną klasą logo2 z zawartością „glass”, paragraf z przypisanymi klasami logo1 i srodek z zawartością „spoon”, paragraf z przypisanymi klasami logo2 i prawa z zawartością „teaspoon”, paragraf z przypisaną klasą logo1 z zawartością „fork”
Kilka klas w jednym atrybucie, rozdzielonych spacją: class="logo1 prawa" - element dostaje style obu klas (R.3.10). Treść małymi literami jak w arkuszu; wielkie litery z ilustracji 2 da CSS.
Typowe błędy
Dwa atrybuty class w jednym znaczniku - przeglądarka bierze tylko pierwszy, a klucz mówi o tym wprost przy R.3.10.
R.2.8 W stopce znajdują się dwie listy punktowane: pierwszy element pierwszej listy zagnieżdża drugą listę, zastosowane znaczniki <ul>, <li>. Podlista <ul> zawarta wewnątrz pierwszego <li> listy głównej
ok. 2 min
Polecenie z arkusza
Zawartość pierwszego bloku stopki: nagłówek czwartego stopnia o treści „Oferowane typy rowerów”, lista punktowana (nieuporządkowana) z elementami: „górskie”, „szosowe”, „miejskie”. Pierwszy element zagnieżdża drugą listę punktowaną z elementami „koła 29 cali”, „koła 26 cali”
Podlista to cała druga <ul>wewnątrz pierwszego <li> - po słowie „górskie”, przed jego </li> (R.2.8).
R.2.5 W bloku głównym znajduje się <h1>: "Dobierz rozmiar ramy roweru do wzrostu", <h2>: "Wybierz rodzaj roweru" lub "Podaj swój wzrost", w bloku bocznym <h1>: "Polecane firmy" oraz przynajmniej jeden <p>, w stopce <h4>: "Oferowane typy rowerów" lub "Informacje"
R.2.9 W stopce znajduje się tabela o 2 wierszach i 2 kolumnach: zastosowane znaczniki <table>, <tr>, <td>; w drugiej komórce pierwszego wiersza wpisany jest numer zdającego
ok. 2 min
Polecenie z arkusza
Zawartość drugiego bloku stopki: nagłówek czwartego stopnia o treści „Informacje”, tabela o dwóch wierszach i dwóch kolumnach. W komórkach pierwszego wiersza wstawione: tekst „Autor: ”, numer zdającego; w komórkach drugiego wiersza: tekst „Aktualna data: ”, efekt działania skryptu 3
Dwa wiersze <tr> po dwie komórki <td>. W drugiej komórce pierwszego wiersza na egzaminie wpisujesz swój numer zdającego (PESEL) - tu stoi imię i nazwisko autora rozwiązania (R.2.9). W ostatniej komórce <time id="date"> - znacznik daty; skrypt 3 wpisze do niego datę czytelną dla człowieka, a w atrybucie datetime tę samą datę w formacie dla maszyn. Z tym krokiem są wszystkie nagłówki i akapity z R.2.5.
Kroki 22-31 · po tym etapie masz 34 z 45 kryteriów (pkt)
Krok 22: Zmienna z kolorem i ciało strony
ok. 2 min
Polecenie z arkusza
Dla ciała strony: szerokość 80%, marginesy zewnętrzne automatycznie wyliczane przez przeglądarkę
Na górze zmienna--dark z ciemną zielenią #02220a - arkusz używa jej w czterech miejscach (stopki, cień bloku bocznego, kafelki). Ciało strony: 80% szerokości i margin: auto - wolne miejsce po równo z lewej i z prawej, strona staje na środku.
Dla bloku nagłówkowego: wysokość 200 px, biały kolor tła, wyrównanie tekstu do środka, blok położony zawsze w odległości 0 px od góry względem okna przeglądarki, pozycja ta nie zmienia się nawet po przewinięciu całej strony
„Względem okna” i „nie zmienia się po przewinięciu” to position: fixed z top: 0 (R.4.5) - klucz wymienia tę parę wprost. position: sticky (blok przykleja się dopiero, gdy dojdzie do krawędzi przy przewijaniu) byłby tu wygodniejszy, bo nie wyjmuje bloku z układu - ale arkusz opisuje zachowanie fixed.
Blok z fixed wypada z układu strony: reszta treści zachowuje się tak, jakby go nie było, i wjeżdża pod niego. Dlatego blok główny i boczny dostaną margines górny 200 px, a białe tło nie pozwala przewijanej treści prześwitywać.
Dla bloku głównego: szerokość 60%, wysokość 650 px, jedynie marginesy wewnętrzne prawy i lewy 2%, jedynie margines zewnętrzny górny 200 px
padding-inline: 2% to skrót od padding-left i padding-right naraz: „inline” to kierunek, w którym płynie tekst (w polskim - poziomo). Górny i dolny margines wewnętrzny zostają bez zmian, jak chce arkusz („jedynie prawy i lewy”). W inspektorze widać dwie wartości: padding-left: 2% i padding-right: 2%. margin-top: 200px odsuwa treść spod przyklejonego nagłówka.
Typowe błędy
padding: 2% dałby 2% także u góry i u dołu - arkusz mówi „jedynie prawy i lewy”.
Dla bloku bocznego: szerokość 20%, wysokość 650 px, cień bloku bez przesunięcia (przesunięcie 0 px), z rozmyciem 100 px w kolorze #02220a, jedynie margines zewnętrzny górny 200 px
box-shadow: 0 0 100px var(--dark) - bez przesunięcia, rozmycie 100 px: cień rozlewa się równo dookoła, na ilustracji 2 to ciemna poświata po bokach bloku (R.4.6). Zero nie potrzebuje jednostki.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowane właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position; żaden blok nie zachodzi na inne bloki - sprawdzić w inspektorze)
ok. 3 min
Polecenie z arkusza
Podział strony na bloki: nagłówkowy, główny, boczny, dwa bloki stopki. Podział zrealizowany za pomocą semantycznych znaczników języka HTML 5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3
display: flex z flex-wrap: wrap na ciele strony: blok główny (60% + 2 × 2% marginesu wewnętrznego = 64%) i boczny (20%) mieszczą się w jednym rzędzie, a dwie stopki po 50% zawijają się razem do drugiego (R.3.1). Nagłówek z position: fixed w tym układzie nie uczestniczy. align-items: flex-start - bloki nie rozciągają się do wysokości najwyższego w rzędzie.
Dlaczego nie siatka? Arkusz i klucz (R.4.2) ustawiają szerokości na samych blokach: 60%, 20%, 50%. W siatce procent szerokości elementu liczy się od jego kolumny, nie od rodzica - blok główny z width: 60% w kolumnie zająłby 60% kolumny (sprawdzone w Chrome). Szerokości trzeba by przenieść do grid-template-columns, a w tym arkuszu klucz takiej formy nie wymienia. Flex liczy procenty od rodzica, więc szerokości z arkusza działają wprost - punkt z klucza ma pierwszeństwo przed zmianą techniki.
Typowe błędy
Bez marginesu górnego 200 px blok główny wjeżdża pod przyklejony nagłówek - w inspektorze bloki na siebie nachodzą i R.3.1 przepada.
R.4.2 szerokość: ciało strony - 80%, blok główny - 60%, blok boczny - 20%, bloki stopki - 50%, selektor img - 16% wysokość: blok nagłówkowy - 200px, bloki główny i boczny - 650px, bloki stopki - 170px
R.4.4 marginesy wewnętrzne (padding) : blok główny: jedynie prawy i lewy - 2%, obrazy - 3px, marginesy zewnętrzne (margin) : ciało strony - auto, obrazy - 8px, blok główny i boczny: jedynie górny - 200px
Selektor znacznika img (uwaga arkusza). border-radius: 50% na prostokątnym zdjęciu daje elipsę - jak na ilustracji 2. Szerokości i wysokości (R.4.2) oraz marginesy (R.4.4) są już komplet.
Krok 29: Etykiety i przycisk jako kafelki, zieleń pod kursorem
Kryteria: ,
R.4.9 dla klasy .klasa_etykiety: szerokość - 18%, wysokość - 60px, wysokość wiersza - 60px, sposób wyświetlania liniowo-blokowy, kolor tła - #02220a, biały kolor czcionki, wyrównanie tekstu do środka, przepełnienie elementu – ukryte (wystarczy 5 cech z 8)
R.4.10 gdy kursor znajdzie się na elemencie z przypisaną klasą .klasa_etykiety jego kolor tła zmienia się na ForestGreen
ok. 3 min
Polecenie z arkusza
Dla klasy klasa_etykiety: szerokość 18%, wysokość 60 px, wysokość wiersza (interlinia) 60 px, sposób wyświetlania liniowo-blokowy, kolor tła #02220a, biały kolor czcionki, wyrównanie tekstu do środka, obsłużone przepełnienie elementu – ukryte. W momencie gdy kursor znajdzie się na elemencie z przypisaną klasą klasa_etykiety jego kolor tła zmienia się na ForestGreen
Etykieta jest elementem liniowym i nie przyjmuje wymiarów - display: inline-block pozwala je nadać, a kafelki nadal stoją w jednej linii. line-height równe wysokości stawia jedną linię tekstu na środku w pionie, overflow: hidden ucina to, co się nie mieści (R.4.9). Pod kursorem :hover - zieleń ForestGreen (R.4.10).
Właściwości w kolejności: sposób wyświetlania i wymiary, potem przepełnienie, na końcu kolory i tekst - w każdej regule tak samo, więc łatwo znaleźć brakującą.
R.4.8 dla klasy .logo1 : wielkość czcionki - 50px, tekst przekształcony na wielkie litery, pochylenie czcionki dla klasy .logo2 : wielkość czcionki - 30px, podkreślenie, krój czcionki Impact
ok. 2 min
Polecenie z arkusza
Dla klasy logo1: wielkość czcionki 50 px, tekst przekształcony na wielkie litery, czcionka pochylona. Dla klasy logo2: wielkość czcionki 30 px, podkreślenie, krój czcionki Impact
text-transform: uppercase pokazuje „CUP”, choć w HTML-u jest „cup”; pochylenie to font-style: italic, podkreślenie - text-decoration: underline (R.4.8).
R.4.3 wyrównanie tekstu do środka: blok nagłówkowy, klasa .srodek wyrównanie tekstu do prawej strony: klasa .prawa
R.4.7 zaokrąglenie rogów: obrazy - 50%, styl listy: selektor ul - brak punktora
ok. 1 min
Polecenie z arkusza
Dla klasy prawa: wyrównanie tekstu do prawej. Dla klasy srodek: wyrównanie tekstu do środka. Dla selektora listy punktowanej: brak punktora
Dwie małe klasy wyrównania (R.4.3) - „cup” bierze rozmiar z logo1, a wyrównanie z prawa. ul (selektor znacznika, jak wymaga uwaga) bez punktorów, także w podliście (R.4.7).
Kroki 32-38 · po tym etapie masz 45 z 45 kryteriów (pkt)
Krok 32: Skrypt 1: suwak przepisuje wzrost do pola
Kryteria: , ,
R.3.3 Zdefiniowano dla przycisku zdarzenie związane z jego wciśnięciem lub dla pola zakresu zdarzenie związane ze zmianą jego wartości, które uruchamia funkcję skryptu
R.5.3 Skrypt pobiera dane z przynajmniej jednej kontrolki
R.5.4 Skrypt 1 wyświetla w polu edycyjnym wartość pobraną z suwaka
ok. 3 min
Polecenie z arkusza
Skrypt 1: wykonywany po zmianie wartości pola zakresu liczbowego (po przesunięciu suwaka), pobiera wartość z pola zakresu liczbowego i wpisuje ją do pola edycyjnego
Skrypt w osobnym pliku skrypt.js, w <head> z defer - wykona się po wczytaniu całego HTML-u. Dwie stałe z polami wzrostu i nasłuchiwacz zdarzenia input na suwaku: zachodzi przy każdym ruchu, więc liczba w polu zmienia się na bieżąco (change zaszłoby dopiero po puszczeniu suwaka). Funkcja strzałkowa przepisuje value suwaka do pola (R.3.3, R.5.3, R.5.4). Przesuń suwak w podglądzie.
Skrypt 2: wylicza rozmiar ramy i wypisuje informacje na ten temat. Pobiera wartość z pola edycyjnego lub pola zakresu liczbowego (wzrost)
Arkusz pozwala skryptowi 2 czytać pole albo suwak - i właśnie na tej dowolności przewraca się ilustracja 4: wzrost 189 wpisany w pole, a wynik policzony z suwaka stojącego w innym miejscu (szczegóły w wersji podstawowej). Drugi nasłuchiwacz na polu przesuwa suwak przy każdej zmianie liczby - oba pola zawsze pokazują to samo i nie ma znaczenia, które z nich czyta skrypt.
Krok 34: Skrypt 2: wzrost z pola po kliknięciu „Sprawdź”
ok. 3 min
Polecenie z arkusza
Wykonywany po kliknięciu na przycisk „Sprawdź”. Pobiera wartość z pola edycyjnego lub pola zakresu liczbowego (wzrost)
FACTORS - obiekt ze współczynnikami z arkusza, kluczem jest id pola opcji. Nazwa wielkimi literami to zwyczaj dla stałych konfiguracyjnych: wartości, których program nie zmienia,
heightField.valueAsNumber daje liczbę od razu (zamiast tekstu z value), a dla pustego pola - NaN (nie-liczbę), co za chwilę pozwoli wykryć brak wzrostu.
Krok 35: Skrypt 2: współczynnik z zaznaczonego pola i obliczenie
Kryteria: , ,
R.5.5 Sprawdzone przynajmniej dla jednego pola radio czy jest wybrane (np.: w warunku zapisane sprawdzenie wartości checked dla elementu)
R.5.6 Skrypt 2 oblicza rozmiar ramy - mnoży wzrost przez współczynnik 0.26 dla zaznaczonego pierwszego radio; 0.3 - drugiego; 0.28 trzeciego, a następnie dzieli przez 2.54
R.5.7 Skrypt 2 zaokrągla obliczony rozmiar ramy do liczby całkowitej
ok. 4 min
Polecenie z arkusza
Oblicza rozmiar ramy roweru, w ten sposób, że mnoży wzrost przez współczynnik zależny od typu roweru. Typ roweru pobiera z pól opcji: gdy zaznaczono pole „górski z kołami 29” wartość współczynnika wynosi 0,26, gdy zaznaczono pole „szosa” wartość współczynnika wynosi 0,3, gdy zaznaczono pole „trekking” wartość współczynnika wynosi 0,28. Następnie dzieli wynik przez 2,54 i zaokrągla do liczby całkowitej
querySelectorAll('input[name="bike"]') - wszystkie trzy pola opcji; [...] zamienia wynik na zwykłą tablicę,
find((radio) => radio.checked) zwraca pierwsze pole, którego właściwość checked jest prawdziwa, czyli zaznaczone (R.5.5),
FACTORS[selected.id] - współczynnik po identyfikatorze pola: mountain → 0.26, road → 0.3, trekking → 0.28. Jedna linia zamiast trzech gałęzi if - nowy typ roweru to nowe pole opcji i jedna pozycja w obiekcie (R.5.6),
wzrost razy współczynnik to długość ramy w cm, dzielenie przez 2,54 zamienia ją na cale, Math.round zaokrągla do całości (R.5.7). Ułamki w JavaScripcie z kropką: 0.26, 2.54.
R.5.8 Skrypt 2 wyświetla pod przyciskiem „Sprawdź” wyliczony rozmiar ramy w formacie: „Zalecany rozmiar ramy to: <rozmiar> cali", gdzie <rozmiar> oznacza obliczoną wartość
ok. 2 min
Polecenie z arkusza
Wyliczony rozmiar ramy wypisuje pod przyciskiem „Sprawdź” w formacie: „Zalecany rozmiar ramy to: <rozmiar> cali”, gdzie <rozmiar> oznacza obliczoną wartość
Szablon tekstowy w odwrotnych apostrofach: ${frame} wstawia liczbę w środek napisu - bez sklejania plusami i pilnowania spacji. textContent, bo to zwykły tekst (R.5.8). Sprawdzone w przeglądarce: szosa i 189 cm - „22 cali”, górski i 150 cm - „15 cali”, trekking i 180 cm - „20 cali”.
Pobiera wartość z pola edycyjnego lub pola zakresu liczbowego (wzrost)
Wersja podstawowa przy pustym polu liczy „0 cali”, a przy wzroście 40 cm - „4 cali”. Tu na początku funkcji jest strażnik: jeśli wzrost nie jest w zakresie suwaka (100-220 cm), skrypt pisze, czego oczekuje, i kończy działanie (return).
Warunek jest zapisany odwrotnie - !(height >= 100 && height <= 220) zamiast height < 100 || height > 220 - bo NaN z pustego pola nie spełnia żadnego porównania: NaN < 100 i NaN > 220 są fałszywe, więc druga postać przepuściłaby puste pole. Sprawdzone w przeglądarce: puste pole i 40 cm dają komunikat.
Krok 38: Skrypt 3: dzisiejsza data DD.MM.RRRR po załadowaniu strony
Kryteria: , , ,
R.5.1 Skrypt napisany w języku JavaScript i zawiera on przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania
R.5.2 Zastosowana przynajmniej jedna zmienna oraz nazewnictwo jest w języku polskim lub angielskim i odzwierciedla cel zastosowania
R.5.9 Skrypt 3 tworzy obiekt typu Date
R.5.10 Skrypt 3 wyświetla w stopce aktualną datę
ok. 3 min
Polecenie z arkusza
Skrypt 3: wykonywany po załadowaniu strony, wyświetla aktualną (dzisiejszą) datę w formacie DD.MM.RRRR
new Date() - obiekt z bieżącą datą i godziną (R.5.9),
toLocaleDateString('pl-PL', {...}) zapisuje datę według polskich zwyczajów: day: '2-digit' i month: '2-digit' dokładają zero przed dniem i miesiącem, a polski format rozdziela je kropkami - wychodzi DD.MM.RRRR bez ręcznego + 1 przy miesiącu i bez if dla zer (R.5.10),
date.dateTime ustawia atrybut datetime znacznika <time> na datę w formacie ISO (RRRR-MM-DD) - tak datę czytają wyszukiwarki i programy. Format ISO daje tu toLocaleDateString('sv-SE'): szwedzki zapis daty to właśnie RRRR-MM-DD, liczony w czasie lokalnym,
window.addEventListener('load', showDate) - „po załadowaniu strony” dosłownie: zdarzenie load zachodzi, gdy wczytane są wszystkie zasoby, także zdjęcia. Sam defer uruchamia skrypt wcześniej, zaraz po przeczytaniu HTML-u.
Nazwy (heightRange, heightField, FACTORS, result, checkFrame, selected, frame, showDate, today) mówią, czemu służą (R.5.1, R.5.2).
Typowe błędy
Kusi toISOString().slice(0, 10), ale ta metoda podaje czas UTC - między północą a 1:00 (latem 2:00) polskiego czasu to jeszcze wczorajsza data.
Krok 39 · po tym etapie masz 45 z 45 kryteriów (pkt)
Krok 39: Co jest inaczej i którą wersję wybrać na egzaminie
ok. 2 min
Obie wersje dają komplet 45 punktów. Różnice:
wersja podstawowa
wersja nowoczesna
zdarzenia
oninput, onclick, <body onload> w HTML
addEventListener w skrypt.js z defer
suwak i pole
tylko suwak → pole
w obie strony
zaznaczone pole opcji
if / else if / else z checked
find(radio => radio.checked) + obiekt FACTORS
zły wzrost
„0 cali”, „4 cali”
komunikat o zakresie 100-220 cm
data
getDate, getMonth() + 1, dopisywanie zer
toLocaleDateString('pl-PL'), <time datetime>
wynik
innerHTML i plusy
textContent i szablon tekstowy
przycisk pod polami
<br>
pola w <div>
CSS
kolory wpisane w reguły
zmienna --dark, padding-inline
Układ bloków jest w obu wersjach na flexboksie - tu szerokości bloków z klucza nie dają się przenieść do siatki bez zmiany formy, którą klucz ocenia. Na egzaminie wersja podstawowa trzyma się dosłownie tabel arkusza; z nowoczesnej najbardziej opłaca się przenieść synchronizację pola z suwakiem - to jedna funkcja, a usuwa rozjazd widoczny nawet na ilustracji 4.
Krok 40 · po tym etapie masz 45 z 45 kryteriów (pkt)
Krok 40: Plik przegladarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy o nazwie przegladarka.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 tym arkuszu plik nazywa się przegladarka.txt - bez „ą”, jak w treści zadania. W folderze z numerem zdającego: 1.jpg … 5.jpg (1.jpg po przeróbce), index.html, skrypt.js, styl.css, kwerendy.txt, import.png, kw1.png … kw4.png, przegladarka.txt. Płytę sprawdź po nagraniu.
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.