Spis treści
W części praktycznej egzaminu INF.03 skrypty JavaScript są krótkie, ale precyzyjnie oceniane: komisja uruchamia stronę, wykonuje opisane w arkuszu czynności i sprawdza, czy skrypt zrobił dokładnie to, co trzeba. Kurs prowadzi od podstaw języka do wzorców powtarzających się w arkuszach – każdy wzorzec ma kompletny kod HTML, CSS i JavaScript oraz listę typowych błędów.
Pracuj z edytorem i przeglądarką otwartymi obok siebie. Do ćwiczeń są paczki ZIP z obrazami (znajdziesz je w lekcjach). Każda lekcja kończy się pytaniami „Sprawdź się”, a każda część – zadaniem praktycznym; wzorce ćwicz tak długo, aż napiszesz je z pamięci w kilka minut.
Część A
JavaScript na egzaminie i podstawy języka
Co sprawdza egzamin INF.03 w skryptach po stronie klienta, jak podłączyć skrypt do strony oraz zmienne, warunki, pętle, funkcje, tablice, obiekty i JSON.
Część A, lekcja 1
Jak wygląda JavaScript na egzaminie INF.03
W części praktycznej egzaminu INF.03 (150 minut) wykonujesz kompletną witrynę: bazę danych, strony HTML/CSS i skrypty. Skrypty po stronie klienta pisze się w JavaScript, a po stronie serwera w PHP. W arkuszach z czerwca 2026 (zadania 01–12) JavaScript pojawił się w ośmiu z dwunastu zadań, a w czterech pozostałych było PHP. Zadania JavaScript są krótkie (od kilku do kilkudziesięciu linii), ale każda linia jest oceniana, więc liczy się precyzja.
| Typ zadania | Co trzeba zrobić | Najważniejsze techniki |
|---|---|---|
| karta produktu, galeria | kliknięcie miniatury podmienia obraz główny; kliknięcie obrazu otwiera okno z powiększeniem; krzyżyk zamyka okno | querySelector, .src, style.display, onclick z argumentem |
| rezerwacja, formularz dwuczęściowy | dwa przyciski przełączają aktywną część formularza i kolor przycisków; strzałki przewijają zdjęcia i nazwy miejsc | disabled, style.backgroundColor, tablica obiektów, licznik z zawinięciem |
| dane pacjenta, recepty | z obiektu/tablicy JSON wygenerować bloki z listami; puste pola pominąć | pętla forEach, szablony napisów `${...}`, innerHTML, warunek na pusty napis |
| plansza do gry | kliknięcie pustego pola wstawia kółko lub krzyżyk, zmienia się gracz i widoczność napisów | zmienna stanu, if, visibility, sprawdzanie src |
| licznik odwiedzin | po każdym wejściu zwiększyć licznik zapisany w przeglądarce i wypisać w stopce | localStorage, parseInt, DOMContentLoaded |
| zamówienia w restauracji | kliknięcie potrawy dodaje element listy; przycisk czyści; inny wyświetla alert i czyści | createElement, append, alert, innerHTML = "" |
| atlas, wyszukiwarka | dwie tablice (nazwy, opisy); kliknięcie obrazu lub wpisanie nazwy generuje tytuł i opis | tablice równoległe, includes, indexOf, tworzenie elementów DOM |
| kalkulator | suwak i pole liczbowe zsynchronizowane; wynik zależy od zaznaczonej opcji; wypisanie dzisiejszej daty | input type=range/number/radio, :checked, Math.round, Date, padStart |
Jak oceniany jest rezultat „Skrypty”
- Kryteria skryptów sprawdza się w przeglądarce, wykonując akcje opisane w arkuszu (klik, wpisanie wartości), a gdy skrypt nie działa – w kodzie źródłowym.
- Skrypt musi robić dokładnie to, co jest w poleceniu: dokładne teksty (np. „Zalecany rozmiar ramy to: 62 cali”), kolejność, kolory, nazwy klas i identyfikatorów podane w arkuszu. Nie wolno zmieniać nazw klas z projektu.
- Zmienne i funkcje nazywasz znacząco, po polsku lub angielsku (
podmienObraz,wyczyscZamowienie,currentPlayer) – nazwy typua,x1,funsą obniżane w ocenie. - Kod może być w osobnym pliku
main.js(zwykle wymagany przez arkusz) i musi być prawidłowo podłączony do strony.
Na egzaminie najpierw wykonaj bazę i kwerendy (łatwe, szybkie punkty), potem HTML i CSS, a skrypty zostaw na koniec – ale nie pomijaj ich: każdy działający skrypt to osobne punkty. Skrypty JavaScript z arkuszy da się napisać w 5–15 minut, jeśli znasz wzorce z tego kursu.
W kursie znajdziesz paczki ZIP z obrazami do ćwiczeń (galeria, wycieczki, gra, zamówienia). HTML i CSS piszesz samodzielnie – dokładnie jak na egzaminie – a przykłady w lekcjach pokazują sprawdzone układy.
Dlaczego nazwy funkcji i zmiennych w skrypcie powinny być znaczące?
Pokaż przykładową odpowiedź
Bo wymaga tego arkusz egzaminacyjny i ocenia je komisja: nazwa ma wskazywać cel (np. wyczyscZamowienie), a nie być przypadkowa (f1, x).
Co zrobisz, gdy skrypt na egzaminie nie działa, a zostaje mało czasu?
Pokaż przykładową odpowiedź
Zostawię go z poprawną składnią i logiką w pliku (komisja może ocenić kod źródłowy), sprawdzę konsolę (F12) pod kątem błędu, a jeśli to nie pomoże – przejdę do kolejnych zadań i wrócę, gdy zostanie czas.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Wypisz w konsoli przeglądarki napis „Egzamin INF.03” i zadeklaruj stałą z liczbą pytań.
("Egzamin INF.03");
liczbaPytan = 40;
Znajdź w dokumencie element o klasie okno i zmień jego tekst.
document.(".okno"). = "Witaj";
Instrukcja nie wypisze tekstu w konsoli: nazwa obiektu jest napisana błędnie, a napis nie jest zamknięty. Popraw kod.
Część A, lekcja 2
Podłączenie skryptu do strony i narzędzia pracy
Skrypt można osadzić w HTML na trzy sposoby. Na egzaminie arkusz zwykle wymaga osobnego pliku (main.js, skrypty.js) połączonego ze stroną.
<!-- 1. zewnętrzny plik: zalecany; defer = wykonanie po wczytaniu HTML -->
<script src="main.js" defer></script>
<!-- 2. skrypt wewnętrzny -->
<script>
console.log("Witaj");
</script>
<!-- 3. atrybut zdarzenia w elemencie (spotykany w arkuszach: wywołanie funkcji po kliknięciu) -->
<button onclick="zamknijOkno()">Zamknij</button>
<!-- skrypt na końcu body też działa, bo elementy już istnieją -->
<script src="main.js"></script>
</body>
| Umiejscowienie | Skutek |
|---|---|
<script src> w head bez defer | skrypt uruchamia się przed zbudowaniem strony, więc querySelector(...) zwraca null (błąd „Cannot read properties of null”) |
w head z defer | wykonanie po wczytaniu HTML, ale przed zdarzeniem DOMContentLoaded – bezpieczny wybór |
na końcu body | elementy już istnieją; działa bez defer |
funkcja wywoływana z atrybutu onclick | skrypt mógł być wczytany wcześniej lub później – ważne, aby funkcja była globalna (na najwyższym poziomie pliku) |
Skrypt w head bez defer wykonuje się, zanim strona istnieje. Objaw w konsoli: Uncaught TypeError: Cannot read properties of null (reading 'style'). Rozwiązanie: defer, przeniesienie skryptu na koniec body albo pobieranie elementów wewnątrz funkcji wywoływanych po wczytaniu.
Konsola i debugowanie
- F12 otwiera narzędzia deweloperskie: karta Console pokazuje błędy (czerwone) i wyniki
console.log(). - Karta Elements pozwala sprawdzić, czy element ma oczekiwany styl i klasy po wykonaniu skryptu, a Sources – ustawić punkt przerwania.
console.log(zmienna)to najszybszy sposób sprawdzenia wartości;console.table(tablica)pokazuje tablicę w tabeli.- Komunikat o błędzie zawiera nazwę pliku i numer linii – kliknij go, aby przejść do miejsca błędu.
Dlaczego skrypt w sekcji head bez atrybutu defer może nie znaleźć elementów strony?
Pokaż przykładową odpowiedź
Bo przeglądarka wykonuje go w trakcie czytania HTML, zanim elementy z body zostaną utworzone; querySelector zwraca wtedy null.
Jak sprawdzisz, jaką wartość ma zmienna w trakcie działania skryptu?
Pokaż przykładową odpowiedź
Wypiszę ją przez console.log(zmienna) i obejrzę w karcie Console narzędzi deweloperskich (F12) lub użyję punktu przerwania w Sources.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Podłącz plik skrypt.js na końcu strony tak, aby uruchomił się po wczytaniu elementów strony.
<body>
<div class="okno"></div>
< ="skrypt.js"></>
</body>
Skrypt jest podłączony niepoprawnie: atrybut ma zła nazwę, a znacznik nie jest zamknięty. Popraw kod HTML.
Uruchom funkcję start dopiero po wczytaniu całego dokumentu.
document.("", start);
Skrypt w nagłówku strony nie widzi elementów, bo uruchamia się zbyt wcześnie. Dodaj atrybut, który opóźni wykonanie do końca wczytywania dokumentu.
Część A, lekcja 3
Zmienne, typy, operatory
| Deklaracja | Zasięg | Przypisanie ponowne |
|---|---|---|
const | blokowy | niedozwolone (zawartość obiektu lub tablicy można zmieniać) |
let | blokowy | dozwolone |
var | funkcyjny | dozwolone; w nowym kodzie unikaj (spotkasz w starszych materiałach i na egzaminie) |
const imie = "Anna"; // string
let wiek = 17; // number (całkowite i rzeczywiste)
let aktywny = true; // boolean
let nic = null; // null: celowy brak wartości
let niezdefiniowane; // undefined: zmienna bez wartości
console.log(typeof imie, typeof wiek, typeof aktywny); // string number boolean
console.log(Number("42"), parseInt("42px"), parseFloat("3.5"), String(7), (7).toString());
console.log("5" + 2, "5" - 2, "5" * "2"); // 52 3 10
console.log(isNaN(parseInt("abc"))); // true
| Operatory | Przykład | Uwagi |
|---|---|---|
| arytmetyczne | + - * / % **, ++, -- | % – reszta z dzielenia (np. 7 % 3 = 1) |
| przypisania | = += -= *= /= | x += 2 to x = x + 2 |
| porównania | == != === !== < > <= >= | w skryptach egzaminacyjnych używaj === (porównanie wartości i typu) |
| logiczne | &&, ||, ! | && – i, || – lub, ! – nie |
| napisy | +, szablon `tekst ${zmienna}` | szablon z odwrotnymi apostrofami wstawia wartości wyrażeń i może mieć wiele linii |
input.value jest napisem, nawet w polu type="number". Przed obliczeniami zamień na liczbę: Number(pole.value) lub parseInt(pole.value). Bez tego "160" + 5 daje "1605".
Co wypisze console.log("10" + 5) i console.log("10" - 5)?
Pokaż przykładową odpowiedź
105 (sklejenie napisów) oraz 5 (odejmowanie zamienia napis na liczbę).
Czym różni się const od let?
Pokaż przykładową odpowiedź
Zmiennej const nie można ponownie przypisać, a let można; oba mają zasięg blokowy.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Zadeklaruj stałą z nazwą, zmienną z licznikiem i zwiększ licznik o 1.
nazwa = "Rower";
licznik = 0;
licznik;
Wylicz cenę po rabacie 15% i wypisz napis z wartością (szablon w odwróconych apostrofach).
const cena = 200;
const rabat = 0.15;
const doZaplaty = cena (1 - rabat);
console.log(Do zapłaty: zł);
Wynik dodawania jest sklejony jako tekst („52”), bo wartość z pola jest napisem. Zamień ją na liczbę, aby wynik wynosił 7.
Próba zmiany stałej kończy się błędem. Popraw deklarację tak, aby zmienną można było zwiększać.
Użyj operatora reszty z dzielenia, aby sprawdzić parzystość, oraz porównania ścisłego.
const liczba = 8;
const parzysta = liczba 2 0;
console.log(parzysta);
Część A, lekcja 4
Instrukcje warunkowe
const temperatura = 18;
if (temperatura >= 25) {
console.log("gorąco");
} else if (temperatura >= 15) {
console.log("ciepło");
} else {
console.log("zimno");
}
// operator trójargumentowy: warunek ? gdyPrawda : gdyFałsz
const opis = temperatura > 20 ? "lato" : "nie lato";
// switch przy wielu wartościach jednej zmiennej
switch (opis) {
case "lato": console.log("kąpiel"); break;
default: console.log("kurtka");
}
// typowe w arkuszach: ustawienie współczynnika zależnie od wyboru
let wspolczynnik = 0.26;
if (wybor === "szosa") wspolczynnik = 0.3;
if (wybor === "trekking") wspolczynnik = 0.28;
W warunku fałszywe są: false, 0, "" (pusty napis), null, undefined i NaN. Dlatego if (recepta.lek2) pomija pusty lek, ale if (recepta.lek2 != "") robi to jawniej – w arkuszu podobne warunki są wprost wymagane.
| Operator | Znaczenie |
|---|---|
===, !== | równość i różność z kontrolą typu (zalecane); == porównuje po konwersji typów |
<, <=, >, >= | porównania liczb (i napisów alfabetycznie) |
&&, ||, ! | i, lub, negacja – łączenie warunków |
Jak sprawdzisz, że napis lek2 nie jest pusty?
Pokaż przykładową odpowiedź
if (lek2 !== "") { ... } lub krócej if (lek2) { ... }.
Kiedy użyjesz switch zamiast else if?
Pokaż przykładową odpowiedź
Gdy jedna zmienna jest porównywana z wieloma konkretnymi wartościami; pamiętaj o break i default.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Wypisz „gorąco” dla temperatury od 25 stopni, „ciepło” od 15 i „zimno” w pozostałych przypadkach.
const t = 18;
(t >= 25) {
console.log("gorąco");
} (t 15) {
console.log("ciepło");
} {
console.log("zimno");
}
Warunek ma sprawdzić, czy napis wybor jest równy „szosa”, ale zamiast porównania stoi przypisanie. Popraw kod.
Użyj operatora trójargumentowego oraz instrukcji switch.
const opis = temperatura > 20 "lato" "nie lato";
(opis) {
case "lato": console.log("kąpiel"); ;
default: console.log("kurtka");
}
Pole lek2 ma być pominięte, gdy jest puste, ale warunek sprawdza coś innego. Popraw go tak, aby kod wykonał się tylko przy niepustym napisie.
Połącz dwa warunki: wiek co najmniej 18 oraz zgoda wyrażona.
if (wiek >= 18 zgoda) {
console.log("można");
}
if (wiek < 18 !zgoda) {
console.log("nie można");
}
Część A, lekcja 5
Pętle
for (let i = 0; i < 5; i++) { // znana liczba powtórzeń
console.log(i);
}
let n = 3;
while (n > 0) { console.log(n); n--; }
const miasta = ["Radom", "Kielce", "Lublin"];
for (const miasto of miasta) console.log(miasto); // po wartościach
miasta.forEach((miasto, indeks) => console.log(indeks, miasto)); // z indeksem
| Pętla | Kiedy |
|---|---|
for | znana liczba powtórzeń lub potrzebny indeks (plansza, tabela) |
while | powtarzanie, dopóki warunek jest prawdziwy – pamiętaj o zmianie zmiennej w treści pętli |
for...of, forEach | przejście po wszystkich elementach tablicy |
break, continue | przerwanie pętli, przejście do następnego obrotu |
while (n > 0) { ... } bez n-- nigdy się nie zakończy i zawiesi kartę przeglądarki. Sprawdź, czy zmienna sterująca zmienia się w każdym obrocie.
Którą pętlą przejdziesz po wszystkich elementach tablicy bez użycia indeksu?
Pokaż przykładową odpowiedź
for (const element of tablica) lub tablica.forEach(element => ...).
Ile razy wykona się for (let i = 1; i <= 5; i++)?
Pokaż przykładową odpowiedź
Pięć razy (i = 1, 2, 3, 4, 5).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Wypisz liczby od 0 do 4 pętlą for.
(let i = 0; i 5; i) {
console.log(i);
}
Pętla while odlicza od 3 do 1, ale nigdy się nie kończy. Popraw kod.
Wypisz każde miasto z tablicy: raz pętlą po wartościach, raz metodą forEach z indeksem.
const miasta = ["Radom", "Kielce", "Lublin"];
for (const miasto miasta) console.log(miasto);
miasta.((miasto, ) => console.log(indeks, miasto));
Pętla ma zsumować elementy tablicy, ale suma jest zerowana w każdym obrocie. Popraw kod.
Część A, lekcja 6
Funkcje i ich wywoływanie z HTML
Funkcja to nazwany fragment kodu, który można wywołać wielokrotnie. W arkuszach egzaminacyjnych funkcje są uruchamiane po zdarzeniu, najczęściej przez atrybut onclick elementu HTML.
function otworzOkno() { // bez parametrów
document.querySelector(".okno").style.display = "block";
}
function podmienObraz(nazwaPliku) { // z parametrem
document.querySelector(".obraz").src = `img/${nazwaPliku}`;
}
function sredniaOcen(oceny) { // z wartością zwracaną
let suma = 0;
for (const ocena of oceny) suma += ocena;
return suma / oceny.length;
}
console.log(sredniaOcen([5, 4, 3]).toFixed(2)); // "4.00"
const kwadrat = x => x * x; // funkcja strzałkowa
<img class="miniatura" src="img/rower2.svg" alt="miniatura" onclick="podmienObraz('rower2.svg')">
<button onclick="otworzOkno()">Powiększ</button>
<input type="number" id="wzrost" onchange="obliczRozmiar()">
<button onclick="zmienSekcje('uczestnik')">Uczestnik</button>
- Funkcja ma zasięg globalny, jeśli jest zadeklarowana na najwyższym poziomie pliku – tylko wtedy widzi ją atrybut
onclick. - Argument tekstowy w atrybucie HTML zapisuj w apostrofach wewnątrz cudzysłowów:
onclick="podmienObraz('rower2.svg')". - Atrybut
onclick="funkcja(this)"przekazuje do funkcji element, który został kliknięty (this) – wzorzec użyty w planszy gry. - Nie dodawaj nawiasów przy przypisaniu funkcji do zdarzenia w JS:
przycisk.onclick = funkcja(bez()), bofunkcja()wykona się od razu.
document.addEventListener("DOMContentLoaded", licznik()) wykona licznik() natychmiast i przekaże do zdarzenia jego wynik (undefined). Poprawnie: addEventListener("DOMContentLoaded", licznik). Podobnie onclick="funkcja" w HTML nic nie wykona – potrzebne są nawiasy.
Co oznacza przekazanie this w onclick="zaznaczPole(this)"?
Pokaż przykładową odpowiedź
Do funkcji trafia kliknięty element (np. komórka tabeli z obrazem), więc funkcja może zmienić jego właściwości bez wyszukiwania.
Dlaczego wywołanie addEventListener("click", funkcja()) jest błędem?
Pokaż przykładową odpowiedź
Nawiasy powodują natychmiastowe wywołanie funkcji, a do obsługi zdarzenia trafia jej wynik zamiast samej funkcji; powinno być addEventListener("click", funkcja).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Napisz funkcję z parametrem, która podmienia obraz, i funkcję zwracającą średnią.
podmienObraz(nazwaPliku) {
document.querySelector(".obraz").src = `img/${nazwaPliku}`;
}
function srednia(oceny) {
let suma = 0;
for (const ocena of oceny) suma += ocena;
suma / oceny.length;
}
Wywołaj funkcje z elementów HTML: kliknięcie miniatury i przycisku.
<img class="miniatura" src="img/rower2.svg" ="podmienObraz('rower2.svg')">
<button onclick="otworzOkno">Powiększ</button>
Obsługa zdarzenia uruchamia funkcję natychmiast, a nie po kliknięciu. Popraw przypisanie funkcji.
Funkcja ma zwrócić kwadrat liczby, ale po wywołaniu wynikiem jest undefined. Popraw kod.
Zapisz tę samą funkcję jako funkcję strzałkową.
const kwadrat = x x * x;
Część A, lekcja 7
Tablice w JavaScript
Tablica przechowuje uporządkowaną listę wartości pod jedną nazwą. Elementy numerujemy od zera. Tablice służą w arkuszach do list nazw, ścieżek obrazów, opisów i cen.
const drzewa = ["buk", "lipa", "wierzba"];
console.log(drzewa[0], drzewa.length); // buk 3
drzewa.push("dąb"); // dodanie na końcu
console.log(drzewa.includes("lipa")); // true: czy zawiera
console.log(drzewa.indexOf("wierzba")); // 2: pozycja lub -1
drzewa.forEach((drzewo, i) => console.log(i, drzewo));
// tablice równoległe: ten sam indeks = to samo drzewo
const opisy = ["Duże drzewo...", "Drzewo o szerokiej koronie...", "Rośnie nad wodą..."];
const gdzie = drzewa.indexOf("lipa");
console.log(`${drzewa[gdzie]}: ${opisy[gdzie]}`);
| Operacja | Zapis |
|---|---|
| odczyt elementu, długość | t[0], t.length; ostatni element: t[t.length - 1] |
| dodanie / usunięcie na końcu | t.push(x) / t.pop() |
| czy zawiera, pozycja | t.includes(x) (true/false), t.indexOf(x) (indeks lub −1) |
| pętla | t.forEach(el => ...), for (const el of t) |
| nowa tablica z wynikami | t.map(el => ...), t.filter(el => warunek) |
| sortowanie, złączenie | t.sort(), t.join(", ") |
Pierwszy element ma indeks 0, a ostatni length - 1. Błąd o 1 w indeksie to jedna z najczęstszych przyczyn błędnego wyniku skryptu. W karuzeli wycieczek poprawne wartości numeru to 0, 1, 2 – przekroczenie zakresu (3 lub −1) wymaga zawinięcia.
Jak sprawdzić, czy wpisana nazwa drzewa jest w tablicy nazw?
Pokaż przykładową odpowiedź
drzewa.includes(nazwa) zwraca true lub false; pozycję zwróci drzewa.indexOf(nazwa).
Jak odczytać ostatni element tablicy t?
Pokaż przykładową odpowiedź
t[t.length - 1].
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Utwórz tablicę, odczytaj pierwszy element i długość, dodaj element na końcu.
const drzewa = "buk", "lipa", "wierzba";
console.log(drzewa[], drzewa.);
drzewa.("dąb");
Sprawdź, czy tablica zawiera napis, i znajdź jego pozycję.
console.log(drzewa.("lipa"));
const gdzie = drzewa.("wierzba");
Odczyt ostatniego elementu tablicy zwraca undefined, bo indeksy liczymy od zera. Popraw wyrażenie.
Utwórz nową tablicę podwojonych liczb oraz tablicę liczb większych od 15.
const liczby = [10, 20, 30];
const podwojone = liczby.(x => x * 2);
const duze = liczby.(x => x 15);
Część A, lekcja 8
Obiekty w JavaScript
Obiekt grupuje powiązane dane jako pary klucz: wartość, np. jedną wycieczkę czy jednego pacjenta. W arkuszach dane najczęściej mają postać tablicy obiektów, po której przechodzisz pętlą.
const wycieczki = [
{ obraz: "img/1.svg", miejsce: "Barcelona" },
{ obraz: "img/2.svg", miejsce: "Rzym" },
{ obraz: "img/3.svg", miejsce: "Londyn" }
];
console.log(wycieczki[1].miejsce); // Rzym
wycieczki.forEach(w => console.log(w.miejsce, w.obraz));
const pacjent = {
imie: "Agnieszka",
nazwisko: "Nowak",
recepty: [
{ data: "8.03.2025", kod: "1220", lek1: "Witamina C", lek2: "Potas", lek3: "" },
{ data: "13.05.2025", kod: "2913", lek1: "Melatonina", lek2: "", lek3: "" }
]
};
console.log(pacjent.recepty[0].lek1, pacjent["imie"], pacjent.recepty.length);
| Operacja | Zapis |
|---|---|
| odczyt własności | o.nazwa lub o["nazwa"] (druga postać także ze zmienną: o[klucz]) |
| zmiana lub dodanie własności | o.cena = 20; |
| sprawdzenie klucza | "cena" in o |
| klucze i wartości | Object.keys(o), Object.values(o) |
| obiekt w tablicy, tablica w obiekcie | pacjent.recepty[0].lek1 – czytaj od lewej do prawej |
Przy kluczu zapisanym w zmiennej nie możesz użyć kropki: o.klucz szuka własności o nazwie „klucz”. Poprawnie: o[klucz].
Jak odczytać pierwszy lek z drugiej recepty pacjenta?
Pokaż przykładową odpowiedź
pacjent.recepty[1].lek1 – indeksy zaczynają się od 0.
Jak przejść po wszystkich obiektach tablicy wycieczki i wypisać miejsce?
Pokaż przykładową odpowiedź
wycieczki.forEach(w => console.log(w.miejsce)); lub for (const w of wycieczki) ....
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Utwórz obiekt wycieczki i odczytaj jego własności na dwa sposoby.
const wycieczka = { obraz: "img/1.svg", miejsce: "Barcelona" };
console.log(wycieczkamiejsce);
console.log(wycieczka);
Wypisz miejsce każdej wycieczki z tablicy obiektów.
const wycieczki = [{ miejsce: "Rzym" }, { miejsce: "Londyn" }];
wycieczki.(w => console.log(w));
Odczyt pierwszego leku z drugiej recepty pacjenta jest zapisany błędnie. Popraw wyrażenie (indeksy zaczynają się od 0).
Klucz jest zapisany w zmiennej, ale kropka szuka własności o nazwie „klucz”. Popraw odczyt.
Część A, lekcja 9
JSON i dane wklejone z pliku
W arkuszach dane często dostajesz w pliku tekstowym (dane.json, do_strony.txt) – wklejasz je do skryptu jako gotową strukturę. Zapis JSON jest bardzo podobny do obiektów JavaScript.
// 1. struktura wklejona do skryptu jako zmienna
const dane = {
"id": "1",
"imie": "Agnieszka",
"recepty": [
{ "id": "0", "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop" },
{ "id": "1", "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": "" }
]
};
console.log(dane.recepty.length); // 2
// 2. zamiana napisu JSON na obiekt i odwrotnie
const napis = '{"nazwa": "Ala", "oceny": [5, 4]}';
const obiekt = JSON.parse(napis);
console.log(obiekt.oceny[0]); // 5
console.log(JSON.stringify(obiekt)); // {"nazwa":"Ala","oceny":[5,4]}
- W JSON klucze i teksty są w podwójnych cudzysłowach, nie ma komentarzy, a ostatni element listy nie ma przecinka na końcu.
- Gdy w treści zadania napisano, że tablica może zostać rozbudowana o nowe elementy, skrypt musi używać pętli po
lengthtablicy (a nie na sztywno trzech elementów) – inaczej straci punkty przy sprawdzaniu z innymi danymi. - Wartości mogą być puste (
"") – należy je pominąć w wyniku (patrz wzorzec „recepty”).
Gdy dane pochodzą z serwera, pobierasz je funkcją fetch() i zamieniasz przez .json(); w prostych arkuszach egzaminacyjnych wystarcza wklejona struktura.
Co oznacza wymaganie, że w tablicy mogą pojawić się nowe elementy?
Pokaż przykładową odpowiedź
Skrypt ma działać dla dowolnej liczby elementów, więc trzeba użyć pętli po całej tablicy (forEach, for...of, length), a nie odwoływać się do indeksów na sztywno.
Czym różni się obiekt JavaScript od zapisu JSON?
Pokaż przykładową odpowiedź
JSON to tekstowy format danych z kluczami i napisami w podwójnych cudzysłowach, bez funkcji i komentarzy; obiekt JS jest strukturą w pamięci. JSON.parse i JSON.stringify zamieniają jedno na drugie.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Zamień tekst JSON na obiekt oraz obiekt na tekst.
const tekst = '{"miejsce":"Rzym","cena":300}';
const dane = JSON.(tekst);
console.log(dane.cena);
const z_powrotem = JSON.(dane);
Ten tekst nie jest poprawnym JSON-em: klucze i napisy muszą być w cudzysłowach. Popraw tekst.
Dane wklejone z pliku to tablica obiektów; wypisz imię i nazwisko każdego pacjenta.
const pacjenci = [{ imie: "Anna", nazwisko: "Nowak" }, { imie: "Jan", nazwisko: "Kot" }];
(const p pacjenci) {
console.log(`${p.imie} ${p.nazwisko}`);
}
Po odczytaniu JSON-u zmienna jest nadal tekstem, więc odwołanie do własności zwraca undefined. Popraw kod.
Zadanie praktyczne
Funkcje, tablice i obiekty: statystyki oceny
Zadanie
Przygotuj stronę, która po wczytaniu wylicza i wypisuje statystyki ocen ucznia z tablicy obiektów. Układ zrób według własnego pomysłu, ale zachowaj wymagania poniżej.
Założenia
- Tablica obiektów
przedmioty: nazwa przedmiotu i tablica ocen (min. 4 przedmioty, jeden z pustą tablicą ocen). - Funkcja
sredniaPrzedmiotu(oceny)zwraca średnią lub0dla pustej tablicy; funkcjanajlepszyPrzedmiot()zwraca nazwę przedmiotu z najwyższą średnią. - Po wczytaniu strony skrypt wpisuje w paragrafie z
id="wynik"tekst „Najlepszy przedmiot: <nazwa> (średnia <wartość>)” z średnią zaokrągloną do dwóch miejsc po przecinku. - Dodaj przycisk „Dodaj ocenę 5 do matematyki” z atrybutem
onclick; po kliknięciu ocena trafia do tablicy, a wynik zostaje wyliczony ponownie (bez przeładowania strony). - Kod w osobnym pliku podłączonym z
defer; nazwy zmiennych i funkcji po polsku; brak błędów w konsoli.
Ocenie podlegać będzie
- poprawność obliczeń i obsługa pustej tablicy,
- podział na funkcje z parametrami,
- poprawne dołączenie skryptu i wywołanie z HTML,
- znaczące nazwy i czytelny kod.
Wskazówki
- Zaokrąglenie:
toFixed(2). - Wywołaj funkcję wyliczającą wynik najpierw przy ładowaniu, a potem po kliknięciu przycisku.
- Lekcje 5 i 6.
Część B
DOM, zdarzenia i formularze
Wyszukiwanie i zmiana elementów, style i klasy, zdarzenia, tworzenie elementów, pola formularzy, liczby i daty oraz localStorage.
Część B, lekcja 10
DOM: wyszukiwanie elementów i odczyt wartości
DOM (Document Object Model) to drzewo obiektów reprezentujące stronę. Skrypt „widzi” stronę przez obiekt document i może odczytać oraz zmienić każdy element. Do wyszukiwania w zadaniach egzaminacyjnych wystarczą trzy metody:
| Metoda | Zwraca | Przykład |
|---|---|---|
document.querySelector(selektor) | pierwszy pasujący element lub null | querySelector("#wynik"), (".obraz"), ("ul"), ("input[type='range']") |
document.querySelectorAll(selektor) | wszystkie pasujące (lista, po której można użyć forEach) | querySelectorAll("input[name='wyzywienie']") |
document.getElementById(id) | element o danym identyfikatorze (bez #) | getElementById("prawy2") |
Selektor w querySelector jest taki sam jak w CSS: #id, .klasa, znacznik, znacznik.klasa, rodzic potomek, [atrybut='wartość'], :checked.
| Co odczytać / zmienić | Właściwość | Przykład |
|---|---|---|
| tekst (bez HTML) | textContent | wynik.textContent = "Gotowe" |
| zawartość z HTML | innerHTML | blok.innerHTML = "<h2>Tytuł</h2>" |
| wartość pola formularza | value | const wzrost = Number(pole.value) |
| źródło obrazu, adres | src, href | obraz.src = "img/rower2.svg" |
| dowolny atrybut | getAttribute(), setAttribute() | img.setAttribute("alt", "miniatura") |
| zaznaczenie pola wyboru / radio | checked | if (zgoda.checked) { ... } |
| blokada pola | disabled | pole.disabled = true |
<input type="text" id="imie">
<button onclick="przywitaj()">Przywitaj</button>
<p id="powitanie"></p>
<script>
function przywitaj() {
const imie = document.querySelector("#imie").value; // odczyt
const akapit = document.querySelector("#powitanie");
akapit.textContent = `Cześć, ${imie}!`; // zapis
}
</script>
innerHTML interpretuje wstawiony napis jako HTML. Jeśli wstawiasz tekst wpisany przez użytkownika, użyj textContent (zapobiega atakom XSS). W zadaniach egzaminacyjnych generujących własne elementy z danych w skrypcie innerHTML jest dopuszczalny.
Czym różni się querySelector od querySelectorAll?
Pokaż przykładową odpowiedź
querySelector zwraca pierwszy pasujący element (lub null), a querySelectorAll – listę wszystkich pasujących elementów.
Jak odczytasz liczbę wpisaną w polu type="number" o id wzrost jako liczbę, a nie napis?
Pokaż przykładową odpowiedź
Number(document.querySelector("#wzrost").value) lub parseInt(...).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Znajdź element o identyfikatorze wynik, wszystkie elementy o klasie miniatura i pierwszy z nich.
const wynik = document.("wynik");
const miniatury = document.(".miniatura");
const pierwsza = document.(".miniatura");
Odczytaj wartość pola tekstowego o identyfikatorze imie i wstaw tekst do akapitu.
const imie = document.getElementById("imie").;
document.querySelector("p"). = "Witaj, " + imie;
Selektor klasy w querySelector wymaga kropki, a identyfikatora – znaku #. Popraw oba selektory.
Pętla ma ustawić tekst „x” w każdej miniaturze, ale querySelector zwraca tylko jeden element. Popraw kod.
Część B, lekcja 11
Style, klasy i stan elementów z poziomu JavaScript
Skrypt może zmieniać wygląd elementów przez właściwość style (pojedyncze style inline) lub przez classList (przełączanie klas zdefiniowanych w CSS). W arkuszach egzaminacyjnych wymagane bywa jedno albo drugie – czytaj dokładnie: „przez zastosowanie odpowiedniej właściwości CSS”.
const okno = document.querySelector(".okno");
okno.style.display = "block"; // pokaż (element wcześniej: display: none w CSS)
okno.style.display = "none"; // ukryj, element nie zajmuje miejsca
okno.style.visibility = "hidden"; // ukryj, ale miejsce zostaje
okno.style.visibility = "visible";
const przycisk = document.querySelector("#uczestnikBtn");
przycisk.style.backgroundColor = "dodgerblue"; // właściwości CSS w camelCase: background-color → backgroundColor
przycisk.style.color = "#ffffff";
przycisk.style.fontSize = "150%";
przycisk.classList.add("aktywny"); // dodaj klasę
przycisk.classList.remove("aktywny"); // usuń klasę
przycisk.classList.toggle("aktywny"); // przełącz
console.log(przycisk.classList.contains("aktywny"));
| CSS | JavaScript (style) |
|---|---|
background-color | style.backgroundColor |
font-size | style.fontSize |
border-radius | style.borderRadius |
display, visibility, opacity | style.display, style.visibility, style.opacity |
z-index | style.zIndex |
Blokowanie pól formularza
function zmienSekcje(wybrana) {
const pola1 = document.querySelectorAll("#sekcja1 input");
const pola2 = document.querySelectorAll("#sekcja2 input, #sekcja2 select");
const uczestnik = wybrana === "uczestnik";
pola1.forEach(p => p.disabled = !uczestnik); // true = pole nieaktywne
pola2.forEach(p => p.disabled = uczestnik);
document.querySelector("#uczestnikBtn").style.backgroundColor = uczestnik ? "dodgerblue" : "skyblue";
document.querySelector("#rezerwacjaBtn").style.backgroundColor = uczestnik ? "skyblue" : "dodgerblue";
}
display: none usuwa element z układu strony (pozostałe elementy się przesuwają), a visibility: hidden tylko go ukrywa. Arkusz zwykle precyzuje: „staje się ukryty” albo „zostaje usunięty zastosowaniem właściwości CSS”. W razie wątpliwości użyj tej właściwości, którą arkusz wymienia przy pierwszym pojawieniu się elementu (np. display: none w CSS bloku okna).
Jak zapiszesz w JavaScript właściwość CSS background-color?
Pokaż przykładową odpowiedź
element.style.backgroundColor = "kolor" (camelCase).
Jak zablokujesz pole formularza?
Pokaż przykładową odpowiedź
Ustawiając pole.disabled = true (odblokowanie: false).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Ukryj okno, pokaż je i zmień kolor tła elementu.
const okno = document.querySelector(".okno");
okno.style. = "none";
okno.style.display = "";
okno.style. = "lightblue";
Dodaj klasę, usuń klasę i przełącz klasę elementu.
el.classList.("aktywny");
el.classList.("aktywny");
el.classList.("aktywny");
W JavaScript nazwy właściwości stylu zapisujemy w camelCase, a wartości jako napisy. Popraw przypisanie.
Pole ma zostać wyłączone, a przycisk ukryty, ale zapisy są niepoprawne. Popraw kod.
Część B, lekcja 12
Zdarzenia: onclick, addEventListener, onchange
Zdarzenie to sygnał, że coś się stało (kliknięcie, zmiana wartości, wczytanie strony). Program przypisuje do zdarzenia funkcję, która ma się wykonać.
| Sposób | Przykład | Kiedy |
|---|---|---|
| atrybut w HTML | <button onclick="zamknijOkno()"> | najkrócej; często wymagany przez arkusz („kliknięcie wywołuje funkcję”) |
| właściwość obiektu | przycisk.onclick = zamknijOkno; | bez nawiasów po nazwie funkcji |
addEventListener | przycisk.addEventListener("click", zamknijOkno); | zalecany; wiele funkcji na jedno zdarzenie |
| Zdarzenie | Kiedy zachodzi | Typowy użytek na egzaminie |
|---|---|---|
click (onclick) | kliknięcie myszą | przyciski, obrazy, komórki tabeli, bloki z potrawami |
change (onchange) | zatwierdzenie zmiany wartości (suwak po puszczeniu, lista po wyborze) | pola formularza |
input (oninput) | każda zmiana wartości w trakcie (np. przesuwanie suwaka) | suwak zsynchronizowany z polem liczbowym |
load, DOMContentLoaded | wczytanie strony / zbudowanie drzewa DOM | licznik odwiedzin, wypisanie daty, generowanie bloków |
mouseover, mouseout | wejście i wyjście kursora | efekty najechania |
keydown | wciśnięcie klawisza | sterowanie klawiaturą |
const suwak = document.querySelector("input[type='range']");
suwak.addEventListener("input", function (e) {
console.log("Nowa wartość:", e.target.value); // e.target = element, na którym zaszło zdarzenie
});
document.addEventListener("DOMContentLoaded", function () {
console.log("Strona wczytana");
});
// wykonanie funkcji po załadowaniu strony – dwa równoważne sposoby
window.onload = aktualnaData;
document.addEventListener("DOMContentLoaded", aktualnaData); // bez nawiasów!
Arkusz „wykonywany po zmianie wartości pola zakresu liczbowego (po przesunięciu suwaka)” spełni zarówno oninput (na bieżąco), jak i onchange (po puszczeniu). Wybierz oninput, jeśli wartość ma się zmieniać w trakcie przesuwania.
Czym różnią się zdarzenia input i change na suwaku?
Pokaż przykładową odpowiedź
input zachodzi cały czas podczas przesuwania suwaka, a change dopiero po jego puszczeniu (zatwierdzeniu wartości).
Jak uruchomić funkcję po załadowaniu strony?
Pokaż przykładową odpowiedź
document.addEventListener("DOMContentLoaded", funkcja) lub window.onload = funkcja (bez nawiasów po nazwie funkcji) albo wywołać ją na końcu skryptu umieszczonego na końcu body.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Obsłuż kliknięcie przycisku za pomocą addEventListener.
const przycisk = document.querySelector("#przycisk");
przycisk.("", function () {
alert("Kliknięto");
});
Wywołaj funkcję po zmianie wyboru w liście i po wpisaniu tekstu w polu.
<select ="przelicz()">...</select>
<input type="text" ="szukaj()">
Obsługa zdarzenia ma odczytać klikniętą komórkę, ale funkcja nie ma parametru zdarzenia. Popraw funkcję, aby korzystała z event.target.
W atrybucie onclick brakuje nawiasów, więc funkcja się nie wykona, a argument tekstowy ma niepoprawne cudzysłowy. Popraw znacznik.
Część B, lekcja 13
Tworzenie elementów DOM i generowanie zawartości
Dwa sposoby generowania zawartości strony ze skryptu: (1) składanie napisu HTML i wstawienie go przez innerHTML, (2) tworzenie węzłów przez createElement. Arkusz czasem wymaga drugiego („Element DOM dla nagłówka…”, „dodaje element do listy”).
const lista = document.querySelector("ul");
const nowy = document.createElement("li"); // utwórz <li>
nowy.textContent = "naleśniki"; // wypełnij treścią
nowy.classList.add("pozycja"); // przypisz klasę
lista.append(nowy); // dodaj na końcu listy (appendChild też działa)
lista.innerHTML = ""; // wyczyść całą zawartość listy
document.querySelector("li").remove(); // usuń element
const sekcja = document.querySelector("#prawy2");
dane.recepty.forEach(recepta => {
let leki = "";
if (recepta.lek1 !== "") leki += `<li>${recepta.lek1}</li>`;
if (recepta.lek2 !== "") leki += `<li>${recepta.lek2}</li>`;
if (recepta.lek3 !== "") leki += `<li>${recepta.lek3}</li>`;
sekcja.innerHTML += `
<div class="recepta">
<p>Data wystawienia: ${recepta.data}</p>
<ol>${leki}</ol>
<h4>Kod: ${recepta.kod}</h4>
</div>`;
});
- Szablon napisu w odwrotnych apostrofach (
`...`) może zajmować wiele linii i wstawia wartości przez${...}– to najwygodniejszy sposób budowania HTML. +=nainnerHTMLdopisuje na końcu;=zastępuje całą zawartość.- Klasa elementu z arkusza (np.
recepty) musi być dokładnie taka sama jak w poleceniu – CSS już jest do niej przygotowany. - Po
createElementelement nie jest jeszcze na stronie – widać go dopiero poappend/appendChild.
Jak dodać element li o treści „pierogi” na koniec listy ul?
Pokaż przykładową odpowiedź
const li = document.createElement("li"); li.textContent = "pierogi"; document.querySelector("ul").append(li);
Jak wyczyścić zawartość listy?
Pokaż przykładową odpowiedź
lista.innerHTML = "";
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Utwórz element listy z tekstem i dołącz go do listy o identyfikatorze lista.
const li = document.("li");
li. = "Gitara";
document.getElementById("lista").(li);
Wygeneruj bloki z danych za pomocą szablonu tekstowego i dopisz je do kontenera.
const dane = [{ nazwa: "Rzym" }, { nazwa: "Paryż" }];
const kontener = document.querySelector(".galeria");
dane.forEach(d => {
kontener.innerHTML <div class="blok">${d.nazwa}</div>;
});
Element jest utworzony, ale nie pojawia się na stronie, bo nie został dołączony do dokumentu. Dodaj brakującą instrukcję.
W nazwie metody jest literówka, a obraz nie ma ustawionego źródła. Popraw kod tak, aby powstał obraz z plikiem rower.svg.
Część B, lekcja 14
Formularze w JavaScript: liczby, radio, listy i suwaki
// pole liczbowe i suwak
const suwak = document.querySelector("input[type='range']");
const liczba = document.querySelector("input[type='number']");
liczba.value = suwak.value; // synchronizacja suwaka z polem
// radio: zaznaczona opcja z grupy o wspólnym name
const wybrany = document.querySelector("input[name='rodzaj']:checked");
console.log(wybrany.value); // value zaznaczonego przycisku
// lista rozwijana
const lista = document.querySelector("select");
console.log(lista.value, lista.options[lista.selectedIndex].text);
// pole wyboru
const zgoda = document.querySelector("#zgoda");
console.log(zgoda.checked); // true / false
// pole tekstowe
const szukane = document.querySelector("#szukaj").value.trim().toLowerCase();
const opcje = document.querySelectorAll("input[name='rodzaj']");
let wybranyRodzaj = "";
opcje.forEach(opcja => {
if (opcja.checked) wybranyRodzaj = opcja.value;
});
| Pole | Odczyt wartości | Uwagi |
|---|---|---|
text, number, range, date | pole.value (napis) | liczby zamień przez Number() lub parseInt() |
radio | document.querySelector("input[name='x']:checked").value | jeśli żadne nie jest zaznaczone, wynik to null – zabezpiecz warunkiem |
checkbox | pole.checked | wartość logiczna |
select | lista.value | wartość atrybutu value wybranej opcji |
W grupie radio value musi być ustawione w HTML (<input type="radio" name="rodzaj" value="szosa">), bo to ono trafia do skryptu. Etykieta obok pola nie jest wartością.
Jak odczytać wybraną opcję z grupy przycisków radio o nazwie rodzaj?
Pokaż przykładową odpowiedź
document.querySelector("input[name='rodzaj']:checked").value.
Jak zsynchronizować pole liczbowe z suwakiem?
Pokaż przykładową odpowiedź
W obsłudze zdarzenia input suwaka przypisać poleLiczbowe.value = suwak.value.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Odczytaj liczbę z pola, wybraną opcję z listy i sprawdź pole wyboru.
const ile = (document.getElementById("ile").value);
const kolor = document.getElementById("kolor").;
const zgoda = document.getElementById("zgoda").;
Odczytaj zaznaczony przycisk radio z grupy o nazwie rozmiar.
const rozmiar = document.querySelector("input[name='rozmiar']").;
Wartość suwaka jest tekstem, więc dodawanie skleja napisy. Zamień ją na liczbę, aby suma była liczbą.
Wyświetlana wartość suwaka nie zmienia się podczas przesuwania, bo użyto zdarzenia zmiany zamiast zdarzenia na bieżąco. Popraw nazwę zdarzenia.
Część B, lekcja 15
Liczby, zaokrąglanie i daty
| Zadanie | Zapis |
|---|---|
| zaokrąglenie do całości | Math.round(x); w dół Math.floor(x), w górę Math.ceil(x) |
| zaokrąglenie do 2 miejsc (jako napis) | x.toFixed(2) |
| zamiana napisu na liczbę | Number("12,5".replace(",", ".")) – przecinek zamień na kropkę |
| maksimum, minimum, potęga, pierwiastek | Math.max(a, b), Math.min(), Math.pow(a, b), Math.sqrt() |
| liczba losowa całkowita 1–6 | Math.floor(Math.random() * 6) + 1 |
// rozmiar ramy [cale] = wzrost [cm] × współczynnik ÷ 2,54, zaokrąglony do całości
function obliczRozmiarRamy() {
const wzrost = Number(document.querySelector("input[type='number']").value);
const rodzaj = document.querySelector("input[name='rodzajRoweru']:checked").value;
let wspolczynnik = 0.26; // górski
if (rodzaj === "szosa") wspolczynnik = 0.3;
if (rodzaj === "trekking") wspolczynnik = 0.28;
const rozmiar = Math.round((wzrost * wspolczynnik) / 2.54);
document.querySelector("#wynik").textContent = `Zalecany rozmiar ramy to: ${rozmiar} cali`;
}
function aktualnaData() {
const dzis = new Date();
const dzien = String(dzis.getDate()).padStart(2, "0"); // 5 → "05"
const miesiac = String(dzis.getMonth() + 1).padStart(2, "0"); // miesiące liczone od 0!
const rok = dzis.getFullYear();
document.querySelector("#komorkaDaty").textContent = `${dzien}.${miesiac}.${rok}`;
}
aktualnaData();
getMonth() zwraca liczbę od 0 (styczeń) do 11 (grudzień), więc do wyświetlenia trzeba dodać 1. getDay() zwraca dzień tygodnia (0 = niedziela), a dzień miesiąca daje getDate().
Jak zapisać w JavaScript dzisiejszą datę jako 07.03.2026?
Pokaż przykładową odpowiedź
Pobrać new Date(), dzień i miesiąc (getMonth() + 1) uzupełnić zerem przez String(x).padStart(2, "0") i złożyć `${dzien}.${miesiac}.${rok}`.
Jak zaokrąglić wynik 61,6 do liczby całkowitej?
Pokaż przykładową odpowiedź
Math.round(61.6) daje 62.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Zaokrąglij liczbę do całości i wyświetl ją z dwoma miejscami po przecinku.
console.log(Math.(3.6));
console.log((2.5).(2));
Pobierz bieżącą datę, rok i numer miesiąca (miesiące liczone są od zera).
const dzis = new ();
const rok = dzis.();
const miesiac = dzis.getMonth() ;
Liczba dni między datami jest błędna, bo różnica jest wyrażona w milisekundach. Przelicz ją na dni.
Wynik ma mieć dwa miejsca po przecinku, ale funkcja jest wywołana na całej wartości jak zwykła funkcja. Popraw zapis.
Część B, lekcja 16
localStorage, sessionStorage i alerty
function licznik() {
let liczba = localStorage.getItem("odwiedziny"); // napis lub null
liczba = liczba === null ? 0 : parseInt(liczba);
liczba++;
localStorage.setItem("odwiedziny", liczba);
const stopka = document.querySelector("#licznikWejsc");
if (stopka) stopka.textContent = `Liczba wejść na stronę: ${liczba}`;
}
document.addEventListener("DOMContentLoaded", licznik); // bez nawiasów!
| Mechanizm | Czas życia | Zasięg |
|---|---|---|
localStorage | bez ograniczenia czasu (do ręcznego usunięcia) | wszystkie karty tej samej witryny (domena + protokół + port) |
sessionStorage | do zamknięcia karty | tylko dana karta |
ciasteczka (document.cookie) | ustawiany datą ważności | wysyłane do serwera z każdym żądaniem |
- Metody:
setItem(klucz, wartość),getItem(klucz),removeItem(klucz),clear(). Wartości są zawsze napisami, więc liczbę zamieniasz przezparseInt/Number. - Obiekty i tablice zapisujesz przez
JSON.stringify, odczytujesz przezJSON.parse. - Zawartość podglądniesz w DevTools: Application → Local Storage (przydatne do zerowania licznika podczas testów).
- Okna dialogowe:
alert("Tekst")– komunikat,confirm("Na pewno?")– zwracatrue/false,prompt("Podaj imię")– zwraca wpisany napis lubnull.
Przy pierwszym uruchomieniu getItem zwraca null; parseInt(null) to NaN i licznik się zepsuje. Zawsze obsłuż przypadek braku wartości (jak w przykładzie).
Co zwróci localStorage.getItem("klucz"), gdy takiego klucza nie zapisano?
Pokaż przykładową odpowiedź
Wartość null.
Jak zapisać w localStorage tablicę obiektów?
Pokaż przykładową odpowiedź
localStorage.setItem("lista", JSON.stringify(tablica)), a odczytać JSON.parse(localStorage.getItem("lista")).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Zapisz wartość w localStorage, odczytaj ją i usuń.
localStorage.("imie", "Anna");
const imie = localStorage.("imie");
localStorage.("imie");
Zapisz w localStorage tablicę (jako tekst JSON) i odczytaj ją z powrotem.
localStorage.setItem("koszyk", JSON.(koszyk));
const koszyk2 = JSON.(localStorage.getItem("koszyk"));
Do localStorage można zapisać tylko tekst, więc tablica jest zapisana jako „[object Object]”. Zamień obiekt na tekst JSON.
Wyświetl komunikat i zapytaj użytkownika o potwierdzenie.
("Zamówienie przyjęte");
if (("Czy na pewno usunąć?")) {
console.log("usunięto");
}
Zadanie praktyczne
Mini-aplikacja: kalkulator zamówienia
Zadanie
Wykonaj stronę „Zamów pizzę”. Układ i style przygotuj samodzielnie, a skrypty napisz według wymagań.
Założenia
- Formularz: pole
number„Liczba osób” (1–10) z powiązanym suwakiemrange(1–10), gruparadio„Rozmiar” (mała 20 zł, średnia 28 zł, duża 36 zł) i lista rozwijana „Dodatek” (brak 0 zł, ser 4 zł, szynka 6 zł). - Skrypt 1 (po przesunięciu suwaka): wpisuje wartość suwaka do pola liczbowego. Skrypt 2 (po wpisaniu liczby w polu): ustawia suwak na tę wartość.
- Skrypt 3 (po kliknięciu „Oblicz”): koszt = (cena rozmiaru + cena dodatku) × liczba osób; wynik w akapicie w formacie „Do zapłaty: 64.00 zł” (dwa miejsca po przecinku). Jeśli nie wybrano rozmiaru – wypisz „Wybierz rozmiar”.
- Skrypt 4 (po załadowaniu strony): w stopce wypisuje datę w formacie DD.MM.RRRR oraz zwiększa i pokazuje licznik wizyt zapisany w
localStorage. - Wszystkie funkcje mają znaczące nazwy po polsku; nie wolno zmieniać nazw klas i identyfikatorów podanych w projekcie.
Ocenie podlegać będzie
- poprawna synchronizacja suwaka i pola,
- poprawny odczyt radio i listy oraz obliczenia,
- formatowanie wyniku i obsługa braku wyboru,
- data i licznik w localStorage,
- czytelność kodu.
Wskazówki
- Pole
numberi suwak: użyj zdarzeniaoninputw obu elementach. - Cena dodatku:
Number(select.value)– ustawvaluew opcjach. - Lekcje 12–14.
Część C
Wzorce zadań egzaminacyjnych
Sześć kompletnych wzorców (galeria z oknem, przełączanie sekcji i karuzela, lista zamówienia, generowanie z danych, kalkulator, plansza gry) oraz lista kontrolna i debugowanie.
Część C, lekcja 17
Wzorzec 1: galeria z podmianą obrazu i oknem powiększenia
Sytuacja z arkusza: karta produktu ma obraz główny i trzy miniatury. Kliknięcie miniatury podmienia obraz główny; kliknięcie obrazu głównego otwiera okno z jego powiększeniem; kliknięcie znaku × zamyka okno. Okno ma być ukryte stylem CSS, a skrypt zmienia sposób jego wyświetlania. Pliki do ćwiczenia: js-galeria.zip (obrazy rower1–3).
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Karta produktu</title>
<link rel="stylesheet" href="styl.css">
<script src="main.js" defer></script>
</head>
<body>
<header><h1>Rower miejski</h1></header>
<main>
<section>
<img class="obraz" src="img/rower1.svg" alt="rower" onclick="otworzOkno()">
<div>
<img class="miniatury" src="img/rower1.svg" alt="miniatura" onclick="podmienObraz('rower1.svg')">
<img class="miniatury" src="img/rower2.svg" alt="miniatura" onclick="podmienObraz('rower2.svg')">
<img class="miniatury" src="img/rower3.svg" alt="miniatura" onclick="podmienObraz('rower3.svg')">
</div>
</section>
<article>
<h2>Rower miejski Eco</h2>
<p>Lekki rower z koszykiem i błotnikami.</p>
</article>
</main>
<div class="okno">
<span class="zamknij" onclick="zamknijOkno()">×</span>
<img class="obrazOkno" alt="powiększenie">
</div>
</body>
</html>
.obraz { width: 40%; cursor: zoom-in; }
.miniatury { width: 15%; cursor: pointer; }
.okno {
display: none; /* ukryte na starcie – skrypt zmieni na block */
position: fixed; /* względem okna przeglądarki */
top: 0;
left: 0;
width: 80%;
height: 100%;
z-index: 10; /* zawsze na wierzchu */
background-color: rgba(0, 0, 0, 0.7); /* czarne tło z przezroczystością */
}
.obrazOkno { display: block; margin: 40px auto; max-width: 80%; } /* blokowy, środek */
.zamknij {
position: absolute; /* względem pierwszego pozycjonowanego rodzica (.okno) */
top: 15px;
right: 35px;
font-size: 40px;
font-weight: bold;
color: beige;
}
.zamknij:hover { cursor: pointer; }
function podmienObraz(nazwaPliku) {
const obrazGlowny = document.querySelector(".obraz");
obrazGlowny.src = `img/${nazwaPliku}`;
}
function otworzOkno() {
const obrazGlowny = document.querySelector(".obraz");
const okno = document.querySelector(".okno");
const obrazOkno = document.querySelector(".obrazOkno");
okno.style.display = "block"; // zmiana sposobu wyświetlania bloku okna na blokowy
obrazOkno.src = obrazGlowny.src; // źródło obrazu z okna = źródło obrazu głównego
}
function zamknijOkno() {
document.querySelector(".okno").style.display = "none";
}
Dlaczego to działa
- Obraz główny i miniatury mają różne klasy (
obraz,miniatury), więcquerySelector(".obraz")trafia zawsze w obraz główny. obrazGlowny.srczwraca pełny adres (np.http://localhost/img/rower2.svg) – można go bezpośrednio przypisać do drugiego obrazu.- Ukrycie okna w CSS (
display: none) i pokazanie w JS (display = "block") to dokładnie to, o co prosi arkusz („zmiana sposobu wyświetlania bloku okna”). - Krzyżyk
×to znak ×, a jego położenie względem okna zapewniaposition: absolute.
style.display = "visible" (taka wartość nie istnieje – poprawnie block), brak średnika lub cudzysłowu w ścieżce img/${...}, zmiana nazw klas z arkusza, próba użycia id tam, gdzie arkusz wymaga klasy.
Którą właściwością CSS ukryjesz okno początkowo, aby skrypt mógł je pokazać?
Pokaż przykładową odpowiedź
display: none; w stylach klasy okna; skrypt zmieni na block.
Dlaczego źródło obrazu głównego można przypisać obrazowi z okna bez dopisywania ścieżki?
Pokaż przykładową odpowiedź
Bo właściwość src elementu img zwraca pełny adres obrazu, który jest poprawnym źródłem dla każdego innego obrazu.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Podmień obraz główny po kliknięciu miniatury (nazwa pliku jest argumentem).
function podmienObraz(plik) {
document.querySelector(".obraz"). = ;
}
Otwórz okno powiększenia, a po kliknięciu przycisku zamknięcia ukryj je.
function otworz() {
document.querySelector(".okno").style.display = "";
}
function zamknij() {
document.querySelector(".okno").style.display = "";
}
document.querySelector(".zamknij"). = zamknij;
Wszystkie miniatury mają reagować na kliknięcie, ale po wczytaniu strony obraz jest podmieniany od razu, bo funkcja jest wywoływana od razu zamiast zostać przypisana jako obsługa zdarzenia. Popraw kod.
Powiększony obraz ma pokazać opis z atrybutu alt kliknętego obrazka, ale kod odczytuje go z niewłaściwego obiektu. Popraw odwołanie.
Część C, lekcja 18
Wzorzec 2: przełączanie sekcji formularza i karuzela zdjęć
Sytuacja z arkusza: strona rezerwacji ma dwa przyciski („Uczestnik” i „Rezerwacja”) przełączające, która część formularza jest aktywna, oraz zmieniające kolor przycisków. Obok jest przeglądarka zdjęć z dwiema strzałkami: kolejne i poprzednie miejsce, z zawinięciem na końcach. Obrazy do ćwiczenia: js-wycieczki.zip.
<nav>
<button id="uczestnikBtn" onclick="zmienSekcje('uczestnik')">Uczestnik</button>
<button id="rezerwacjaBtn" onclick="zmienSekcje('rezerwacja')">Rezerwacja</button>
</nav>
<section id="sekcjaUczestnik">
<input type="text" id="imie" placeholder="Imię">
<input type="text" id="nazwisko" placeholder="Nazwisko">
</section>
<section id="sekcjaRezerwacja">
<input type="number" id="liczbaOsob" value="1" min="1">
<select id="miejsceWylotu"><option>Warszawa</option><option>Kraków</option></select>
<label><input type="radio" name="wyzywienie" value="bez"> bez</label>
<label><input type="radio" name="wyzywienie" value="pelne"> pełne</label>
</section>
<aside>
<img id="zdjecieMiejsca" src="img/1.svg" alt="zdjęcie miejsca">
<p id="miejsceWycieczki">Barcelona</p>
<button onclick="poprzedniaWycieczka()">←</button>
<button onclick="nastepnaWycieczka()">→</button>
</aside>
/* ---- przełączanie aktywnej części formularza ---- */
function zmienSekcje(wybrana) {
const uczestnik = wybrana === "uczestnik";
document.querySelectorAll("#sekcjaUczestnik input").forEach(p => p.disabled = !uczestnik);
document.querySelectorAll("#sekcjaRezerwacja input, #sekcjaRezerwacja select").forEach(p => p.disabled = uczestnik);
document.querySelector("#uczestnikBtn").style.backgroundColor = uczestnik ? "dodgerblue" : "skyblue";
document.querySelector("#rezerwacjaBtn").style.backgroundColor = uczestnik ? "skyblue" : "dodgerblue";
}
zmienSekcje("uczestnik"); // stan początkowy ustawiony w skrypcie
/* ---- przeglądarka zdjęć z zawinięciem ---- */
const wycieczki = [
{ obraz: "img/1.svg", miejsce: "Barcelona" },
{ obraz: "img/2.svg", miejsce: "Rzym" },
{ obraz: "img/3.svg", miejsce: "Londyn" }
];
let numerWycieczki = 0;
function pokazWycieczke() {
document.querySelector("#zdjecieMiejsca").src = wycieczki[numerWycieczki].obraz;
document.querySelector("#miejsceWycieczki").textContent = wycieczki[numerWycieczki].miejsce;
}
function nastepnaWycieczka() {
numerWycieczki++;
if (numerWycieczki >= wycieczki.length) numerWycieczki = 0; // po ostatniej – pierwsza
pokazWycieczke();
}
function poprzedniaWycieczka() {
numerWycieczki--;
if (numerWycieczki < 0) numerWycieczki = wycieczki.length - 1; // przed pierwszą – ostatnia
pokazWycieczke();
}
| Pułapka | Opis |
|---|---|
| indeks poza zakresem | bez zawinięcia po trzecim kliknięciu wycieczki[3] jest undefined i skrypt zgłasza błąd |
pole disabled a kolor | ustawiasz osobno disabled i style.backgroundColor; arkusz wymaga obu efektów |
| różna liczba elementów | pętlę po querySelectorAll zapisuj przez forEach, a nie przez indeksy na sztywno |
| kolejność wycieczek | arkusz podaje kolejność wstecz (Barcelona → Londyn → Rzym) – sprawdź krok po kroku, klikając strzałkę kilka razy |
Zamiast dwóch if możesz użyć reszty z dzielenia: numer = (numer + krok + ile) % ile, gdzie krok to +1 lub −1, a ile to długość tablicy.
Jak zapewnić, że po ostatniej wycieczce wyświetli się pierwsza?
Pokaż przykładową odpowiedź
Po zwiększeniu numeru sprawdzić if (numer >= wycieczki.length) numer = 0; lub użyć numer = (numer + 1) % wycieczki.length.
Jak zablokować wszystkie pola w jednej sekcji formularza?
Pokaż przykładową odpowiedź
Pobrać pola przez querySelectorAll("#sekcja input") i dla każdego ustawić disabled = true (forEach).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Pokaż tylko wybraną sekcję formularza: ukryj wszystkie, pokaż jedną.
function zmienSekcje(id) {
document.querySelectorAll(".sekcja").forEach(s => s.style.display = "");
document.getElementById(id).style.display = "";
}
Karuzela: przejdź do następnego zdjęcia, a po ostatnim wróć do pierwszego.
let numer = 0;
function dalej() {
numer = (numer + 1) zdjecia.;
obraz.src = zdjecia[numer];
}
Przycisk „wstecz” w karuzeli powoduje błąd po przejściu przed pierwsze zdjęcie (indeks −1). Popraw kod tak, aby po pierwszym zdjęciu wyświetlało się ostatnie.
Sekcja formularza ma pozostać ukryta, dopóki nie zostanie wybrana, ale zapis stylu jest błędny. Popraw kod.
Część C, lekcja 19
Wzorzec 3: lista zamówienia (createElement, alert, czyszczenie)
Sytuacja z arkusza: strona restauracji ma bloki z potrawami. Kliknięcie bloku dodaje nazwę potrawy do listy zamówienia, przycisk „Wyczyść” czyści listę, a „Zatwierdź” wyświetla komunikat i czyści listę. Obrazy: js-zamowienia.zip.
<main>
<section class="menu">
<div class="potrawa" onclick="dodajDoZamowienia('naleśniki')">
<img src="img/nalesniki.svg" alt="naleśniki"><h3>Naleśniki</h3>
</div>
<div class="potrawa" onclick="dodajDoZamowienia('pierogi')">
<img src="img/pierogi.svg" alt="pierogi"><h3>Pierogi</h3>
</div>
<div class="potrawa" onclick="dodajDoZamowienia('zupa dnia')">
<img src="img/zupa.svg" alt="zupa"><h3>Zupa dnia</h3>
</div>
</section>
<section class="zamowienie">
<h2>Twoje zamówienie</h2>
<ul></ul>
<button onclick="wyczyscZamowienie()">Wyczyść</button>
<button onclick="zatwierdzZamowienie()">Zatwierdź</button>
</section>
</main>
function dodajDoZamowienia(nazwaPotrawy) {
const lista = document.querySelector(".zamowienie ul");
const pozycja = document.createElement("li");
pozycja.textContent = nazwaPotrawy;
lista.append(pozycja);
}
function wyczyscZamowienie() {
document.querySelector(".zamowienie ul").innerHTML = "";
}
function zatwierdzZamowienie() {
const lista = document.querySelector(".zamowienie ul");
if (lista.children.length === 0) { // opcjonalne zabezpieczenie: pusta lista
alert("Zamówienie jest puste");
return;
}
alert("Zamówienie zostało przekazane do realizacji");
lista.innerHTML = "";
}
- Tekst alertu wpisz dokładnie jak w arkuszu (łącznie z polskimi znakami i bez dodatkowych znaków).
- Selektor
".zamowienie ul"jest bezpieczniejszy niż samo"ul", jeśli na stronie jest jeszcze inna lista (np. menu). lista.children.lengthto liczba elementów potomnych – przydaje się do sprawdzenia, czy lista jest pusta.- Rozszerzenie: zliczanie powtórzeń (kliknięto „pierogi” 2×) lub przycisk usuwania pojedynczej pozycji.
Jak dodać element li z napisem do istniejącej listy ul?
Pokaż przykładową odpowiedź
const li = document.createElement("li"); li.textContent = tekst; lista.append(li);
Jak sprawdzić, ile pozycji ma lista?
Pokaż przykładową odpowiedź
lista.children.length lub lista.querySelectorAll("li").length.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Dodaj do listy zamówienia nowy element z nazwą produktu.
function dodaj(nazwa) {
const li = document.createElement("li");
li.textContent = nazwa;
document.getElementById("zamowienie").(li);
}
Wyczyść listę zamówienia i pokaż komunikat.
function wyczysc() {
document.getElementById("zamowienie").innerHTML = ;
("Lista wyczyszczona");
}
Przed złożeniem zamówienia trzeba sprawdzić, czy lista nie jest pusta. Warunek w kodzie jest odwrócony. Popraw go.
Suma zamówienia powinna rosnąć o cenę produktu, ale po każdym dodaniu jest nadpisywana. Popraw kod.
Część C, lekcja 20
Wzorzec 4: generowanie bloków z danych i wyszukiwarka
Sytuacja z arkusza (recepty): w pliku jest struktura danych pacjenta. Skrypt ma wygenerować tyle bloków, ile jest recept; w każdym: data, lista numerowana leków (pomijamy puste) i nagłówek z kodem. Sytuacja z arkusza (atlas): dwie tablice (nazwy i opisy) – kliknięcie obrazu lub wpisanie nazwy generuje nagłówek i opis w bloku głównym.
const pacjent = {
imie: "Agnieszka",
recepty: [
{ data: "8.03.2025", kod: "1220", lek1: "Witamina C", lek2: "Potas", lek3: "Syrop prawoślazowy" },
{ data: "23.04.2025", kod: "4634", lek1: "APAP", lek2: "Witamina B", lek3: "" },
{ data: "13.05.2025", kod: "2913", lek1: "Melatonina", lek2: "", lek3: "" }
]
};
const sekcja = document.querySelector("#prawy2");
pacjent.recepty.forEach(recepta => {
let leki = "";
if (recepta.lek1 !== "") leki += `<li>${recepta.lek1}</li>`;
if (recepta.lek2 !== "") leki += `<li>${recepta.lek2}</li>`;
if (recepta.lek3 !== "") leki += `<li>${recepta.lek3}</li>`;
sekcja.innerHTML += `
<div class="recepty">
<p>Data wystawienia: ${recepta.data}</p>
<ol>${leki}</ol>
<h4>Kod: ${recepta.kod}</h4>
</div>`;
});
const drzewa = ["buk", "lipa", "wierzba", "dąb"];
const opisy = [
"Duże drzewo liściaste z gładką, szarą korą.",
"Drzewo o sercowatych liściach i pachnących kwiatach.",
"Rośnie nad wodą, ma długie, zwisające gałęzie.",
"Majestatyczne, długowieczne drzewo, owocuje żołędziami."
];
function wybierz(indeks) { // wywoływana z onclick="wybierz(0)" na obrazach
const blok = document.querySelector("main");
blok.innerHTML = ""; // usuń zawartość bloku głównego
const naglowek = document.createElement("h2");
naglowek.textContent = drzewa[indeks];
const akapit = document.createElement("p");
akapit.classList.add("opis");
akapit.textContent = opisy[indeks];
blok.append(naglowek, akapit); // append przyjmuje kilka elementów
}
function szukaj() { // onclick="szukaj()" na przycisku „Szukaj”
const wpisane = document.querySelector("#szukane").value.trim().toLowerCase();
if (drzewa.includes(wpisane)) {
wybierz(drzewa.indexOf(wpisane));
} else {
document.querySelector("main").innerHTML =
"<p>Drzewa, o którym chcesz znaleźć informacje, nie ma w naszym Atlasie drzew.</p>";
}
}
| Wymaganie arkusza | Jak je spełnić |
|---|---|
| „tyle bloków, ile elementów tablicy” | pętla forEach po tablicy, nigdy po stałej liczbie |
| „puste wpisy pomijamy” | warunek if (pole !== "") przed dodaniem <li> |
| „przypisana klasa” | nazwa klasy dokładnie jak w arkuszu (recepty, opis) |
| „usuwa zawartość bloku głównego” | blok.innerHTML = "" przed dodaniem nowych elementów |
| „Element DOM dla nagłówka…” | createElement("h2") i append (nie sam napis HTML) |
Gdy arkusz nie mówi inaczej, porównuj nazwy po trim().toLowerCase() – użytkownik może wpisać „Buk ” albo „BUK”. Tablica nazw musi wtedy zawierać tylko małe litery.
Jak pominąć puste pola lek2 i lek3 przy generowaniu listy leków?
Pokaż przykładową odpowiedź
Przed dodaniem elementu sprawdzić warunek if (recepta.lek2 !== "") i tylko wtedy dopisać <li>.
Jak znaleźć opis drzewa o nazwie wpisanej w polu, korzystając z dwóch tablic?
Pokaż przykładową odpowiedź
Znaleźć indeks nazwy w tablicy nazw (indexOf), a opis odczytać z tablicy opisów pod tym samym indeksem.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Wygeneruj blok HTML dla każdego elementu tablicy danych.
dane.(el => {
kontener.innerHTML += `<div class="blok"><h3></h3><p>${el.cena} zł</p></div>`;
});
Wyszukiwarka: pozostaw tylko elementy, których nazwa zawiera wpisany tekst (bez rozróżniania wielkości liter).
const fraza = pole.value.();
const wynik = dane.(el => el.nazwa.toLowerCase().(fraza));
Przed ponownym wygenerowaniem bloków trzeba wyczyścić kontener, bo bloki się dublują. Dodaj brakującą instrukcję na początku funkcji.
W szablonie tekstowym użyto zwykłych cudzysłowów, więc wartość zmiennej nie jest wstawiana. Popraw zapis.
Część C, lekcja 21
Wzorzec 5: kalkulator z suwakiem, radio i datą
Sytuacja z arkusza: strona salonu rowerowego ma suwak wzrostu zsynchronizowany z polem liczbowym, trzy opcje typu roweru i przycisk „Sprawdź”, który wylicza zalecany rozmiar ramy; po załadowaniu strony w komórce tabeli ma się pojawić dzisiejsza data.
<section>
<h3>Dobierz ramę</h3>
<input type="range" min="140" max="210" value="170" oninput="aktualizujPole()">
<input type="number" min="140" max="210" value="170" oninput="aktualizujSuwak()">
<p>
<label><input type="radio" name="rodzajRoweru" value="gorski" checked> górski z kołami 29"</label>
<label><input type="radio" name="rodzajRoweru" value="szosa"> szosa</label>
<label><input type="radio" name="rodzajRoweru" value="trekking"> trekking</label>
</p>
<button onclick="obliczRozmiarRamy()">Sprawdź</button>
<p id="wynik"></p>
</section>
<table><tr><td>Dzisiejsza data:</td><td id="komorkaDaty"></td></tr></table>
function aktualizujPole() { // suwak → pole
const suwak = document.querySelector("input[type='range']");
document.querySelector("input[type='number']").value = suwak.value;
}
function aktualizujSuwak() { // pole → suwak (rozszerzenie)
const pole = document.querySelector("input[type='number']");
document.querySelector("input[type='range']").value = pole.value;
}
function obliczRozmiarRamy() {
const wzrost = Number(document.querySelector("input[type='number']").value);
const rodzaj = document.querySelector("input[name='rodzajRoweru']:checked").value;
let wspolczynnik = 0.26;
if (rodzaj === "szosa") wspolczynnik = 0.3;
if (rodzaj === "trekking") wspolczynnik = 0.28;
const rozmiar = Math.round((wzrost * wspolczynnik) / 2.54);
document.querySelector("#wynik").textContent = `Zalecany rozmiar ramy to: ${rozmiar} cali`;
}
function aktualnaData() {
const dzis = new Date();
const dzien = String(dzis.getDate()).padStart(2, "0");
const miesiac = String(dzis.getMonth() + 1).padStart(2, "0");
document.querySelector("#komorkaDaty").textContent = `${dzien}.${miesiac}.${dzis.getFullYear()}`;
}
aktualnaData(); // wywołanie przy ładowaniu (skrypt z defer)
170 cm, szosa: 170 × 0,3 = 51 → 51 / 2,54 = 20,08 → 20 cali
170 cm, górski: 170 × 0,26 = 44,2 → 44,2 / 2,54 = 17,40 → 17 cali
170 cm, trekking: 170 × 0,28 = 47,6 → 47,6 / 2,54 = 18,74 → 19 cali
Jeśli żadne radio nie jest zaznaczone (brak checked), querySelector("...:checked") zwraca null, a .value zgłasza błąd. Na egzaminie ustaw checked na pierwszej opcji w HTML albo dodaj warunek if (wybrany).
Co wyświetli skrypt dla wzrostu 180 cm i roweru trekkingowego?
Pokaż przykładową odpowiedź
180 × 0,28 = 50,4; 50,4 / 2,54 ≈ 19,84, po zaokrągleniu 20, czyli „Zalecany rozmiar ramy to: 20 cali”.
Dlaczego w obliczeniach trzeba użyć Number() przy odczycie z pola?
Pokaż przykładową odpowiedź
Bo value jest napisem; bez konwersji działanie wzrost * 0.26 zadziała (JavaScript zamieni napis), ale np. dodawanie skleiłoby napisy, więc dla bezpieczeństwa zawsze konwertuj.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Kalkulator ceny: pomnóż liczbę dni przez cenę za dzień i dodaj opłatę zależną od zaznaczonego przycisku radio.
const dni = Number(document.getElementById("dni").value);
const oplata = Number(document.querySelector("input[name='typ']").value);
const razem = dni 120 oplata;
document.getElementById("wynik").textContent = razem.(2) + " zł";
Liczba dni pobytu powinna wynikać z różnicy dat, ale zamiast dni wyświetla się liczba milisekund. Popraw obliczenie.
Aktualizuj etykietę przy przesuwaniu suwaka i przelicz wynik.
suwak.addEventListener("", () => {
etykieta.textContent = suwak.;
przelicz();
});
Cena jest wyświetlana z wieloma miejscami po przecinku. Zaokrąglij ją do dwóch miejsc.
Część C, lekcja 22
Wzorzec 6: plansza do gry (stan gry i zdarzenia)
Sytuacja z arkusza: plansza 3×3 w tabeli, w każdej komórce obraz „puste pole”. Gracze (kółko i krzyżyk) klikają na zmianę puste pole. Po ruchu kółka widoczny jest napis „Gra krzyżyk”, po ruchu krzyżyka „Gra kółko”. Kliknięcie zajętego pola nic nie robi. Obrazy: js-gra.zip.
<section id="lewa"><h3>Gra kółko</h3></section>
<table>
<tr>
<td><img src="img/nic.svg" alt="pole" onclick="zaznaczPole(this)"></td>
<td><img src="img/nic.svg" alt="pole" onclick="zaznaczPole(this)"></td>
<td><img src="img/nic.svg" alt="pole" onclick="zaznaczPole(this)"></td>
</tr>
<!-- wiersze 2 i 3 analogicznie -->
</table>
<section id="prawa"><h3>Gra krzyżyk</h3></section>
let gracz = "kolko"; // stan początkowy: zaczyna kółko
const sekcjaLewa = document.querySelector("#lewa");
const sekcjaPrawa = document.querySelector("#prawa");
sekcjaPrawa.style.visibility = "hidden"; // początkowo widoczny jest napis „Gra kółko”
function zaznaczPole(pole) {
if (!pole.src.includes("nic.svg")) return; // pole zajęte → brak akcji
if (gracz === "kolko") {
pole.src = "img/o.svg";
sekcjaLewa.style.visibility = "hidden";
sekcjaPrawa.style.visibility = "visible";
gracz = "krzyzyk";
} else {
pole.src = "img/x.svg";
sekcjaLewa.style.visibility = "visible";
sekcjaPrawa.style.visibility = "hidden";
gracz = "kolko";
}
}
- Stan gry (
gracz) to zmienna poza funkcją – inaczej jej wartość zniknęłaby po każdym kliknięciu. onclick="zaznaczPole(this)"przekazuje klikniętą komórkę, więc funkcja nie musi jej wyszukiwać.pole.src.includes("nic.svg")to sprawdzenie, czy pole jest jeszcze puste (srczawiera pełny adres, więc porównanie===z samą nazwą pliku by nie zadziałało).- Instrukcja
returnprzerywa funkcję – brak akcji dla zajętego pola.
Rozszerzenie: wykrywanie wygranej
const wygrywajace = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
function czyWygral(symbol) { // symbol: "o.svg" lub "x.svg"
const pola = document.querySelectorAll("table img");
return wygrywajace.some(uklad => uklad.every(i => pola[i].src.includes(symbol)));
}
// po ruchu: if (czyWygral("o.svg")) alert("Wygrało kółko!");
Dlaczego zmienną gracz deklarujemy poza funkcją?
Pokaż przykładową odpowiedź
Aby jej wartość zachowała się między kolejnymi wywołaniami funkcji; zmienna lokalna byłaby tworzona od nowa przy każdym kliknięciu.
Jak sprawdzić, czy kliknięte pole jest puste?
Pokaż przykładową odpowiedź
Sprawdzić, czy pole.src zawiera nazwę pliku z obrazem pustego pola (includes("nic.svg")).
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Plansza: obsłuż kliknięcie komórki, przekazując w HTML kliknięty element.
<td ="zaznacz()"></td>
Zmień stan klikniętej komórki i pilnuj, aby nie dało się jej kliknąć drugi raz.
function zaznacz(komorka) {
if (komorka.classList.contains("zajete")) ;
komorka.classList.("zajete");
komorka.textContent = gracz;
}
Zmiana gracza po każdym ruchu nie działa, bo użyto przypisania w warunku. Popraw kod.
Licznik ruchów ma rosnąć po każdym kliknięciu, ale po wywołaniu funkcji zmienna jest lokalna i się nie zachowuje. Przenieś deklarację zmiennej poza funkcję.
Część C, lekcja 23
Debugowanie i lista kontrolna skryptów JavaScript
| Objaw | Najczęstsza przyczyna | Naprawa |
|---|---|---|
| nic się nie dzieje po kliknięciu | funkcja nie jest podłączona (literówka w onclick) lub skrypt się nie wczytał (zła ścieżka) | otwórz Console i Network (F12); sprawdź nazwę pliku i funkcji |
Cannot read properties of null | querySelector nie znalazł elementu (zły selektor, skrypt w head bez defer) | popraw selektor, dodaj defer, sprawdź console.log(element) |
X is not defined | literówka w nazwie lub funkcja w innym zakresie | sprawdź wielkość liter: zamknijOkno ≠ zamknijokno |
Unexpected token | brak nawiasu, przecinka, cudzysłowu | przeczytaj linię z konsoli |
| wynik „NaN” | pusty napis lub tekst zamieniany na liczbę | Number(pole.value) i sprawdź, czy pole nie jest puste |
| wynik „1605” zamiast 165 | dodawanie napisów | zamień na liczby przed działaniem |
| zmiana stylu nie działa | zapis style.background-color zamiast backgroundColor | camelCase w style |
| skrypt działa tylko raz | zmienna stanu utworzona wewnątrz funkcji | przenieś zmienną poza funkcję |
| lista rośnie przy każdym kliknięciu | użyto += bez czyszczenia | wyczyść innerHTML = "" przed generowaniem |
Lista kontrolna przed oddaniem pracy
- plik
main.jsjest w folderze z numerem zdającego i podłączony do strony (sprawdź w karcie Network, że ładuje się bez błędu 404), - każdy wymagany skrypt wykonałeś w przeglądarce: kliknij, wpisz, zmień wartości, porównaj z ilustracjami z arkusza,
- teksty komunikatów, nazwy klas i identyfikatory są takie jak w arkuszu,
- w konsoli (F12) nie ma czerwonych błędów po załadowaniu i po użyciu funkcji,
- nazwy zmiennych i funkcji są znaczące, kod ma wcięcia, brak zbędnych
console.log, - zapisałeś wszystkie pliki (Ctrl+S) i zapisałeś nazwę przeglądarki w pliku
przegladarka.txt.
Pisz skrypt małymi krokami: najpierw funkcja, która tylko wypisuje coś w konsoli, potem prosta zmiana na stronie, potem pełne wymaganie. Po każdym kroku odśwież stronę (Ctrl+F5) i sprawdź konsolę. Błąd znaleziony po 3 liniach jest łatwiejszy niż po 30.
Co sprawdzisz najpierw, gdy po kliknięciu przycisku nic się nie dzieje?
Pokaż przykładową odpowiedź
Konsolę (F12) pod kątem błędów, potem czy skrypt jest poprawnie wczytany (Network) oraz czy nazwa funkcji w onclick zgadza się z definicją.
Skąd błąd Cannot read properties of null (reading 'style') po otwarciu strony?
Pokaż przykładową odpowiedź
Skrypt próbuje zmienić styl elementu, którego jeszcze nie ma (lub nie znaleziono go przez selektor); trzeba dodać defer, przenieść skrypt na koniec body lub poprawić selektor.
Ćwiczenia interaktywne: uzupełnij i popraw kod
Wpisz brakujące fragmenty w polach albo popraw kod w oknie i kliknij „Sprawdź”. Białe znaki i rodzaj cudzysłowu nie mają znaczenia. Rozwiązane ćwiczenia zapisują się na koncie i liczą się do odznak.
Sprawdź wartość zmiennej i jej typ podczas debugowania.
console.(wartosc);
console.log( wartosc);
Skrypt zgłasza błąd, bo element nie został znaleziony: selektor klasy nie ma kropki. Popraw kod.
Skrypt zgłasza błąd „Unexpected token”: w kodzie brakuje nawiasu zamykającego. Popraw kod.
Wynik porównania liczb z pola jest błędny („10” jest uznane za mniejsze od „9”), bo porównywane są napisy. Zamień wartości na liczby.
Uruchom kod dopiero po wczytaniu strony i obsłuż błąd w bloku try...catch.
document.addEventListener("DOMContentLoaded", () => {
{
start();
} (e) {
console.error(e);
}
});
Zadanie praktyczne
Zadanie próbne: karta produktu z wariantami
Zadanie
Wykonaj kartę produktu dla sklepu z rowerami (własny projekt wizualny). Pliki obrazów: js-galeria.zip.
Założenia
- Blok sekcji: obraz główny (klasa
obraz) i trzy miniatury (klasaminiatury). Kliknięcie miniatury podmienia obraz główny na wybrany, kliknięcie obrazu głównego otwiera okno z jego powiększeniem (klasaokno, ukryte w CSS), kliknięcie znaku × zamyka okno. - Artykuł z listą rozwijaną „Wariant: czerwony / niebieski / czarny”. Po zmianie wartości listy skrypt zmienia kolor tła bloku nagłówkowego (
style.backgroundColor) na odpowiedni. - Pole liczbowe „Liczba sztuk” (1–5) i przycisk „Dodaj do koszyka”. Skrypt wylicza cenę (np. 1499 zł × liczba) i wypisuje w akapicie „W koszyku: 2 szt., razem 2998.00 zł”; dla niepoprawnej liczby wypisuje „Podaj liczbę od 1 do 5”.
- W stopce, po załadowaniu strony, wypisz dzisiejszą datę DD.MM.RRRR oraz licznik odwiedzin z
localStorage. - Wszystkie funkcje o znaczących nazwach, obsługa zdarzeń przez atrybuty HTML i/lub
addEventListener; brak błędów w konsoli.
Ocenie podlegać będzie
- działanie galerii i okna,
- poprawna obsługa listy i obliczeń,
- walidacja liczby sztuk,
- data i licznik,
- czytelność i zgodność z wymaganiami.
Wskazówki
- Wariant koloru: obiekt
{czerwony: "#fecaca", ...}i odczyt przezkolory[lista.value]. - Kontrola liczby:
Number.isInteger(n) && n >= 1 && n <= 5. - Wzorce: lekcje 15, 19 i 14.
Zadanie praktyczne
Zadanie próbne: gra w zgadywanie liczby
Zadanie
Zaprojektuj prostą grę „Zgadnij liczbę”. Komputer losuje liczbę 1–50, a gracz ma 6 prób.
Założenia
- Po załadowaniu strony skrypt losuje liczbę (
Math.floor(Math.random() * 50) + 1) i zapisuje ją w zmiennej poza funkcją; ustawia licznik prób na 6. - Pole liczbowe i przycisk „Sprawdź”. Po kliknięciu skrypt porównuje liczbę z wylosowaną i w akapicie wypisuje: „za mało”, „za dużo” lub „Brawo! Zgadłeś w N próbie”; po wyczerpaniu prób wypisuje wylosowaną liczbę i blokuje pole (
disabled). - Lista użytych prób (elementy
lidodawane przezcreateElement) pokazuje każdy wpisany typ i wynik. - Przycisk „Nowa gra” zeruje stan, czyści listę, odblokowuje pole i losuje nową liczbę.
- Najlepszy wynik (najmniej prób) zapisz w
localStoragei wyświetlaj w stopce.
Ocenie podlegać będzie
- poprawna logika gry i stan zmiennych,
- tworzenie elementów DOM,
- blokowanie i odblokowanie kontrolek,
- zapis w localStorage,
- czytelny kod.
Wskazówki
- Stan gry: zmienne
tajnaiprobypoza funkcjami. - Koniec gry:
pole.disabled = true. - Lekcje 11, 14 i 20.