Przejdź do treści

Temat 19 · 3 × 45 minINF.03

Trening egzaminacyjny: część praktyczna

Masz już wszystkie klocki: odczyt kontrolek, obliczenia, zmiana stylów, tworzenie elementów, stan i walidacja. Ta lekcja składa je w to, co naprawdę zobaczysz na stanowisku: 150 minut, arkusz z pięcioma rezultatami, bez internetu, z jedną tabelą metod DOM jako pomocą. Najpierw poznasz zasady gry – jak czytać kryteria i gdzie zdający tracą punkty – a potem rozwiążesz trzy pełne zadania zbudowane z mechanizmów, które CKE stosuje od 2024 r.

Jak wygląda egzamin praktyczny

ElementJak jest naprawdę
Czas150 minut + 10 minut na zapoznanie się z arkuszem i stanowiskiem (nie wliczane)
Próg zdania75 % punktów
Stanowiskokomputer fizycznie odłączony od sieci, XAMPP (Apache, MySQL/MariaDB, PHP, phpMyAdmin), przeglądarka w aktualnej wersji, edytor z podświetlaniem składni bez WYSIWYG (VS Code, Notepad++…), GIMP/Inkscape, 7-Zip
Pomocetylko arkusz – w wariancie JS zawiera tabelę „Wybrane pola i metody modelu DOM języka JavaScript”; żadnej dokumentacji online
Rezultaty1. operacje na bazie danych (import, 4–5 kwerend, zrzuty), 2. zawartość witryny (HTML), 3. działanie witryny, 4. styl CSS, 5. skrypt – JS albo PHP
Skryptw 25–50 % wariantów sesji to JavaScript; nie wiesz, który wariant wylosujesz, więc ćwiczysz oba
Punkty za skrypt5–8 kryteriów zero-jedynkowych z 34–42 łącznie (13–20 %)
Oddanie pracyfolder o nazwie z numerem zdającego, plik przeglądarka.txt z nazwą użytej przeglądarki, zrzuty ekranu pełnoekranowe z paskiem zadań (wykadrowane nie są oceniane), nagranie na płytę i sprawdzenie, czy się otwiera

Skrypt to zwykle jedna strona z formularzem lub kilkoma przyciskami i jedna–trzy funkcje. Arkusz nie wymaga osobnego pliku .js (możesz pisać w <script> na końcu body), nie określa wersji języka i nie zakazuje let, const, addEventListener czy template stringów – przeglądarka jest aktualna, więc wszystko działa. Liczy się efekt w przeglądarce, który egzaminator klika osobiście.

Budżet czasu

Egzaminator nie wie, ile czasu poświęciłeś na skrypt – ale ty musisz to zaplanować. Orientacyjny podział 150 minut (to szacunek z proporcji kryteriów, nie oficjalna zasada):

EtapCzasUwagi
Czytanie arkusza, rozpakowanie materiałów, folder wynikowy10 minprzeczytaj cały arkusz, zaznacz sformułowania „dokładnie”, „w akapicie”, „w kolorze”
Baza danych: import, kwerendy, zrzuty25 minzrzuty rób od razu po każdej kwerendzie
HTML (zwykle 2–3 strony)40 minszkielet pod skrypt: id kontrolek i pustego akapitu
CSS25 min
Skrypt25 minsekcja poniżej
Grafika / animacja10 min
Test całości w przeglądarce, przeglądarka.txt, płyta15 minzostaw ten czas bezwzględnie

Skrypt rób po HTML, ale nie na końcu – jeśli zabraknie czasu, lepiej mieć działający skrypt bez połowy CSS niż odwrotnie: skrypt to do 8 kryteriów, których nie da się nadrobić „w kodzie”, gdy strona nie działa.

Czytaj arkusz kryterium po kryterium

Oficjalne „Zasady oceniania” nie są dostępne w trakcie egzaminu, ale są przewidywalne: każde zdanie opisu skryptu to jedno kryterium. Przykładowy opis z arkusza (parafraza, styczeń 2025, INF.03-01-25.01): skrypt po kliknięciu „Oblicz” pobiera dane z kontrolek, ustala kwotę za zaznaczone kursy według cen z tabeli, dzieli ją przez liczbę rat i wyświetla pod przyciskiem w akapicie tekst „Kurs odbędzie się w <miasto>. Koszt całkowity: <kwota> zł. Płacisz <liczba> rat po <rata> zł”. Egzaminator sprawdzał to tak:

KryteriumCo sprawdzaJak sprawdza
5.1skrypt w JavaScript, co najmniej jedna instrukcja zgodna ze składniąw kodzie
5.2pobiera dane z co najmniej jednej kontrolki (np. document.getElementById)w kodzie
5.3liczy koszt zaznaczonych kursów, testując zaznaczenie każdego checkboxaw kodzie
5.4pobiera liczbę rat i dzieli przez nią kosztw kodzie
5.5wynik zawiera miasto z listy – dla dwóch różnych miastw przeglądarce
5.6wynik zawiera koszt całkowityw przeglądarce
5.7liczba rat i wysokość raty – dla dwóch różnych wartościw przeglądarce
5.8co najmniej jedna zmienna lub funkcja o znaczącej nazwie (PL/EN)w kodzie

Dwie rzeczy wynikają z tej tabeli. Po pierwsze: gdy skrypt nie uruchamia się (błąd składni, literówka w id), egzaminator sprawdza w kodzie tylko kryteria „kodowe” (język, pobranie, obliczenia, nazwy) – kryteria „wyjściowe” (tekst, miejsce, kolor) przepadają. Po drugie: „dla dwóch różnych wartości” oznacza, że egzaminator zmienia dane i klika ponownie – wynik zaszyty na sztywno, działający tylko dla jednego zestawu, nie dostanie punktu.

Zanim zaczniesz pisać, zrób z opisu własną listę kryteriów. Zdanie „wyświetla pod przyciskiem w akapicie tekst X w kolorze Y” rozbij na trzy: pod przyciskiem w akapicie, tekst dokładnie X, kolor Y. Każde z nich to osobny punkt do zdobycia – i osobny do stracenia.

Sprawdź się

Opis skryptu brzmi: „Po kliknięciu „Sprawdź” skrypt pobiera wagę i wzrost, oblicza BMI (waga / wzrost²) i wyświetla w akapicie pod przyciskiem tekst „Twoje BMI: <wynik>” zaokrąglony do jednego miejsca po przecinku”. Ile osobnych kryteriów wyjściowych (sprawdzanych w przeglądarce) najprawdopodobniej z tego wynika?

Lista kontrolna skryptu egzaminacyjnego

Przejdź ją przed oddaniem pracy. Każdy punkt odpowiada realnemu kryterium albo realnej przyczynie zera.

  1. Skrypt się uruchamia. Otwórz konsolę (F12) – zero czerwonych błędów po załadowaniu i po kliknięciu. Jeden błąd składni zatrzymuje cały skrypt.
  2. Zdarzenie zgodne z arkuszem: „po kliknięciu” → click, „po najechaniu” → mouseover, „po opuszczeniu pola” → blur. Przycisk z arkusza ma dokładnie podany napis.
  3. <script> na końcu body albo defer – inaczej getElementById zwraca null, bo elementów jeszcze nie ma.
  4. Identyfikatory zgadzają się co do znaku z HTML (wielkość liter!). Wynik null w konsoli = literówka w id.
  5. Konwersja na liczbę przy każdym obliczeniu: parseFloat/parseInt/Number. "5" + "3" to "53".
  6. Każda kontrolka z opisu jest odczytana – każdy checkbox sprawdzony osobno, radio z checked, select z value.
  7. Tekst wyniku co do znaku: etykieta, dwukropek, spacje, „zł”, kropka na końcu, kolejność danych. Przepisz go z arkusza do kodu dosłownie, a wartości wstaw w miejsce nawiasów.
  8. Miejsce wyniku takie jak w arkuszu: akapit pod przyciskiem (innerHTML/textContent), okno dialogowe (alert), konsola (console.log). Nie zamieniaj.
  9. Kolor / styl, jeśli podany: style.color = 'red', 'Navy'.
  10. Zaokrąglenie zgodne z treścią: „do góry” → Math.ceil, „do liczby całkowitej” → Math.round, „dwa miejsca” → toFixed(2).
  11. Zawijanie, limity, stan początkowy: przetestuj galerię dookoła, pasek do 100 %, obliczenie przed jakimkolwiek kliknięciem.
  12. Test na dwóch zestawach danych – różne liczby, inna opcja listy, inne zaznaczenia – i na danych błędnych, jeśli arkusz wymaga walidacji.
  13. Znaczące nazwy zmiennych i funkcji (obliczKoszt, liczbaRat), bez polskich znaków w identyfikatorach. a, x1, f1 kosztują kryterium.
  14. Nic ponad arkusz: nie dodawaj walidacji, gdy zadanie mówi „pominąć” – nie ma za to punktów, a może zablokować ścieżkę, którą egzaminator testuje.
  15. Plik zapisany w folderze wynikowym, strona otwarta ponownie z tego folderu i sprawdzona.

Gdzie uciekają punkty

ObjawPrzyczynaKryterium, które przepada
nic się nie dzieje po kliknięciuonclick="oblicz" bez nawiasów; addEventListener('click', oblicz()) z nawiasami; błąd składni gdziekolwiekwszystkie wyjściowe
Cannot read properties of nullliterówka w id; skrypt w head bez deferwszystkie wyjściowe
wynik „Koszt: 53 zł” zamiast 8brak parseFloat – konkatenacja napisówobliczenie + tekst wyniku
wynik liczy tylko pierwszy kurssprawdzony jeden checkbox„testując zaznaczenie każdego”
wynik w okienkualert zamiast akapitumiejsce wyświetlenia, kolor
„Koszt całkowity 300zł”brak dwukropka / spacji z arkuszatekst wyniku
9,25 puszki farbybrak Math.ceilzaokrąglenie
po 7. zdjęciu puste polebrak zawijania„po ostatnim pierwsze”
szerokość 112 %brak Math.min/if„nigdy ponad 100 %”
trzy zakładki widoczne narazbrak ukrycia pozostałych„pokazuje tylko wybraną”
function f1(), var a, b, cnazwy bez znaczenianazewnictwo (R.5.8)
strona „mruga” i wynik znika<button> w <form> bez type="button" → wysłanie formularzawyjściowe (wynik niewidoczny)

Sprawdź, czy rozpoznasz błędy w kodzie – tak jak egzaminator, który czyta cudzy skrypt.

Sprawdź się

Zadanie: „skrypt sumuje ceny zaznaczonych zabiegów (peeling 45 zł, maska 30 zł) i wypisuje pod przyciskiem „Cena zabiegów: <suma>”. Które kryterium NIE zostanie spełnione przez ten kod?

function policz() {
var suma = 0;
if (document.getElementById('peeling').checked) {
  suma = suma + 45;
  suma = suma + 30;
}
document.getElementById('wynik').innerHTML = 'Cena zabiegów: ' + suma;
}
Sprawdź się

Zadanie: „pod przyciskiem w akapicie wyświetla „Liczba puszek: <liczba>”, zaokrąglona w górę (1 puszka = 4 m²)”. Co straci ten skrypt?

function policzPuszki() {
var powierzchnia = document.getElementById('pow').value;
var puszki = powierzchnia / 4;
alert('Liczba puszek: ' + Math.ceil(puszki));
}
Sprawdź się

Skrypt ma działać po kliknięciu przycisku. HTML: <button onclick='zmienKolor'>Zmień</button>. Co się stanie?

Jak pracować nad skryptem: 25 minut krok po kroku

  1. (2 min) Przeczytaj opis skryptu dwa razy i wypisz kryteria na kartce (z arkusza możesz korzystać jak z brudnopisu).
  2. (3 min) Szkielet, który już działa: funkcja, podpięcie do zdarzenia, wewnątrz console.log('klik'). Kliknij. Jeśli w konsoli jest „klik”, połączenie HTML–JS jest poprawne i najgorszy scenariusz (zero kryteriów) masz z głowy.
  3. (5 min) Pobranie danych: po jednej zmiennej na kontrolkę, od razu parseFloat tam, gdzie będziesz liczyć. console.log wszystkich zmiennych – sprawdź typy i wartości.
  4. (5 min) Logika: obliczenie, if/else, zawijanie, limity. Testuj w konsoli, zanim cokolwiek wypiszesz.
  5. (5 min) Wyjście: tekst przepisany z arkusza, właściwe miejsce, kolor. Dopiero teraz patrzysz na stronę.
  6. (5 min) Testy: dwa zestawy danych, stan początkowy, ścieżka błędna (jeśli jest walidacja), konsola bez błędów. Usuń pomocnicze console.log tylko wtedy, gdy arkusz czegoś nie wypisuje w konsoli celowo – inaczej mogą zostać, nie szkodzą.
  7. (ostatnia minuta) Nazwy: przejrzyj identyfikatory – czy ktoś obcy zrozumie, co trzymają?

Nie zaczynaj od pisania całego skryptu „na raz”. Każdy etap kończy się działającym kodem, więc jeśli zabraknie czasu, oddajesz coś, co zdobywa kryteria kodowe.

Na egzaminie

Ściąga

Tabela z arkusza plus to, czego w niej nie ma, a czego używasz najczęściej:

SkładniaCo robiPrzykład
document.getElementById('id')element o danym id (albo null)const pole = document.getElementById('wiek')
document.querySelector('sel') / querySelectorAllelement / lista wg selektora CSSquerySelectorAll('.miniatura')
getElementsByClassName, getElementsByTagNamekolekcja (indeks, pętla)elementy[i].style.color = 'red'
el.value, el.checked, el.selectedIndexodczyt kontrolekparseFloat(pole.value)
el.innerHTML, el.textContenttreść elementuwynik.innerHTML = 'Koszt: ' + koszt + ' zł'
el.style.wlasciwoscstyl inline (camelCase)style.backgroundColor, style.display = 'none'
el.setAttribute('atr', 'w'), el.src, el.title, el.altatrybutyimg.src = numer + '.jpg'
document.createElement('tag'), rodzic.appendChild(el)nowy element dołączony na konieclista.appendChild(li)
rodzic.removeChild(el), el.remove()usunięcie
el.classList.add/remove/toggleklasyclassList.add('aktywny')
el.addEventListener('click', f) / onclick="f()"zdarzenia: click, mouseover, mouseout, blur, change, input, keyup
parseFloat, parseInt, Number, isNaNkonwersjaisNaN(parseFloat(x))
Math.ceil, Math.round, Math.floor, Math.random, toFixed(2)zaokrąglenia i losowośćMath.floor(Math.random() * n)
s.toUpperCase(), s.slice(a, b), s.lastIndexOf('x'), s.split(''), s.trim()napisynazwa pliku: s.slice(s.lastIndexOf('\\') + 1)
alert(t), console.log(t)okno / konsola – tylko gdy arkusz tego żąda

Zadania

Zadanie 1
średniejak na INF.03

Zapisy na obóz programistyczny: zakładki i pasek postępu

Strona zapisy.html ma gotową strukturę (HTML poniżej jest kompletny – twoim zadaniem jest wyłącznie skrypt). Trzy przyciski nawigacji i trzy sekcje-karty; na starcie widoczna jest tylko karta „Uczestnik” (pozostałe ukryte w CSS regułą display: none).

zapisy.html (fragment)
<nav>
  <button id="btn-uczestnik" onclick="pokazKarte('uczestnik')">Uczestnik</button>
  <button id="btn-szkola" onclick="pokazKarte('szkola')">Szkoła</button>
  <button id="btn-kontakt" onclick="pokazKarte('kontakt')">Kontakt</button>
</nav>
<div id="pasek"><div id="postep"></div></div>
<section id="uczestnik" class="karta">
  <label>Imię: <input id="imie"></label>
  <label>Nazwisko: <input id="nazwisko"></label>
</section>
<section id="szkola" class="karta">
  <label>Szkoła: <input id="nazwaSzkoly"></label>
  <label>Klasa: <input id="klasa"></label>
</section>
<section id="kontakt" class="karta">
  <label>E-mail: <input id="email"></label>
  <label><input type="checkbox" id="rodo"> Zgoda na przetwarzanie danych</label>
  <button type="button" onclick="zatwierdz()">Zatwierdź</button>
</section>
styl.css (fragment)
.karta { display: none; }
#uczestnik { display: block; }
#pasek { width: 300px; height: 20px; background: #ddd; }
#postep { width: 0; height: 20px; background: green; }

Skrypt wykonywany po stronie klienta:

  1. Kliknięcie przycisku nawigacji ukrywa wszystkie karty i pokazuje wybraną; kliknięty przycisk ma tło LightGreen, pozostałe – białe. Zrealizuj to jedną funkcją z parametrem pokazKarte(idKarty).
  2. Opuszczenie dowolnego z pięciu pól tekstowych (zdarzenie utraty fokusu) zwiększa szerokość paska #postep o 20 % (20 %, 40 %, 60 %…). Zabezpiecz funkcję, aby szerokość nigdy nie przekroczyła 100 %.
  3. Kliknięcie „Zatwierdź” wypisuje w konsoli przeglądarki jeden wiersz: „Zgłoszenie: Imię Nazwisko, Szkoła, kl. Klasa, e-mail; RODO: tak/nie” (wartości z pól; „tak” gdy checkbox zaznaczony). Dla uproszczenia walidację pomiń.
  4. Stosuj znaczące nazwy zmiennych i funkcji w języku polskim lub angielskim.

Kryteria (0/1):

  • 5.1 Skrypt w JavaScript, co najmniej jedna poprawna składniowo instrukcja.
  • 5.2 Kliknięcie przycisku nawigacji pokazuje wyłącznie wybraną kartę (sprawdzane dla dwóch różnych kart).
  • 5.3 Kliknięty przycisk ma tło LightGreen, pozostałe białe.
  • 5.4 Karty obsługuje jedna funkcja z parametrem.
  • 5.5 Opuszczenie pola zwiększa szerokość paska o 20 %.
  • 5.6 Szerokość paska nigdy nie przekracza 100 % (sprawdzane po 6 i więcej zdarzeniach).
  • 5.7 „Zatwierdź” wypisuje w konsoli dane z pól w podanym formacie.
  • 5.8 Znaczące nazewnictwo.
Pokaż rozwiązanie
Rozwiązanie: zapisy na obóz
// 1. zakładki – jedna funkcja z parametrem
const NAZWY_KART = ['uczestnik', 'szkola', 'kontakt'];

function pokazKarte(idKarty) {
  for (const nazwa of NAZWY_KART) {
    document.getElementById(nazwa).style.display = 'none';               // ukryj każdą kartę
    document.getElementById('btn-' + nazwa).style.backgroundColor = 'white'; // odznacz każdy przycisk
  }
  document.getElementById(idKarty).style.display = 'block';
  document.getElementById('btn-' + idKarty).style.backgroundColor = 'LightGreen';
}
pokazKarte('uczestnik'); // stan początkowy: pierwszy przycisk podświetlony

// 2. pasek postępu – stan poza funkcją, limit 100
let szerokoscPaska = 0;

function zwiekszPostep() {
  szerokoscPaska = Math.min(szerokoscPaska + 20, 100);
  document.getElementById('postep').style.width = szerokoscPaska + '%';
}

const polaTekstowe = ['imie', 'nazwisko', 'nazwaSzkoly', 'klasa', 'email'];
for (const idPola of polaTekstowe) {
  document.getElementById(idPola).addEventListener('blur', zwiekszPostep);
}

// 3. zatwierdzenie – wynik w konsoli, jak żąda arkusz
function zatwierdz() {
  const imie = document.getElementById('imie').value;
  const nazwisko = document.getElementById('nazwisko').value;
  const szkola = document.getElementById('nazwaSzkoly').value;
  const klasa = document.getElementById('klasa').value;
  const email = document.getElementById('email').value;
  const rodo = document.getElementById('rodo').checked ? 'tak' : 'nie';
  console.log('Zgłoszenie: ' + imie + ' ' + nazwisko + ', ' + szkola + ', kl. ' + klasa + ', ' + email + '; RODO: ' + rodo);
}
Podgląd

Samoocena: kliknij „Szkoła”, potem „Kontakt” (5.2, 5.3); co najmniej 6 razy wejdź w pole i je opuść (klik poza pole albo Tab) i sprawdź, czy pasek zatrzymał się na 100 % (5.5, 5.6); wypełnij pola i zatwierdź z zaznaczonym i niezaznaczonym checkboxem (5.7).

Zadanie 2
średniejak na INF.03

Drukarnia plakatów: koszyk z polem file

Strona zamowienie.html (HTML gotowy):

zamowienie.html (fragment)
<label>Plik z projektem (PNG): <input type="file" id="plik" accept="image/png"></label>
<label>Liczba sztuk: <input type="number" id="sztuki" value="1" min="1"></label>
<label>Format:
  <select id="format">
    <option value="12">A3 – 12 zł</option>
    <option value="20">A2 – 20 zł</option>
    <option value="35">A1 – 35 zł</option>
  </select>
</label>
<label><input type="checkbox" id="laminowanie"> Laminowanie (+3 zł/szt.)</label>
<button type="button" onclick="dodajDoKoszyka()">Dodaj do koszyka</button>
<section id="koszyk"><h2>Koszyk</h2></section>

Skrypt po kliknięciu „Dodaj do koszyka”:

  1. Ustala nazwę pliku bez ścieżki dostępu z pola file (przeglądarka zwraca wartość w postaci C:\fakepath\nazwa.png).
  2. Oblicza cenę pozycji: liczba sztuk × cena formatu (z wartości opcji) + 3 zł za sztukę, jeśli zaznaczono laminowanie.
  3. Dokleja na końcu sekcji #koszyk nowy blok div z klasą pozycja, zawierający: element img o src i alt równych nazwie pliku oraz klasie miniatura, akapit „Plik: <nazwa>, format <A3/A2/A1>, <sztuki> szt.” oraz akapit „Cena: <cena> zł”. Kolejne kliknięcia dopisują kolejne pozycje; pozycje nie są usuwane.
  4. Pod nagłówkiem koszyka akapit <p id="suma"> pokazuje „Razem: <suma> zł” – sumę wszystkich pozycji (utwórz go skryptem przy pierwszym dodaniu albo wpisz w HTML).
  5. Znaczące nazwy zmiennych i funkcji.

Kryteria (0/1):

  • 5.1 JavaScript, funkcja wywoływana przyciskiem.
  • 5.2 Pobiera dane z co najmniej jednej kontrolki.
  • 5.3 Nazwa pliku ustalona bez ścieżki dostępu.
  • 5.4 Cena uwzględnia liczbę sztuk, format i laminowanie – sprawdzane dla dwóch różnych zestawów.
  • 5.5 Nowa pozycja tworzona elementami DOM (createElement/appendChild) i dołączana na końcu koszyka; kolejne kliknięcia dodają kolejne.
  • 5.6 Element img ma src, alt równe nazwie pliku i klasę miniatura.
  • 5.7 Teksty pozycji i sumy zgodne z formatem.
  • 5.8 Znaczące nazewnictwo.
Pokaż rozwiązanie

W placu zabaw obrazek się nie wyświetli (nie ma pliku), zobaczysz tekst alternatywny – na egzaminie plik leży w folderze strony i miniatura się pokaże.

Rozwiązanie: drukarnia plakatów
let sumaKoszyka = 0; // stan: suma wszystkich pozycji

function nazwaPlikuBezSciezki(sciezka) {
  // 'C:\fakepath\plakat.png' → 'plakat.png'; pusta wartość → ''
  return sciezka.slice(sciezka.lastIndexOf('\\') + 1);
}

function dodajDoKoszyka() {
  const nazwaPliku = nazwaPlikuBezSciezki(document.getElementById('plik').value);
  const sztuki = parseInt(document.getElementById('sztuki').value);
  const listaFormatow = document.getElementById('format');
  const cenaFormatu = parseFloat(listaFormatow.value);                        // np. 20
  const nazwaFormatu = listaFormatow.options[listaFormatow.selectedIndex].text.slice(0, 2); // 'A2'
  const laminowanie = document.getElementById('laminowanie').checked;

  let cenaSztuki = cenaFormatu;
  if (laminowanie) cenaSztuki += 3;
  const cenaPozycji = sztuki * cenaSztuki;

  // nowy blok pozycji – elementy DOM
  const pozycja = document.createElement('div');
  pozycja.className = 'pozycja';

  const miniatura = document.createElement('img');
  miniatura.src = nazwaPliku;      // plik z folderu strony
  miniatura.alt = nazwaPliku;
  miniatura.className = 'miniatura';

  const opis = document.createElement('p');
  opis.textContent = 'Plik: ' + nazwaPliku + ', format ' + nazwaFormatu + ', ' + sztuki + ' szt.';

  const cena = document.createElement('p');
  cena.textContent = 'Cena: ' + cenaPozycji + ' zł';

  pozycja.appendChild(miniatura);
  pozycja.appendChild(opis);
  pozycja.appendChild(cena);
  document.getElementById('koszyk').appendChild(pozycja); // na końcu koszyka

  sumaKoszyka += cenaPozycji;
  document.getElementById('suma').textContent = 'Razem: ' + sumaKoszyka + ' zł';
}
Podgląd

Dwa zestawy testowe: 2 szt. A2 bez laminowania → 40 zł; 3 szt. A3 z laminowaniem → 3 × 15 = 45 zł; suma 85 zł.

Zadanie 3
trudnejak na INF.03

Wypożyczalnia rowerów: galeria z pętli i obliczenie wg stanu

Strona rowery.html (HTML gotowy, folder zawiera pliki rower1.jpg…rower6.jpg oraz rower1d.jpg…rower6d.jpg):

rowery.html (fragment)
<div id="miniatury"></div>
<div id="galeria">
  <button id="poprzedni">&lt;</button>
  <img id="duzy" src="rower1d.jpg" alt="Rower 1">
  <button id="nastepny">&gt;</button>
</div>
<p id="opis">Rower 1 – miejski, 10 zł/h</p>
<label>Liczba godzin: <input type="number" id="godziny" value="1" min="1"></label>
<button id="oblicz">Oblicz</button>
<p id="koszt"></p>

Skrypt wykonywany po stronie klienta:

  1. Pętla tworzy w bloku #miniatury sześć obrazów rower1.jpg…rower6.jpg, każdy z klasą miniatura, tekstem alternatywnym „Rower N” i dymkiem (title) „Rower N” (N = numer).
  2. Kliknięcie miniatury wyświetla w #duzy plik rowerNd.jpg i aktualizuje akapit #opis: „Rower N – miejski, 10 zł/h” dla rowerów 1–3 albo „Rower N – górski, 16 zł/h” dla 4–6.
  3. Przyciski „<” i „>” zmieniają duży obraz na poprzedni/następny z zawijaniem: po 6 → 1, przed 1 → 6 (z aktualizacją opisu).
  4. „Oblicz” pobiera liczbę godzin, sprawdza, który rower jest aktualnie wyświetlony, i wypisuje pod przyciskiem „Rower N, <godziny> h: <koszt> zł” wg stawki 10 lub 16 zł/h. Ma działać także dla stanu początkowego (rower 1).
  5. Znaczące nazwy.

Kryteria (0/1):

  • 5.1 JavaScript, co najmniej jedna poprawna instrukcja.
  • 5.2 Miniatury tworzone pętlą (createElement w pętli), każda z klasą, alt i title z numerem.
  • 5.3 Kliknięcie miniatury zmienia src dużego obrazu na właściwy plik i opis.
  • 5.4 „>” po ostatnim pokazuje pierwszy, „<” przed pierwszym – ostatni.
  • 5.5 Skrypt pobiera liczbę godzin z pola.
  • 5.6 Koszt zależy od wyświetlonego roweru – sprawdzane dla roweru miejskiego, górskiego i stanu początkowego.
  • 5.7 Tekst wyniku pod przyciskiem w podanym formacie – dla dwóch liczb godzin.
  • 5.8 Znaczące nazewnictwo.
Pokaż rozwiązanie
Rozwiązanie: wypożyczalnia rowerów
// Zamiennik plików rowerN.jpg / rowerNd.jpg – na egzaminie wpisujesz nazwy plików.
function obrazek(numer, szer, wys) {
  const kolor = numer <= 3 ? 'SteelBlue' : 'DarkOliveGreen';
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + szer + '" height="' + wys + '">' +
    '<rect width="' + szer + '" height="' + wys + '" fill="' + kolor + '"/>' +
    '<text x="' + szer / 2 + '" y="' + (wys / 2 + 6) + '" font-size="' + wys / 3 + '" fill="white" text-anchor="middle" font-family="system-ui">rower' + numer + '</text></svg>';
  return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg);
}
function plikMiniatury(numer) { return obrazek(numer, 48, 32); }   // egzamin: 'rower' + numer + '.jpg'
function plikDuzy(numer) { return obrazek(numer, 200, 110); }      // egzamin: 'rower' + numer + 'd.jpg'

const LICZBA_ROWEROW = 6;
let numerRoweru = 1; // stan: który rower jest wyświetlony

const duzy = document.getElementById('duzy');

function stawka(numer) { return numer <= 3 ? 10 : 16; }
function typRoweru(numer) { return numer <= 3 ? 'miejski' : 'górski'; }

function pokazRower(numer) {
  numerRoweru = numer;
  duzy.src = plikDuzy(numer);
  duzy.alt = 'Rower ' + numer;
  document.getElementById('opis').textContent =
    'Rower ' + numer + ' – ' + typRoweru(numer) + ', ' + stawka(numer) + ' zł/h';
}

// 1. miniatury generowane pętlą
const blokMiniatur = document.getElementById('miniatury');
for (let i = 1; i <= LICZBA_ROWEROW; i++) {
  const miniatura = document.createElement('img');
  miniatura.src = plikMiniatury(i);
  miniatura.alt = 'Rower ' + i;
  miniatura.title = 'Rower ' + i;            // dymek
  miniatura.className = 'miniatura';
  miniatura.addEventListener('click', () => pokazRower(i)); // każda zna swój numer
  blokMiniatur.appendChild(miniatura);
}

// 3. galeria z zawijaniem
document.getElementById('nastepny').addEventListener('click', () => {
  let nowy = numerRoweru + 1;
  if (nowy > LICZBA_ROWEROW) nowy = 1;
  pokazRower(nowy);
});
document.getElementById('poprzedni').addEventListener('click', () => {
  let nowy = numerRoweru - 1;
  if (nowy < 1) nowy = LICZBA_ROWEROW;
  pokazRower(nowy);
});

// 4. obliczenie zależne od stanu
document.getElementById('oblicz').addEventListener('click', () => {
  const godziny = parseInt(document.getElementById('godziny').value);
  const koszt = godziny * stawka(numerRoweru);
  document.getElementById('koszt').textContent =
    'Rower ' + numerRoweru + ', ' + godziny + ' h: ' + koszt + ' zł';
});

pokazRower(1); // stan początkowy zgodny z HTML
Podgląd

Wersja bez zmiennej stanu, odczytująca numer z adresu obrazu (jak przy plikach rowerNd.jpg): const numer = parseInt(duzy.getAttribute('src').replace('rower', '')); – parseInt zatrzyma się na literze d. Obie wersje są poprawne; zmienna jest czytelniejsza.

Test powtórkowy

Test powtórkowy

Zasady egzaminu i czytanie kryteriów – sprawdź, czy wiesz, o co gra.

0/0poprawnych
Sprawdź się

Ile trwa część praktyczna egzaminu INF.03 i jaki jest próg zdania?

Sprawdź się

Z czego możesz korzystać podczas pisania skryptu na stanowisku egzaminacyjnym?

Sprawdź się

Skrypt nie uruchamia się z powodu błędu składni. Które kryteria egzaminator może jeszcze przyznać na podstawie kodu źródłowego?

Sprawdź się

Kryterium brzmi: „wynik zawiera miasto wybrane z listy – sprawdzane dla dwóch różnych miast”. Który skrypt go NIE spełni?

Sprawdź się

Który zrzut ekranu z wykonanych kwerend zostanie oceniony?

Sprawdź się

Arkusz: „pasek rośnie o 12 % przy każdym opuszczeniu pola; szerokość nigdy nie może przekroczyć 100 %”. Który fragment spełnia oba wymagania?

// A
szer = szer + 12; pasek.style.width = szer + '%';
// B
szer = Math.min(szer + 12, 100); pasek.style.width = szer + '%';
// C
if (szer < 100) pasek.style.width = '100%';
// D
szer = szer + 12; if (szer == 100) szer = 100;
Sprawdź się

HTML strony ma <p id='Wynik'></p>, a skrypt wykonuje document.getElementById('wynik').innerHTML = koszt;. Co zobaczy egzaminator?

Sprawdź się

W którym miejscu dokumentu należy umieścić <script>, aby document.getElementById znajdował elementy strony bez dodatkowych atrybutów?

Sprawdź się

Zadanie wymaga „znaczącego nazewnictwa zmiennych i funkcji w języku polskim lub angielskim”. Który zestaw nazw spełnia kryterium?

Sprawdź się

Arkusz mówi: „dla uproszczenia wszelką walidację należy pominąć”. Co powinieneś zrobić?