Przejdź do treści

Temat 18 · 2 × 45 minINF.03

Walidacja formularzy: HTML5 i JavaScript

Formularz bez walidacji przyjmie wszystko: puste imię, wiek „abc”, hasło różne od powtórzenia. Walidacja (validation) to sprawdzenie danych zanim zostaną użyte albo wysłane. Przeglądarka potrafi zrobić część pracy sama – wystarczą atrybuty HTML5 – a resztę piszesz w JavaScripcie: porównanie dwóch pól, własny komunikat w akapicie, zmiana koloru. W tej lekcji poznasz obie warstwy, dowiesz się, jak współpracują ze zdarzeniem submit, i jak zbudować komunikaty tak, by zrozumiał je także użytkownik czytnika ekranu.

Dwie warstwy walidacji

WarstwaGdzieCo sprawdzaZaletyOgraniczenia
HTML5 (atrybuty)w znacznikach inputpuste pole, zakres, długość, format, typzero kodu, dymki przeglądarki, działa bez JSkomunikaty standardowe, tylko pojedyncze pole, wymaga <form> i przycisku submit
JavaScriptw skrypciewszystko, także zależności między polami (hasło = powtórzenie)dowolny komunikat, miejsce, kolortrzeba napisać i przetestować
Serwer (PHP itp.)po wysłaniuwszystko jeszcze razjedyna warstwa, której użytkownik nie obejdziepoza tą lekcją

Walidacja po stronie klienta (HTML5 + JS) daje natychmiastową reakcję, ale nie jest zabezpieczeniem – użytkownik może wyłączyć skrypty albo zmienić HTML w narzędziach deweloperskich. Dlatego serwer zawsze sprawdza dane ponownie. Na egzaminie INF.03 liczy się warstwa kliencka: w części pisemnej jako „zadanie wykonywane tylko po stronie klienta – sprawdzanie danych w polu w czasie rzeczywistym”, w części praktycznej jako komunikat w akapicie.

Schemat: kliknięcie przycisku submit uruchamia walidację HTML5; przy błędzie pojawia się dymek i zdarzenie submit nie zachodzi; gdy jest poprawnie, zachodzi zdarzenie submit, w którym skrypt może zablokować wysłanie przez preventDefault
Rys. 1. Kolejność po kliknięciu „Wyślij”: najpierw atrybuty HTML5, dopiero potem zdarzenie submit i twój skrypt.

Atrybuty HTML5

Atrybuty wpisujesz w input, select lub textarea. Przeglądarka sprawdza je przy próbie wysłania formularza i blokuje wysłanie, pokazując dymek przy pierwszym niepoprawnym polu.

AtrybutZnaczeniePrzykład
requiredpole nie może być puste (checkbox: musi być zaznaczony; radio: jedna z grupy)<input required>
min, maxzakres liczby lub daty (type=number, range, date)<input type="number" min="1" max="10">
stepdozwolony krok (step="0.01" dla groszy, step="any" – dowolny)<input type="number" step="0.5">
minlength, maxlengthdługość napisu w znakach<input minlength="3" maxlength="20">
patternwyrażenie regularne, które musi pasować do całej wartości<input pattern="[0-9]{2}-[0-9]{3}">
type="email"wymaga postaci nazwa@domena<input type="email">
type="url"wymaga adresu ze schematem, np. https://…<input type="url">
type="number"tylko liczba (litery nie dają się wpisać, a jeśli się dadzą – pole jest niepoprawne)<input type="number">
Walidacja samymi atrybutami – spróbuj wysłać pusty formularz
<form id="zapisy">
  <p><label for="imie">Imię (min. 2 znaki):</label>
     <input id="imie" name="imie" required minlength="2" maxlength="30"></p>
  <p><label for="wiek">Wiek (13–19):</label>
     <input id="wiek" name="wiek" type="number" required min="13" max="19"></p>
  <p><label for="email">E-mail:</label>
     <input id="email" name="email" type="email" required></p>
  <p><label for="kod">Kod pocztowy (NN-NNN):</label>
     <input id="kod" name="kod" pattern="[0-9]{2}-[0-9]{3}" placeholder="00-000" required></p>
  <p><label><input type="checkbox" name="regulamin" required> Akceptuję regulamin</label></p>
  <button type="submit">Zapisz</button>
</form>
<p id="status"></p>
Podgląd

Kliknij „Zapisz” z pustymi polami: dymek pojawia się przy pierwszym błędnym polu, a tekst „Dane poprawne…” nie wyświetla się, bo funkcja w ogóle nie została wywołana.

Sprawdź się

Które pole zablokuje wysłanie formularza, gdy użytkownik wpisze w nie 7?

Kilka szczegółów, które mylą: pattern nie wymaga ^ i $ – wzorzec i tak musi objąć całą wartość. type="email" uznaje za poprawne jan@szkola (bez kropki w domenie) – jeśli chcesz wymusić domenę z kropką, dodaj pattern. placeholder to podpowiedź, nie wartość: pole z samym placeholder jest puste i required je odrzuci.

Stylowanie: :invalid, :valid, :user-invalid

Przeglądarka na bieżąco oznacza pola jako poprawne lub nie, a CSS może to pokazać. Pseudoklasa :invalid działa jednak od razu po załadowaniu strony – puste pole required jest już niepoprawne, więc cały formularz świeci na czerwono, zanim użytkownik cokolwiek wpisze. Dlatego do stylów błędów używaj :user-invalid – pasuje dopiero po interakcji użytkownika z polem (od końca 2023 r. działa we wszystkich głównych przeglądarkach).

Czerwona ramka dopiero po interakcji
input { padding: 6px; border: 2px solid #999; border-radius: 4px; }
input:user-invalid { border-color: Crimson; background: #fff0f0; }
input:user-invalid + .znak::after { content: " – popraw to pole"; color: Crimson; }
input:valid { border-color: SeaGreen; }
input:focus { outline: 3px solid #F2D338; }
Podgląd

Przydadzą się też :required, :optional, :in-range, :out-of-range i :placeholder-shown. Pamiętaj: kolor to dodatek – komunikat tekstowy jest obowiązkowy (patrz sekcja o dostępności).

Sterowanie walidacją HTML5 z JavaScriptu

Każde pole i cały formularz mają Constraint Validation API – zestaw metod i właściwości, którymi skrypt może zapytać o wynik walidacji HTML5 i go uzupełnić.

ElementCo daje
pole.checkValidity()true/false; przy false wywołuje na polu zdarzenie invalid, bez dymka
pole.reportValidity()jak wyżej, ale pokazuje dymek przeglądarki
formularz.checkValidity()true, gdy wszystkie pola są poprawne
pole.validityobiekt z flagami: valueMissing, typeMismatch, patternMismatch, tooShort, tooLong, rangeUnderflow, rangeOverflow, stepMismatch, badInput, customError, valid
pole.validationMessagetekst, który pokazałby dymek (po polsku, jeśli przeglądarka jest po polsku)
pole.setCustomValidity('tekst')ustawia własny błąd – pole staje się niepoprawne, dymek pokaże twój tekst
pole.setCustomValidity('')kasuje własny błąd (bez tego pole zostanie niepoprawne na zawsze)
<form novalidate>wyłącza dymki i blokadę – walidację robisz sam, ale checkValidity() nadal działa

Najczęstszy przypadek użycia setCustomValidity: porównanie dwóch pól, czego atrybuty nie potrafią.

Zgodność haseł przez setCustomValidity
const haslo = document.getElementById('haslo');
const haslo2 = document.getElementById('haslo2');

function sprawdzZgodnosc() {
  if (haslo.value !== haslo2.value) {
    haslo2.setCustomValidity('Hasła muszą być identyczne.'); // pole staje się niepoprawne
  } else {
    haslo2.setCustomValidity(''); // pusty napis = brak błędu – KONIECZNE
  }
}

// sprawdzaj na bieżąco, przy każdej zmianie któregokolwiek pola
haslo.addEventListener('input', sprawdzZgodnosc);
haslo2.addEventListener('input', sprawdzZgodnosc);

document.getElementById('rejestracja').addEventListener('submit', (e) => {
  e.preventDefault();
  document.getElementById('komunikat').textContent = 'Konto założone (walidacja HTML5 przeszła).';
});
Podgląd
Sprawdź się

Co zwróci pole.checkValidity() dla <input type='number' min='1' max='5' value='9'>?

validity.js
// podgląd, dlaczego pole jest niepoprawne – przydatne przy pisaniu własnych komunikatów
const wiek = document.getElementById('wiek'); // <input type="number" min="13" max="19" required>
wiek.addEventListener('input', () => {
  const v = wiek.validity;
  if (v.valueMissing)        console.log('puste pole');
  else if (v.rangeUnderflow) console.log('za mało – minimum ' + wiek.min);
  else if (v.rangeOverflow)  console.log('za dużo – maksimum ' + wiek.max);
  else if (v.badInput)       console.log('to nie jest liczba');
  else                       console.log('OK');
});

Walidacja w JavaScripcie

Gdy arkusz mówi „skrypt sprawdza, czy pola są wypełnione, i wyświetla komunikat w akapicie”, atrybuty HTML5 nie wystarczą – komunikat ma być twój, w twoim miejscu, często w określonym kolorze. Schemat jest zawsze ten sam:

  1. pobierz wartości kontrolek,
  2. sprawdź warunki po kolei; przy pierwszym błędzie wpisz komunikat do akapitu, ustaw kolor i zakończ (return),
  3. jeśli wszystko jest dobrze – policz lub wypisz wynik w innym kolorze.

Warunki, które powtarzają się w zadaniach:

SprawdzenieKodUwaga
pole pusteimie.trim() === ''trim() usuwa spacje – same spacje to też „puste”
to nie liczbaisNaN(parseFloat(wartosc))nie isNaN(wartosc): isNaN('') daje false, bo pusty napis zamienia się na 0
poza zakresemwiek < 13 || wiek > 19pamiętaj o || w zakresie „poza” i && w zakresie „wewnątrz”
za krótkiehaslo.length < 6length to właściwość, bez nawiasów
hasła różnehaslo !== powtorzporównuj napisy po trim() tylko wtedy, gdy to ma sens (haseł nie przycinaj)
checkbox niezaznaczony!zgoda.checkedchecked to true/false, nie napis
nic nie wybrano w selectmiasto.value === ''pierwsza opcja z value=""
zły format/^[0-9]{2}-[0-9]{3}$/.test(kod)wyrażenie regularne, tu z ^ i $
Walidacja w JS z komunikatem w akapicie
const komunikat = document.getElementById('komunikat');

function pokazBlad(tekst) {
  komunikat.textContent = tekst;
  komunikat.style.color = 'red';
}

function sprawdzFormularz(zdarzenie) {
  zdarzenie.preventDefault(); // zawsze zatrzymaj wysłanie – decyzję podejmujemy niżej

  const imie = document.getElementById('imie').value.trim();
  const wiek = parseInt(document.getElementById('wiek').value);
  const haslo = document.getElementById('haslo').value;
  const haslo2 = document.getElementById('haslo2').value;
  const zgoda = document.getElementById('zgoda').checked;

  if (imie === '') {
    pokazBlad('Wpisz imię.');
    return;                                   // pierwszy błąd kończy sprawdzanie
  }
  if (isNaN(wiek) || wiek < 13 || wiek > 19) {
    pokazBlad('Wiek musi być liczbą od 13 do 19.');
    return;
  }
  if (haslo.length < 6) {
    pokazBlad('Hasło musi mieć co najmniej 6 znaków.');
    return;
  }
  if (haslo !== haslo2) {
    pokazBlad('Podane hasła różnią się.');
    return;
  }
  if (!zgoda) {
    pokazBlad('Musisz zapoznać się z regulaminem.');
    return;
  }

  // wszystko poprawne
  komunikat.textContent = 'Witaj ' + imie.toUpperCase() + ', zgłoszenie przyjęte.';
  komunikat.style.color = 'Navy';
}

document.getElementById('zgloszenie').addEventListener('submit', sprawdzFormularz);
Podgląd

Dlaczego preventDefault() jest na samym początku? Bo w placu zabaw (i na egzaminie) nie ma serwera – wysłanie formularza przeładowałoby stronę i wymazało komunikat. Gdybyś chciał wysłać dane po udanej walidacji, wywołaj preventDefault() tylko w gałęziach z błędem.

Sprawdź się

Użytkownik zostawia pole wieku puste. Który warunek wykryje to poprawnie, jeśli wiek = document.getElementById('wiek').value?

Walidacja na bieżąco

Zamiast czekać na „Wyślij”, możesz sprawdzać pole przy każdej zmianie (input) albo przy opuszczeniu (blur/change). Każde pole dostaje własny akapit komunikatu.

Komunikat przy polu po opuszczeniu (blur)
function ustawBlad(pole, tekst) {
  document.getElementById(pole.id + '-blad').textContent = tekst;
  pole.setAttribute('aria-invalid', tekst !== ''); // true gdy jest błąd, false gdy pusto
}

document.getElementById('nick').addEventListener('blur', (e) => {
  const nick = e.target.value.trim();
  if (nick.length < 3 || nick.length > 10) ustawBlad(e.target, 'Nick musi mieć od 3 do 10 znaków.');
  else ustawBlad(e.target, '');
});

document.getElementById('punkty').addEventListener('input', (e) => {
  const punkty = parseFloat(e.target.value);
  if (isNaN(punkty) || punkty < 0 || punkty > 100) ustawBlad(e.target, 'Podaj liczbę od 0 do 100.');
  else ustawBlad(e.target, '');
});
Podgląd

Dialekt egzaminacyjny: onsubmit i return false

W materiałach CKE i starszych podręcznikach zdarzenie wysłania obsługuje atrybut onsubmit, a wysłanie blokuje zwrócenie false z funkcji. Musisz ten zapis czytać – w części pisemnej pojawia się pytanie „które zdarzenie może zablokować wysłanie formularza” (odpowiedź: onsubmit).

dialekt-egzaminacyjny.html
<form onsubmit="return sprawdz()">
  <input id="email" type="text">
  <input type="submit" value="Wyślij">
</form>
<p id="info"></p>
<script>
  function sprawdz() {
    var email = document.getElementById('email').value;
    if (email == '') {
      document.getElementById('info').innerHTML = 'Podaj e-mail';
      return false;   // false = formularz NIE zostanie wysłany
    }
    return true;      // true = wyślij
  }
</script>

Słowo return w atrybucie jest konieczne: onsubmit="sprawdz()" wywoła funkcję, ale zignoruje jej wynik i formularz wyśle się mimo błędu. W nowym kodzie pisz addEventListener('submit', …) z preventDefault() – robi dokładnie to samo, a nie da się zapomnieć return.

Sprawdź się

Formularz ma onsubmit='sprawdz()', a funkcja sprawdz zwraca false przy pustym polu. Co się stanie po kliknięciu „Wyślij” z pustym polem?

Dostępność komunikatów

Kryteria INF.03.3.6.6–8 wymagają stron „uwzględniających potrzeby użytkowników z różnymi niepełnosprawnościami”. Dla formularzy sprowadza się to do kilku nawyków, które poprawiają też zwykłą wygodę:

  • <label for="id"> dla każdego pola – kliknięcie etykiety ustawia fokus, a czytnik ekranu odczytuje nazwę pola. Sam placeholder nie jest etykietą (znika po wpisaniu).
  • aria-describedby="id-komunikatu" na polu – czytnik odczyta treść błędu razem z polem.
  • aria-live="polite" na akapicie komunikatu – zmiana tekstu zostanie odczytana bez przenoszenia fokusu. role="alert" działa podobnie, ale przerywa czytanie (dla pilnych błędów).
  • aria-invalid="true" na błędnym polu (i usunięcie po poprawie).
  • Nie tylko kolor: czerwony tekst to za mało dla osób z zaburzeniem widzenia barw – zawsze pełne zdanie, ewentualnie ikona lub prefiks „Błąd:”.
  • Fokus na pierwsze błędne pole po nieudanym wysłaniu: pole.focus() – użytkownik klawiatury od razu wie, co poprawić.
  • Atrybuty HTML5 są dostępne „za darmo”: dymek przeglądarki jest odczytywany przez czytniki ekranu.
fokus-na-blad.js
// po nieudanej walidacji ustaw fokus na pierwszym niepoprawnym polu
const pierwszyBlad = formularz.querySelector(':invalid, [aria-invalid="true"]');
if (pierwszyBlad) pierwszyBlad.focus();

Na egzaminie

Ściąga

SkładniaCo robiPrzykład
requiredpole obowiązkowe<input required>
min="1" max="10"zakres liczby/datytype="number" min="1" max="10"
minlength / maxlengthdługość napisuminlength="3"
pattern="…"wyrażenie regularne na całą wartośćpattern="[0-9]{2}-[0-9]{3}"
type="email" / "url" / "number"sprawdzenie formatutype="email" required
novalidatewyłącza dymki HTML5 w formularzu<form novalidate>
:invalid, :validstan pola (od załadowania strony)input:invalid { … }
:user-invalidstan pola po interakcji użytkownikainput:user-invalid { border-color: red }
pole.checkValidity()true/false bez dymkaif (!pole.checkValidity())
pole.reportValidity()jak wyżej, z dymkiemform.reportValidity()
pole.validity.valueMissingdlaczego niepoprawnerangeOverflow, patternMismatch, badInput
pole.setCustomValidity('tekst')własny błąd; '' kasujezgodność haseł
form.addEventListener('submit', f)reakcja na wysłanief(e) { e.preventDefault(); … }
onsubmit="return f()"dialekt egzaminacyjny; false blokujereturn false;
wartosc.trim() === ''pole puste (także same spacje)if (imie.trim() === '')
isNaN(parseFloat(w))to nie liczbaisNaN('') to false – nie używaj samego isNaN
pole.checkedcheckbox/radio zaznaczonyif (!zgoda.checked)
p.style.color = 'red'kolor komunikatu'Navy', '#c00'
aria-describedby, aria-live, aria-invaliddostępność komunikatów<p id="blad" aria-live="polite">

Zadania

Zadanie 1
łatwe

Formularz zamówienia samymi atrybutami

Zbuduj formularz zamówienia pizzy bez ani jednej linii walidacji w JS. Wymagania: imię (obowiązkowe, 2–30 znaków), telefon (obowiązkowy, dokładnie 9 cyfr – użyj pattern), liczba sztuk (1–10), rozmiar jako select z pierwszą opcją „– wybierz –” o pustej wartości (obowiązkowy), checkbox zgody (obowiązkowy). Dodaj CSS: błędne pole po interakcji ma czerwoną ramkę. Skrypt ma tylko zatrzymać wysłanie i wypisać „Zamówienie przyjęte” po udanej walidacji.

Pokaż rozwiązanie
Rozwiązanie: zamówienie pizzy
<form id="pizza">
  <p><label for="imie">Imię:</label> <input id="imie" required minlength="2" maxlength="30"></p>
  <p><label for="tel">Telefon (9 cyfr):</label> <input id="tel" pattern="[0-9]{9}" required inputmode="numeric"></p>
  <p><label for="ile">Liczba sztuk:</label> <input id="ile" type="number" min="1" max="10" value="1" required></p>
  <p><label for="rozmiar">Rozmiar:</label>
    <select id="rozmiar" required>
      <option value="">– wybierz –</option>
      <option value="s">mała</option>
      <option value="m">średnia</option>
      <option value="l">duża</option>
    </select></p>
  <p><label><input type="checkbox" required> Zgadzam się na kontakt telefoniczny</label></p>
  <button type="submit">Zamów</button>
</form>
<p id="wynik"></p>
Podgląd

Pusta pierwsza opcja z value="" sprawia, że required na select działa: wybór „– wybierz –” liczy się jako brak wartości.

Zadanie 2
średnie

Rejestracja z własnymi komunikatami

Formularz rejestracji: login, e-mail, hasło, powtórzenie hasła, wiek. Bez atrybutów HTML5 (albo z novalidate). Po kliknięciu „Zarejestruj” skrypt sprawdza po kolei i wypisuje w akapicie #komunikat pierwszy napotkany błąd na czerwono:

  • „Login musi mieć od 4 do 12 znaków.”
  • „E-mail musi zawierać znak @ i kropkę po nim.” (sprawdź przez indexOf lub includes)
  • „Hasło musi mieć co najmniej 8 znaków.”
  • „Hasła nie są identyczne.”
  • „Wiek musi być liczbą co najmniej 16.”

Gdy wszystko jest poprawne: „Konto LOGIN utworzone.” w kolorze green, gdzie LOGIN to login wielkimi literami. Dodatkowo ustaw fokus na błędnym polu.

Pokaż rozwiązanie
Rozwiązanie: rejestracja
const komunikat = document.getElementById('komunikat');

function blad(pole, tekst) {
  komunikat.textContent = tekst;
  komunikat.style.color = 'red';
  pole.focus();                       // użytkownik od razu trafia do błędnego pola
}

document.getElementById('rejestracja').addEventListener('submit', (e) => {
  e.preventDefault();

  const loginPole = document.getElementById('login');
  const emailPole = document.getElementById('email');
  const hasloPole = document.getElementById('haslo');
  const haslo2Pole = document.getElementById('haslo2');
  const wiekPole = document.getElementById('wiek');

  const login = loginPole.value.trim();
  const email = emailPole.value.trim();
  const wiek = parseInt(wiekPole.value);

  if (login.length < 4 || login.length > 12) return blad(loginPole, 'Login musi mieć od 4 do 12 znaków.');

  const malpa = email.indexOf('@');
  const kropkaPoMalpie = email.indexOf('.', malpa) > malpa; // kropka ZA znakiem @
  if (malpa < 1 || !kropkaPoMalpie) return blad(emailPole, 'E-mail musi zawierać znak @ i kropkę po nim.');

  if (hasloPole.value.length < 8) return blad(hasloPole, 'Hasło musi mieć co najmniej 8 znaków.');
  if (hasloPole.value !== haslo2Pole.value) return blad(haslo2Pole, 'Hasła nie są identyczne.');
  if (isNaN(wiek) || wiek < 16) return blad(wiekPole, 'Wiek musi być liczbą co najmniej 16.');

  komunikat.textContent = 'Konto ' + login.toUpperCase() + ' utworzone.';
  komunikat.style.color = 'green';
});
Podgląd

return blad(...) to skrót: funkcja blad nic nie zwraca (undefined), ale return kończy obsługę zdarzenia po pierwszym błędzie.

Zadanie 3
trudne

Walidacja na żywo z podsumowaniem

Trzy pola: nazwa produktu (3–40 znaków), cena (liczba większa od 0, maks. 2 miejsca po przecinku), ilość (liczba całkowita 1–999). Każde pole ma własny span z komunikatem (aria-live="polite", powiązany przez aria-describedby) aktualizowany przy zdarzeniu input. Przycisk „Dodaj” jest wyłączony (disabled), dopóki wszystkie pola nie są poprawne. Po kliknięciu „Dodaj” pod formularzem pojawia się akapit „Dodano: NAZWA, ILOŚĆ szt. po CENA zł = WARTOŚĆ zł” (wartość z dwoma miejscami po przecinku). Podpowiedź: trzymaj stan poprawności każdego pola w obiekcie poprawne = { nazwa: false, cena: false, ilosc: false }.

Pokaż rozwiązanie
Rozwiązanie: walidacja na żywo
const poprawne = { nazwa: false, cena: false, ilosc: false }; // stan każdego pola
const dodaj = document.getElementById('dodaj');

// reguły: funkcja zwraca pusty napis (OK) albo tekst błędu
const reguly = {
  nazwa: (w) => (w.trim().length >= 3 && w.trim().length <= 40 ? '' : 'Od 3 do 40 znaków.'),
  cena: (w) => (/^[0-9]+([.,][0-9]{1,2})?$/.test(w.trim()) && parseFloat(w.replace(',', '.')) > 0
    ? '' : 'Liczba większa od 0, maks. 2 miejsca po przecinku.'),
  ilosc: (w) => (/^[0-9]+$/.test(w.trim()) && parseInt(w) >= 1 && parseInt(w) <= 999
    ? '' : 'Liczba całkowita od 1 do 999.'),
};

function sprawdzPole(id) {
  const pole = document.getElementById(id);
  const blad = reguly[id](pole.value);
  document.getElementById(id + '-info').textContent = blad;
  pole.setAttribute('aria-invalid', blad !== '');
  poprawne[id] = blad === '';
  dodaj.disabled = !(poprawne.nazwa && poprawne.cena && poprawne.ilosc); // wszystkie trzy
}

for (const id of ['nazwa', 'cena', 'ilosc']) {
  document.getElementById(id).addEventListener('input', () => sprawdzPole(id));
}

document.getElementById('produkt').addEventListener('submit', (e) => {
  e.preventDefault();
  const nazwa = document.getElementById('nazwa').value.trim();
  const cena = parseFloat(document.getElementById('cena').value.replace(',', '.'));
  const ilosc = parseInt(document.getElementById('ilosc').value);
  const wartosc = (cena * ilosc).toFixed(2);
  document.getElementById('wynik').textContent =
    'Dodano: ' + nazwa + ', ' + ilosc + ' szt. po ' + cena.toFixed(2) + ' zł = ' + wartosc + ' zł';
});
Podgląd
Zadanie 4
średniejak na INF.03

Formularz zgłoszenia serwisowego

Strona serwis.html zawiera tabelę z kontrolkami (HTML gotowy):

serwis.html (fragment)
<table>
  <tr><td>Imię:</td><td><input type="text" id="imie"></td></tr>
  <tr><td>Nazwisko:</td><td><input type="text" id="nazwisko"></td></tr>
  <tr><td>Opis usterki:</td><td><textarea id="opis"></textarea></td></tr>
  <tr><td colspan="2"><input type="checkbox" id="regulamin"> Zapoznałem się z regulaminem serwisu</td></tr>
  <tr><td colspan="2"><button type="button" onclick="wyslijZgloszenie()">Prześlij</button></td></tr>
</table>
<hr>
<p id="komunikat"></p>

Skrypt, wykonywany po stronie klienta po kliknięciu „Prześlij”:

  1. Jeśli checkbox nie jest zaznaczony – w akapicie pod linią poziomą pojawia się tekst „Musisz zaakceptować regulamin serwisu” w kolorze czerwonym.
  2. Jeśli jest zaznaczony – w tym samym akapicie, w kolorze Navy: w pierwszej linii imię i nazwisko WIELKIMI LITERAMI, w drugiej linii „Opis usterki:”, w trzeciej treść opisu (do łamania linii użyj znacznika <br>).
  3. Stosuj znaczące nazwy zmiennych i funkcji.

Kryteria w stylu „Zasad oceniania” (0/1):

  • 5.1 Skrypt w języku JavaScript, funkcja uruchamiana przyciskiem „Prześlij”.
  • 5.2 Skrypt pobiera wartość z co najmniej jednej kontrolki.
  • 5.3 Przy niezaznaczonym checkboxie wyświetla „Musisz zaakceptować regulamin serwisu”.
  • 5.4 Przy zaznaczonym: imię i nazwisko w pierwszej linii, niżej „Opis usterki:” i treść.
  • 5.5 Komunikat wyświetlany w akapicie pod linią poziomą (nie w oknie dialogowym).
  • 5.6 Kolor: czerwony dla błędu, Navy dla danych.
  • 5.7 Imię i nazwisko wielkimi literami.
  • 5.8 Znaczące nazwy zmiennych i funkcji (PL lub EN).
Pokaż rozwiązanie
Rozwiązanie: zgłoszenie serwisowe
function wyslijZgloszenie() {
  const imie = document.getElementById('imie').value;
  const nazwisko = document.getElementById('nazwisko').value;
  const opis = document.getElementById('opis').value;
  const regulaminZaznaczony = document.getElementById('regulamin').checked;
  const komunikat = document.getElementById('komunikat');

  if (!regulaminZaznaczony) {
    komunikat.innerHTML = 'Musisz zaakceptować regulamin serwisu';
    komunikat.style.color = 'red';
  } else {
    const imieNazwisko = (imie + ' ' + nazwisko).toUpperCase();
    komunikat.innerHTML = imieNazwisko + '<br>Opis usterki:<br>' + opis; // innerHTML, bo <br>
    komunikat.style.color = 'Navy';
  }
}
Podgląd

Tu przycisk ma type="button" i nie ma <form>, więc nic nie przeładuje strony – preventDefault jest zbędny. Gdyby HTML z arkusza zawierał <form> i type="submit", trzeba by go dodać. Test: raz bez zaznaczenia, raz z zaznaczeniem i innymi danymi.

Test powtórkowy

Test powtórkowy

Format jak w części pisemnej INF.03: 4 odpowiedzi, jedna poprawna.

0/0poprawnych
Sprawdź się

Które zdarzenie formularza pozwala skryptowi zablokować jego wysłanie?

Sprawdź się

Który atrybut sprawi, że pole liczbowe przyjmie tylko wartości od 1 do 5?

Sprawdź się

Co zwraca metoda checkValidity() wywołana na polu formularza?

Sprawdź się

Formularz ma onsubmit='return sprawdz()'. Co musi zwrócić funkcja sprawdz, aby formularz NIE został wysłany?

Sprawdź się

Co wypisze ten kod, gdy pole wiek jest puste?

var wiek = document.getElementById('wiek').value;
if (isNaN(wiek)) {
document.write('blad');
} else {
document.write('ok');
}
Sprawdź się

Które zadanie może być wykonane wyłącznie po stronie klienta (w przeglądarce)?

Sprawdź się

Pole <input type='text' id='kod' pattern='[0-9]{2}-[0-9]{3}' required> jest w formularzu z przyciskiem submit. Która wartość pozwoli wysłać formularz?

Sprawdź się

Skrypt ma wyświetlić komunikat błędu „w akapicie pod przyciskiem, w kolorze czerwonym”. Który fragment realizuje to poprawnie?

Sprawdź się

Po wpisaniu różnych haseł wywołano haslo2.setCustomValidity('Hasła różne'). Użytkownik poprawił drugie hasło, ale formularz nadal się nie wysyła. Dlaczego?

Sprawdź się

Która pseudoklasa CSS oznacza pole niepoprawne dopiero po tym, jak użytkownik z nim pracował (a nie od razu po załadowaniu strony)?