3.3.1 - Hibajelzés
Röviden a szabványpontról
A WCAG 2.2 Success Criterion 3.3.1 (Error Identification) megköveteli, hogy amikor beviteli hibát észlelünk, a hibát azonosítsuk és szöveges formában ismertessük a felhasználóval. Ez vonatkozik minden felhasználói beviteli űrlapra, interaktív vezérlőre és adatbeviteli pontra a webes tartalomban. A cél, annak biztosítása, hogy azok a felhasználók, akik hibákat ejtenek az űrlapok kitöltése, vagy a bevitelek használata során, világosan tájékoztatva legyenek arról, hogy mit rontottak el, és így a felmerülő hibákat ki is tudják javítani.
Cél: Segíteni a felhasználókat abban, hogy elkerüljék a megtévesztést és frusztrációt azáltal, hogy világos és érthető hibaüzeneteket kapnak, amelyek pontosan megmondják, mit kell javítaniuk. Ez különösen fontos a kisegítő technológiákat használó felhasználók számára.
Mire vonatkozik: Minden olyan webes tartalomra, amely felhasználói adatbevitelt fogad, beleértve az űrlapokat, interaktív vezérlőket, keresőmezőket és bármilyen adatvalidációt igénylő elemet.
Kiket érint
Elsődleges felhasználók: Kognitív fogyatékossággal, tanulási nehézségekkel, gyengénlátással élő emberek vagy azok, akik képernyőolvasóra támaszkodnak, nagy hasznot húznak a világos hibaazonosításból. Segít nekik megérteni, hogy melyik bevitelt kell javítaniuk.
Másodlagos előnyök: Minden felhasználó számára előnyösek a világos hibaüzenetek, melyek javítják az általános használhatóságot és csökkentik a hibákat az űrlap beküldése vagy egyéb interakció során.
Tesztelés
- Manuális űrlap tesztelés: Szándékosan érvénytelen adatokat írj be és/vagy hagyd ki a kötelező mezőket és ellenőrizd, hogy megjelennek-e a hibaüzenetek és világosan leírják-e a problémát
- Képernyőolvasó tesztelés: Használj képernyőolvasót (pl. NVDA, JAWS, VoiceOver) annak ellenőrzésére, hogy a hibaüzenetek programozottan kapcsolódnak a megfelelő beviteli mezőkhöz és felolvasásra kerülnek-e
- Kizárólag billentyűzetes navigáció: Küldj el hibás űrlapokat csak billentyűzet használatával és győződj meg róla, hogy a fókusz a hibaüzenetre vagy annak közelébe kerül
- Automatizált eszközök: Használj akadálymentességi tesztelő eszközöket, mint az axe DevTools a hiányzó vagy helytelenül kapcsolt hibaüzenetek észlelésére
- Kód vizsgálat: Ellenőrizd, hogy a hibaüzenetek kapcsolódnak a bevitelekhez ARIA attribútumok használatával, mint az aria-describedby vagy a hibaüzenet elhelyezésével a címkékben vagy bevitelek közelében
Jó megoldások
1. Explicit hibaüzenetek beviteli mezőkhöz kapcsolva
<!-- REGISZTRÁCIÓS ŰRLAP - Teljes hibakezeléssel -->
<form class="registration-form" novalidate>
<div class="form-section">
<h2>Új fiók regisztrációja</h2>
<!-- Általános hibák megjelenítése -->
<div id="form-errors" class="form-errors" role="alert" aria-live="polite" style="display: none;">
<h3>Hibák történtek az űrlap kitöltése során:</h3>
<ul id="error-list"></ul>
</div>
</div>
<div class="form-group">
<label for="username">Felhasználónév *</label>
<input
type="text"
id="username"
name="username"
required
minlength="3"
maxlength="20"
pattern="[a-zA-Z0-9]+"
aria-describedby="username-help username-error"
autocomplete="username"
>
<div id="username-help" class="field-help">
3-20 karakter, csak betűk és számok használhatók
</div>
<div id="username-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="email">E-mail cím *</label>
<input
type="email"
id="email"
name="email"
required
aria-describedby="email-help email-error"
autocomplete="email"
>
<div id="email-help" class="field-help">
Valós e-mail címet adjon meg (pl. nev@domain.hu)
</div>
<div id="email-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="password">Jelszó *</label>
<input
type="password"
id="password"
name="password"
required
minlength="8"
aria-describedby="password-help password-error"
autocomplete="new-password"
>
<div id="password-help" class="field-help">
Minimum 8 karakter, tartalmazzon legalább egy számot és egy nagybetűt
</div>
<div id="password-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="password-confirm">Jelszó megerősítése *</label>
<input
type="password"
id="password-confirm"
name="password-confirm"
required
aria-describedby="password-confirm-help password-confirm-error"
autocomplete="new-password"
>
<div id="password-confirm-help" class="field-help">
Írja be újra a jelszót a megerősítéshez
</div>
<div id="password-confirm-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="birth-date">Születési dátum *</label>
<input
type="date"
id="birth-date"
name="birth-date"
required
max="2006-01-01"
aria-describedby="birth-date-help birth-date-error"
>
<div id="birth-date-help" class="field-help">
Legalább 18 évesnek kell lennie a regisztrációhoz
</div>
<div id="birth-date-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<fieldset>
<legend>Értesítési beállítások</legend>
<div class="checkbox-group">
<input type="checkbox" id="newsletter" name="newsletter" value="yes">
<label for="newsletter">Szeretnék hírlevelet kapni</label>
</div>
<div class="checkbox-group">
<input
type="checkbox"
id="terms"
name="terms"
required
aria-describedby="terms-error"
>
<label for="terms">
Elfogadom a <a href="/felhasznalasi-feltetelek" target="_blank">felhasználási feltételeket</a> *
</label>
</div>
<div id="terms-error" class="error-message" role="alert" style="display: none;"></div>
</fieldset>
</div>
<div class="form-actions">
<button type="submit" class="btn-submit">Fiók létrehozása</button>
<button type="reset" class="btn-reset">Űrlap törlése</button>
</div>
</form>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('.registration-form');
const inputs = form.querySelectorAll('input[required]');
// Valós idejű validáció (opcionális)
inputs.forEach(input => {
input.addEventListener('blur', function() {
validateField(input);
});
// Jelszó megerősítés speciális kezelése
if (input.id === 'password-confirm') {
input.addEventListener('input', function() {
validatePasswordMatch();
});
}
});
// Űrlap beküldési validáció
form.addEventListener('submit', function(event) {
event.preventDefault();
let isValid = true;
const errors = [];
// Minden kötelező mező ellenőrzése
inputs.forEach(input => {
const fieldValid = validateField(input);
if (!fieldValid) {
isValid = false;
const label = form.querySelector(`label[for="${input.id}"]`);
const fieldName = label ? label.textContent.replace(' *', '') : input.name;
errors.push({
field: input.id,
fieldName: fieldName,
message: getErrorMessage(input)
});
}
});
// Jelszó egyezés ellenőrzése
if (!validatePasswordMatch()) {
isValid = false;
}
if (isValid) {
// Sikeres validáció - űrlap elküldése
submitForm();
} else {
// Hibák megjelenítése
displayFormErrors(errors);
// Fókusz az első hibás mezőre
const firstErrorField = form.querySelector('input[aria-invalid="true"]');
if (firstErrorField) {
firstErrorField.focus();
firstErrorField.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
});
function validateField(input) {
const errorElement = document.getElementById(input.id + '-error');
let isValid = true;
let errorMessage = '';
// Kötelező mező ellenőrzése
if (input.hasAttribute('required') && !input.value.trim()) {
isValid = false;
errorMessage = `A ${getFieldLabel(input)} megadása kötelező.`;
}
// E-mail formátum ellenőrzése
else if (input.type === 'email' && input.value && !isValidEmail(input.value)) {
isValid = false;
errorMessage = 'Kérjük, adjon meg egy érvényes e-mail címet (pl. nev@domain.hu).';
}
// Jelszó erősség ellenőrzése
else if (input.id === 'password' && input.value && !isStrongPassword(input.value)) {
isValid = false;
errorMessage = 'A jelszónak legalább 8 karakter hosszúnak kell lennie, és tartalmaznia kell legalább egy számot és egy nagybetűt.';
}
// Felhasználónév formátum ellenőrzése
else if (input.id === 'username' && input.value && !isValidUsername(input.value)) {
isValid = false;
if (input.value.length < 3) {
errorMessage = 'A felhasználónév legalább 3 karakter hosszú legyen.';
} else if (input.value.length > 20) {
errorMessage = 'A felhasználónév legfeljebb 20 karakter hosszú lehet.';
} else {
errorMessage = 'A felhasználónév csak betűket és számokat tartalmazhat.';
}
}
// Születési dátum ellenőrzése
else if (input.id === 'birth-date' && input.value && !isValidAge(input.value)) {
isValid = false;
errorMessage = 'Legalább 18 évesnek kell lennie a regisztrációhoz.';
}
// Checkbox ellenőrzése
else if (input.type === 'checkbox' && input.hasAttribute('required') && !input.checked) {
isValid = false;
errorMessage = 'El kell fogadnia a felhasználási feltételeket a folytatáshoz.';
}
// Hibaállapot beállítása
input.setAttribute('aria-invalid', isValid ? 'false' : 'true');
if (isValid) {
errorElement.style.display = 'none';
errorElement.textContent = '';
input.classList.remove('field-error');
} else {
errorElement.style.display = 'block';
errorElement.textContent = errorMessage;
input.classList.add('field-error');
}
return isValid;
}
function validatePasswordMatch() {
const password = document.getElementById('password');
const passwordConfirm = document.getElementById('password-confirm');
const errorElement = document.getElementById('password-confirm-error');
if (passwordConfirm.value && password.value !== passwordConfirm.value) {
passwordConfirm.setAttribute('aria-invalid', 'true');
passwordConfirm.classList.add('field-error');
errorElement.style.display = 'block';
errorElement.textContent = 'A két jelszó nem egyezik meg.';
return false;
} else if (passwordConfirm.value) {
passwordConfirm.setAttribute('aria-invalid', 'false');
passwordConfirm.classList.remove('field-error');
errorElement.style.display = 'none';
errorElement.textContent = '';
}
return true;
}
function displayFormErrors(errors) {
const formErrors = document.getElementById('form-errors');
const errorList = document.getElementById('error-list');
if (errors.length > 0) {
errorList.innerHTML = '';
errors.forEach(error => {
const li = document.createElement('li');
const link = document.createElement('a');
link.href = `#${error.field}`;
link.textContent = `${error.fieldName}: ${error.message}`;
link.addEventListener('click', function(e) {
e.preventDefault();
document.getElementById(error.field).focus();
});
li.appendChild(link);
errorList.appendChild(li);
});
formErrors.style.display = 'block';
formErrors.scrollIntoView({ behavior: 'smooth', block: 'center' });
// Képernyőolvasó értesítése
announceToScreenReader(`${errors.length} hibát találtunk az űrlapban. Kérjük, javítsa ki őket.`);
} else {
formErrors.style.display = 'none';
}
}
function getFieldLabel(input) {
const label = form.querySelector(`label[for="${input.id}"]`);
return label ? label.textContent.replace(' *', '').toLowerCase() : input.name;
}
function getErrorMessage(input) {
const errorElement = document.getElementById(input.id + '-error');
return errorElement ? errorElement.textContent : 'Érvénytelen érték.';
}
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function isStrongPassword(password) {
return password.length >= 8 &&
/[A-Z]/.test(password) &&
/[0-9]/.test(password);
}
function isValidUsername(username) {
return username.length >= 3 &&
username.length <= 20 &&
/^[a-zA-Z0-9]+$/.test(username);
}
function isValidAge(birthDate) {
const today = new Date();
const birth = new Date(birthDate);
const age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
return age - 1 >= 18;
}
return age >= 18;
}
function submitForm() {
announceToScreenReader('Űrlap sikeresen elküldve. Kérjük, várjon...');
// Itt történne a tényleges űrlap elküldése
console.log('Űrlap elküldése...');
// Siker üzenet megjelenítése
setTimeout(() => {
alert('Regisztráció sikeres! Ellenőrizze e-mail címét az aktiválási linkért.');
}, 1000);
}
function announceToScreenReader(message) {
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', 'polite');
announcement.className = 'visually-hidden';
announcement.textContent = message;
document.body.appendChild(announcement);
setTimeout(() => {
if (announcement.parentNode) {
document.body.removeChild(announcement);
}
}, 1000);
}
});
</script>
<style>
.registration-form {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
background: white;
border: 1px solid #e9ecef;
border-radius: 8px;
}
.form-section h2 {
margin: 0 0 1.5rem 0;
color: #495057;
}
.form-errors {
background: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 4px;
padding: 1rem;
margin-bottom: 1.5rem;
}
.form-errors h3 {
margin: 0 0 0.5rem 0;
color: #721c24;
font-size: 1.1em;
}
.form-errors ul {
margin: 0;
padding-left: 1.2rem;
}
.form-errors li {
margin-bottom: 0.25rem;
}
.form-errors a {
color: #721c24;
text-decoration: none;
}
.form-errors a:hover, .form-errors a:focus {
text-decoration: underline;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
color: #495057;
}
.form-group input, .form-group select {
width: 100%;
padding: 0.75rem;
border: 2px solid #ced4da;
border-radius: 4px;
font-size: 1rem;
transition: border-color 0.2s ease;
}
.form-group input:focus, .form-group select:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.form-group input.field-error {
border-color: #dc3545;
background-color: #fff5f5;
}
.form-group input.field-error:focus {
border-color: #dc3545;
box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.1);
}
.field-help {
margin-top: 0.5rem;
font-size: 0.9em;
color: #6c757d;
line-height: 1.4;
}
.error-message {
margin-top: 0.5rem;
padding: 0.5rem;
background: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 4px;
color: #721c24;
font-size: 0.9em;
font-weight: 500;
}
fieldset {
border: 1px solid #e9ecef;
border-radius: 4px;
padding: 1rem;
margin: 0;
}
legend {
font-weight: 600;
color: #495057;
padding: 0 0.5rem;
}
.checkbox-group {
display: flex;
align-items: flex-start;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.checkbox-group input[type="checkbox"] {
width: auto;
margin-top: 0.25rem;
}
.checkbox-group label {
margin-bottom: 0;
font-weight: normal;
cursor: pointer;
}
.form-actions {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
.btn-submit, .btn-reset {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-submit {
background: #28a745;
color: white;
}
.btn-submit:hover, .btn-submit:focus {
background: #218838;
}
.btn-reset {
background: #6c757d;
color: white;
}
.btn-reset:hover, .btn-reset:focus {
background: #545b62;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@media (max-width: 768px) {
.registration-form {
margin: 1rem;
padding: 1rem;
}
.form-actions {
flex-direction: column;
}
}
</style>
Magyarázat: A hibaüzenetek az aria-describedby attribútummal kapcsolódnak a mezőkhöz, role=”alert” attribútummal dinamikusan bejelentésre kerülnek, és az aria-invalid attribútum jelzi a hibás állapotot a kisegítő technológiák számára.
2. Fókusz kezelése hiba után és programozott hibaazonosítás
<!-- KAPCSOLATFELVÉTELI ŰRLAP - Fejlett hibakezeléssel -->
<form class="contact-form" novalidate>
<div class="form-header">
<h2>Kapcsolatfelvételi űrlap</h2>
<!-- Hibák összesítő doboza -->
<div id="error-summary" class="error-summary" role="alert" aria-labelledby="error-summary-title" style="display: none;">
<h3 id="error-summary-title">Az űrlapban hibák találhatók</h3>
<p>Kérjük, javítsa ki az alábbi hibákat a folytatáshoz:</p>
<ul id="error-summary-list"></ul>
</div>
</div>
<div class="form-content">
<div class="form-group">
<label for="contact-name">
Teljes név
<span class="required-indicator" aria-label="kötelező">*</span>
</label>
<input
type="text"
id="contact-name"
name="name"
required
minlength="2"
aria-describedby="contact-name-help contact-name-error"
autocomplete="name"
>
<div id="contact-name-help" class="field-help">
Adja meg teljes nevét (vezetéknév és keresztnév)
</div>
<div id="contact-name-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="contact-email">
E-mail cím
<span class="required-indicator" aria-label="kötelező">*</span>
</label>
<input
type="email"
id="contact-email"
name="email"
required
aria-describedby="contact-email-help contact-email-error"
autocomplete="email"
>
<div id="contact-email-help" class="field-help">
Érvényes e-mail címet adjon meg (pl. nev@domain.hu)
</div>
<div id="contact-email-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="contact-phone">Telefonszám</label>
<input
type="tel"
id="contact-phone"
name="phone"
pattern="[\+]?[0-9\s\-\(\)]+"
aria-describedby="contact-phone-help contact-phone-error"
autocomplete="tel"
>
<div id="contact-phone-help" class="field-help">
Opcionális. Magyar vagy nemzetközi formátumban (pl. +36 1 234 5678)
</div>
<div id="contact-phone-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="contact-subject">
Tárgy
<span class="required-indicator" aria-label="kötelező">*</span>
</label>
<select id="contact-subject" name="subject" required aria-describedby="contact-subject-help contact-subject-error">
<option value="">Válasszon témát</option>
<option value="general">Általános kérdés</option>
<option value="technical">Technikai probléma</option>
<option value="billing">Számlázási kérdés</option>
<option value="complaint">Panasz</option>
<option value="suggestion">Javaslat</option>
</select>
<div id="contact-subject-help" class="field-help">
Válassza ki a legmegfelelőbb kategóriát
</div>
<div id="contact-subject-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="contact-message">
Üzenet
<span class="required-indicator" aria-label="kötelező">*</span>
</label>
<textarea
id="contact-message"
name="message"
required
minlength="10"
maxlength="1000"
rows="5"
aria-describedby="contact-message-help contact-message-error contact-message-count"
></textarea>
<div id="contact-message-help" class="field-help">
Részletesen írja le kérését vagy problémáját (minimum 10, maximum 1000 karakter)
</div>
<div id="contact-message-count" class="character-count" aria-live="polite">
0 / 1000 karakter
</div>
<div id="contact-message-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<fieldset>
<legend>Adatvédelmi hozzájárulás</legend>
<div class="checkbox-group">
<input
type="checkbox"
id="privacy-consent"
name="privacy"
required
aria-describedby="privacy-consent-error"
>
<label for="privacy-consent">
Elolvastam és elfogadom az
<a href="/adatvedelem" target="_blank" rel="noopener">adatvédelmi tájékoztatót</a>
<span class="required-indicator" aria-label="kötelező">*</span>
</label>
</div>
<div id="privacy-consent-error" class="error-message" role="alert" style="display: none;"></div>
</fieldset>
</div>
<div class="form-actions">
<button type="submit" class="btn-submit">
Üzenet küldése
<span id="submit-status" class="visually-hidden" aria-live="polite"></span>
</button>
<button type="reset" class="btn-reset">Mezők törlése</button>
</div>
</div>
</form>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('.contact-form');
const messageTextarea = document.getElementById('contact-message');
const characterCount = document.getElementById('contact-message-count');
const submitButton = form.querySelector('.btn-submit');
const submitStatus = document.getElementById('submit-status');
let isSubmitting = false;
// Karakter számláló frissítése
messageTextarea.addEventListener('input', function() {
const length = this.value.length;
const maxLength = 1000;
characterCount.textContent = `${length} / ${maxLength} karakter`;
if (length > maxLength * 0.9) {
characterCount.classList.add('warning');
} else {
characterCount.classList.remove('warning');
}
});
// Valós idejű validáció
const inputs = form.querySelectorAll('input, select, textarea');
inputs.forEach(input => {
input.addEventListener('blur', function() {
validateField(this);
});
// Azonnali visszajelzés javítás után
input.addEventListener('input', function() {
if (this.getAttribute('aria-invalid') === 'true') {
clearFieldError(this);
}
});
});
// Űrlap beküldés kezelése
form.addEventListener('submit', function(event) {
event.preventDefault();
if (isSubmitting) return;
const validationResult = validateForm();
if (validationResult.isValid) {
submitForm();
} else {
handleFormErrors(validationResult.errors);
}
});
function validateForm() {
const errors = [];
let isValid = true;
inputs.forEach(input => {
const fieldValid = validateField(input);
if (!fieldValid.isValid) {
isValid = false;
errors.push({
field: input.id,
fieldName: getFieldLabel(input),
message: fieldValid.message,
element: input
});
}
});
return { isValid, errors };
}
function validateField(input) {
const errorElement = document.getElementById(input.id + '-error');
let isValid = true;
let message = '';
// Kötelező mezők ellenőrzése
if (input.hasAttribute('required')) {
if (input.type === 'checkbox' && !input.checked) {
isValid = false;
message = 'Az adatvédelmi tájékoztató elfogadása kötelező.';
} else if (input.type !== 'checkbox' && !input.value.trim()) {
isValid = false;
message = `A ${getFieldLabel(input).toLowerCase()} megadása kötelező.`;
}
}
// Specifikus validációk
if (isValid && input.value.trim()) {
switch (input.type) {
case 'email':
if (!isValidEmail(input.value)) {
isValid = false;
message = 'Kérjük, adjon meg egy érvényes e-mail címet.';
}
break;
case 'tel':
if (!isValidPhone(input.value)) {
isValid = false;
message = 'Kérjük, adjon meg egy érvényes telefonszámot.';
}
break;
}
// Hossz ellenőrzése
if (input.hasAttribute('minlength') && input.value.length < parseInt(input.getAttribute('minlength'))) {
isValid = false;
const minLength = input.getAttribute('minlength');
message = `Legalább ${minLength} karakter szükséges.`;
}
if (input.hasAttribute('maxlength') && input.value.length > parseInt(input.getAttribute('maxlength'))) {
isValid = false;
const maxLength = input.getAttribute('maxlength');
message = `Maximum ${maxLength} karakter engedélyezett.`;
}
}
// Select mező specifikus ellenőrzés
if (input.tagName === 'SELECT' && input.hasAttribute('required') && !input.value) {
isValid = false;
message = 'Kérjük, válasszon egy opciót.';
}
// Hibaállapot beállítása
updateFieldError(input, isValid, message);
return { isValid, message };
}
function updateFieldError(input, isValid, message) {
const errorElement = document.getElementById(input.id + '-error');
input.setAttribute('aria-invalid', isValid ? 'false' : 'true');
if (isValid) {
input.classList.remove('field-error');
if (errorElement) {
errorElement.style.display = 'none';
errorElement.textContent = '';
}
} else {
input.classList.add('field-error');
if (errorElement) {
errorElement.style.display = 'block';
errorElement.textContent = message;
}
}
}
function clearFieldError(input) {
updateFieldError(input, true, '');
}
function handleFormErrors(errors) {
// Hibák összesítő megjelenítése
displayErrorSummary(errors);
// Fókusz az első hibás mezőre
if (errors.length > 0) {
const firstErrorField = errors[0].element;
// Smooth scroll az első hibához
firstErrorField.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
// Fókusz beállítása kis késleltetéssel
setTimeout(() => {
firstErrorField.focus();
}, 300);
// Képernyőolvasó értesítése
announceToScreenReader(`${errors.length} hibát találtunk az űrlapban. A kurzor az első hibás mezőre került.`);
}
}
function displayErrorSummary(errors) {
const errorSummary = document.getElementById('error-summary');
const errorList = document.getElementById('error-summary-list');
if (errors.length > 0) {
errorList.innerHTML = '';
errors.forEach(error => {
const li = document.createElement('li');
const link = document.createElement('a');
link.href = `#${error.field}`;
link.textContent = `${error.fieldName}: ${error.message}`;
link.addEventListener('click', function(e) {
e.preventDefault();
error.element.focus();
error.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
li.appendChild(link);
errorList.appendChild(li);
});
errorSummary.style.display = 'block';
errorSummary.scrollIntoView({ behavior: 'smooth', block: 'start' });
// Fókusz az error summary-ra
setTimeout(() => {
errorSummary.focus();
}, 300);
} else {
errorSummary.style.display = 'none';
}
}
function submitForm() {
isSubmitting = true;
submitButton.disabled = true;
submitStatus.textContent = 'Üzenet küldése folyamatban...';
// Szimuláció: űrlap küldése
setTimeout(() => {
isSubmitting = false;
submitButton.disabled = false;
submitStatus.textContent = '';
// Sikeres küldés
announceToScreenReader('Üzenet sikeresen elküldve!');
// Success üzenet megjelenítése
const successMessage = document.createElement('div');
successMessage.className = 'success-message';
successMessage.setAttribute('role', 'alert');
successMessage.innerHTML = `
<h3>Üzenet sikeresen elküldve!</h3>
<p>Köszönjük megkeresését. Munkatársunk 24 órán belül válaszol.</p>
`;
form.parentNode.insertBefore(successMessage, form);
form.style.display = 'none';
successMessage.scrollIntoView({ behavior: 'smooth', block: 'center' });
successMessage.focus();
}, 2000);
}
function getFieldLabel(input) {
const label = form.querySelector(`label[for="${input.id}"]`);
if (label) {
return label.textContent.replace(/\s*\*\s*$/, '').trim();
}
return input.name || input.id;
}
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function isValidPhone(phone) {
const phoneRegex = /^[\+]?[0-9\s\-\(\)]{6,}$/;
return phoneRegex.test(phone);
}
function announceToScreenReader(message) {
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', 'polite');
announcement.className = 'visually-hidden';
announcement.textContent = message;
document.body.appendChild(announcement);
setTimeout(() => {
if (announcement.parentNode) {
document.body.removeChild(announcement);
}
}, 1000);
}
});
</script>
<style>
.contact-form {
max-width: 700px;
margin: 2rem auto;
padding: 2rem;
background: white;
border: 1px solid #e9ecef;
border-radius: 8px;
}
.form-header h2 {
margin: 0 0 1.5rem 0;
color: #495057;
}
.error-summary {
background: #f8d7da;
border: 2px solid #f5c6cb;
border-radius: 6px;
padding: 1.5rem;
margin-bottom: 2rem;
outline: none;
}
.error-summary:focus {
outline: 3px solid #dc3545;
outline-offset: 2px;
}
.error-summary h3 {
margin: 0 0 0.5rem 0;
color: #721c24;
font-size: 1.2em;
}
.error-summary p {
margin: 0.5rem 0;
color: #721c24;
}
.error-summary ul {
margin: 0.5rem 0 0 0;
padding-left: 1.5rem;
}
.error-summary li {
margin-bottom: 0.5rem;
}
.error-summary a {
color: #721c24;
font-weight: 500;
text-decoration: none;
}
.error-summary a:hover, .error-summary a:focus {
text-decoration: underline;
outline: 2px solid #721c24;
outline-offset: 1px;
}
.required-indicator {
color: #dc3545;
font-weight: bold;
}
.character-count {
font-size: 0.9em;
color: #6c757d;
text-align: right;
margin-top: 0.25rem;
}
.character-count.warning {
color: #856404;
font-weight: bold;
}
.success-message {
background: #d4edda;
border: 2px solid #c3e6cb;
border-radius: 6px;
padding: 1.5rem;
margin-bottom: 2rem;
outline: none;
}
.success-message:focus {
outline: 3px solid #28a745;
outline-offset: 2px;
}
.success-message h3 {
margin: 0 0 0.5rem 0;
color: #155724;
}
.success-message p {
margin: 0;
color: #155724;
}
/* További stílusok az előző példából... */
</style>
Magyarázat: A rendszer automatikusan az első hibás mezőre irányítja a fókuszt, hibák összesítőt jelenít meg, és programozott kapcsolatot biztosít az aria-invalid és aria-describedby attribútumokkal.
3. Világos és konkrét hibaüzenetek leírásokkal
<!-- BEJELENTKEZÉSI ŰRLAP - Specifikus hibaüzenetekkel -->
<form class="login-form" novalidate>
<div class="login-header">
<h2>Bejelentkezés</h2>
<p>Adja meg felhasználónevét és jelszavát a belépéshez.</p>
</div>
<div class="form-group">
<label for="login-username">Felhasználónév vagy e-mail cím</label>
<input
type="text"
id="login-username"
name="username"
required
autocomplete="username"
aria-describedby="login-username-error"
>
<div id="login-username-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="login-password">Jelszó</label>
<div class="password-container">
<input
type="password"
id="login-password"
name="password"
required
autocomplete="current-password"
aria-describedby="login-password-error"
>
<button
type="button"
class="password-toggle"
aria-label="Jelszó megjelenítése"
onclick="togglePasswordVisibility('login-password')"
>
<span class="toggle-text">Mutat</span>
</button>
</div>
<div id="login-password-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="remember-me" name="remember">
<label for="remember-me">Emlékezzen rám ezen az eszközön</label>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn-login">Bejelentkezés</button>
<a href="/jelszo-visszaallitas" class="forgot-password">Elfelejtette jelszavát?</a>
</div>
<!-- Általános hiba üzenetek -->
<div id="login-general-error" class="general-error" role="alert" style="display: none;"></div>
</form>
<!-- FIZETÉSI ŰRLAP - Komplex validációval -->
<form class="payment-form" novalidate>
<div class="payment-header">
<h2>Fizetési adatok</h2>
<p>Minden mezőt pontosan töltsön ki a biztonságos fizetéshez.</p>
</div>
<div class="form-group">
<label for="card-number">Bankkártya száma</label>
<input
type="text"
id="card-number"
name="cardNumber"
required
maxlength="19"
pattern="[0-9\s]{13,19}"
autocomplete="cc-number"
aria-describedby="card-number-help card-number-error"
placeholder="1234 5678 9012 3456"
>
<div id="card-number-help" class="field-help">
16 számjegy, szóközökkel vagy anélkül
</div>
<div id="card-number-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-row">
<div class="form-group form-group-half">
<label for="expiry-date">Lejárati dátum</label>
<input
type="text"
id="expiry-date"
name="expiryDate"
required
maxlength="5"
pattern="[0-9]{2}/[0-9]{2}"
autocomplete="cc-exp"
aria-describedby="expiry-date-help expiry-date-error"
placeholder="MM/YY"
>
<div id="expiry-date-help" class="field-help">
HH/ÉÉ formátumban
</div>
<div id="expiry-date-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group form-group-half">
<label for="cvv">CVC/CVV kód</label>
<input
type="text"
id="cvv"
name="cvv"
required
maxlength="4"
pattern="[0-9]{3,4}"
autocomplete="cc-csc"
aria-describedby="cvv-help cvv-error"
placeholder="123"
>
<div id="cvv-help" class="field-help">
3-4 számjegy a kártya hátulján
</div>
<div id="cvv-error" class="error-message" role="alert" style="display: none;"></div>
</div>
</div>
<div class="form-group">
<label for="cardholder-name">Kártyatulajdonos neve</label>
<input
type="text"
id="cardholder-name"
name="cardholderName"
required
autocomplete="cc-name"
aria-describedby="cardholder-name-help cardholder-name-error"
placeholder="Ahogy a kártyán szerepel"
>
<div id="cardholder-name-help" class="field-help">
Pontosan úgy, ahogy a bankkártyán szerepel
</div>
<div id="cardholder-name-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-actions">
<button type="submit" class="btn-pay">
Fizetés: <span class="amount">15.990 Ft</span>
</button>
</div>
</form>
<script>
// Specifikus hibaüzenetek definiálása
const ErrorMessages = {
// Bejelentkezési hibák
login: {
usernameRequired: 'Kérjük, adja meg felhasználónevét vagy e-mail címét.',
usernameInvalid: 'A felhasználónév vagy e-mail cím formátuma helytelen.',
passwordRequired: 'Kérjük, adja meg jelszavát.',
passwordTooShort: 'A jelszó túl rövid. Legalább 6 karakter szükséges.',
invalidCredentials: 'Hibás felhasználónév vagy jelszó. Kérjük, ellenőrizze adatait és próbálja újra.',
accountLocked: 'A fiók átmenetileg zárolva van túl sok sikertelen bejelentkezési kísérlet miatt. Próbálja újra 15 perc múlva.',
accountDisabled: 'Ez a fiók inaktív. Kérjük, vegye fel a kapcsolatot az ügyfélszolgálattal.',
},
// Fizetési hibák
payment: {
cardNumberRequired: 'Kérjük, adja meg bankkártyájának számát.',
cardNumberInvalid: 'A bankkártya száma érvénytelen. Kérjük, ellenőrizze és adja meg újra (16 számjegy).',
cardNumberUnsupported: 'Ez a kártyatípus nem támogatott. Kérjük, használjon Visa vagy Mastercard kártyát.',
expiryRequired: 'Kérjük, adja meg a kártya lejárati dátumát.',
expiryInvalid: 'A lejárati dátum formátuma helytelen. Használja a HH/ÉÉ formátumot (pl. 12/25).',
expiryExpired: 'Ez a bankkártya már lejárt. Kérjük, használjon érvényes kártyát.',
cvvRequired: 'Kérjük, adja meg a CVC/CVV kódot.',
cvvInvalid: 'A CVC/CVV kód érvénytelen. 3-4 számjegyű kód szükséges.',
cardholderRequired: 'Kérjük, adja meg a kártyatulajdonos nevét.',
cardholderInvalid: 'A kártyatulajdonos neve csak betűket és szóközöket tartalmazhat.',
processingError: 'Hiba történt a fizetés feldolgozása során. Kérjük, próbálja újra.'
}
};
// Bejelentkezési űrlap kezelése
document.querySelector('.login-form').addEventListener('submit', function(event) {
event.preventDefault();
const username = document.getElementById('login-username');
const password = document.getElementById('login-password');
const generalError = document.getElementById('login-general-error');
let hasErrors = false;
// Felhasználónév validáció
if (!username.value.trim()) {
showFieldError('login-username', ErrorMessages.login.usernameRequired);
hasErrors = true;
} else if (!isValidUsernameOrEmail(username.value)) {
showFieldError('login-username', ErrorMessages.login.usernameInvalid);
hasErrors = true;
} else {
clearFieldError('login-username');
}
// Jelszó validáció
if (!password.value) {
showFieldError('login-password', ErrorMessages.login.passwordRequired);
hasErrors = true;
} else if (password.value.length < 6) {
showFieldError('login-password', ErrorMessages.login.passwordTooShort);
hasErrors = true;
} else {
clearFieldError('login-password');
}
if (hasErrors) {
// Fókusz az első hibás mezőre
const firstError = this.querySelector('input[aria-invalid="true"]');
if (firstError) {
firstError.focus();
}
return;
}
// Szimulált bejelentkezési kísérlet
simulateLogin(username.value, password.value, generalError);
});
// Fizetési űrlap kezelése
document.querySelector('.payment-form').addEventListener('submit', function(event) {
event.preventDefault();
const fields = {
cardNumber: document.getElementById('card-number'),
expiryDate: document.getElementById('expiry-date'),
cvv: document.getElementById('cvv'),
cardholderName: document.getElementById('cardholder-name')
};
let hasErrors = false;
// Bankkártya szám validáció
const cardNumber = fields.cardNumber.value.replace(/\s/g, '');
if (!cardNumber) {
showFieldError('card-number', ErrorMessages.payment.cardNumberRequired);
hasErrors = true;
} else if (!isValidCardNumber(cardNumber)) {
showFieldError('card-number', ErrorMessages.payment.cardNumberInvalid);
hasErrors = true;
} else if (!isSupportedCardType(cardNumber)) {
showFieldError('card-number', ErrorMessages.payment.cardNumberUnsupported);
hasErrors = true;
} else {
clearFieldError('card-number');
}
// Lejárati dátum validáció
const expiry = fields.expiryDate.value;
if (!expiry) {
showFieldError('expiry-date', ErrorMessages.payment.expiryRequired);
hasErrors = true;
} else if (!isValidExpiryFormat(expiry)) {
showFieldError('expiry-date', ErrorMessages.payment.expiryInvalid);
hasErrors = true;
} else if (isCardExpired(expiry)) {
showFieldError('expiry-date', ErrorMessages.payment.expiryExpired);
hasErrors = true;
} else {
clearFieldError('expiry-date');
}
// CVV validáció
const cvv = fields.cvv.value;
if (!cvv) {
showFieldError('cvv', ErrorMessages.payment.cvvRequired);
hasErrors = true;
} else if (!isValidCVV(cvv)) {
showFieldError('cvv', ErrorMessages.payment.cvvInvalid);
hasErrors = true;
} else {
clearFieldError('cvv');
}
// Kártyatulajdonos validáció
const cardholderName = fields.cardholderName.value.trim();
if (!cardholderName) {
showFieldError('cardholder-name', ErrorMessages.payment.cardholderRequired);
hasErrors = true;
} else if (!isValidCardholderName(cardholderName)) {
showFieldError('cardholder-name', ErrorMessages.payment.cardholderInvalid);
hasErrors = true;
} else {
clearFieldError('cardholder-name');
}
if (hasErrors) {
const firstError = this.querySelector('input[aria-invalid="true"]');
if (firstError) {
firstError.focus();
}
return;
}
// Fizetés feldolgozása
processPayment();
});
// Segédfüggvények
function showFieldError(fieldId, message) {
const field = document.getElementById(fieldId);
const errorElement = document.getElementById(fieldId + '-error');
field.setAttribute('aria-invalid', 'true');
field.classList.add('field-error');
errorElement.style.display = 'block';
errorElement.textContent = message;
}
function clearFieldError(fieldId) {
const field = document.getElementById(fieldId);
const errorElement = document.getElementById(fieldId + '-error');
field.setAttribute('aria-invalid', 'false');
field.classList.remove('field-error');
errorElement.style.display = 'none';
errorElement.textContent = '';
}
function isValidUsernameOrEmail(value) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const usernameRegex = /^[a-zA-Z0-9_]{3,}$/;
return emailRegex.test(value) || usernameRegex.test(value);
}
function isValidCardNumber(cardNumber) {
return cardNumber.length === 16 && /^[0-9]+$/.test(cardNumber);
}
function isSupportedCardType(cardNumber) {
// Visa: 4-gyel kezdődik, Mastercard: 5-tel kezdődik
return cardNumber.startsWith('4') || cardNumber.startsWith('5');
}
function isValidExpiryFormat(expiry) {
return /^[0-9]{2}\/[0-9]{2}$/.test(expiry);
}
function isCardExpired(expiry) {
const [month, year] = expiry.split('/').map(Number);
const now = new Date();
const currentYear = now.getFullYear() % 100;
const currentMonth = now.getMonth() + 1;
return year < currentYear || (year === currentYear && month < currentMonth);
}
function isValidCVV(cvv) {
return /^[0-9]{3,4}$/.test(cvv);
}
function isValidCardholderName(name) {
return /^[a-zA-ZáéíóöőúüűÁÉÍÓÖŐÚÜŰ\s]{2,}$/.test(name);
}
function simulateLogin(username, password, generalErrorElement) {
// Szimulált bejelentkezési logika
setTimeout(() => {
const randomOutcome = Math.random();
if (randomOutcome < 0.3) {
// Sikertelen bejelentkezés
generalErrorElement.textContent = ErrorMessages.login.invalidCredentials;
generalErrorElement.style.display = 'block';
} else if (randomOutcome < 0.4) {
// Zárolt fiók
generalErrorElement.textContent = ErrorMessages.login.accountLocked;
generalErrorElement.style.display = 'block';
} else {
// Sikeres bejelentkezés
alert('Sikeres bejelentkezés!');
}
}, 1000);
}
function processPayment() {
alert('Fizetés feldolgozása... (szimulált)');
}
function togglePasswordVisibility(fieldId) {
const field = document.getElementById(fieldId);
const button = field.nextElementSibling;
const toggleText = button.querySelector('.toggle-text');
if (field.type === 'password') {
field.type = 'text';
button.setAttribute('aria-label', 'Jelszó elrejtése');
toggleText.textContent = 'Rejt';
} else {
field.type = 'password';
button.setAttribute('aria-label', 'Jelszó megjelenítése');
toggleText.textContent = 'Mutat';
}
}
</script>
<style>
.login-form, .payment-form {
max-width: 500px;
margin: 2rem auto;
padding: 2rem;
background: white;
border: 1px solid #e9ecef;
border-radius: 8px;
}
.password-container {
position: relative;
}
.password-toggle {
position: absolute;
right: 0.5rem;
top: 50%;
transform: translateY(-50%);
background: #f8f9fa;
border: 1px solid #ced4da;
border-radius: 4px;
padding: 0.25rem 0.5rem;
cursor: pointer;
font-size: 0.8em;
}
.form-row {
display: flex;
gap: 1rem;
}
.form-group-half {
flex: 1;
}
.general-error {
background: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 4px;
padding: 1rem;
margin-top: 1rem;
color: #721c24;
}
.btn-login, .btn-pay {
width: 100%;
padding: 0.75rem;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
}
.btn-pay {
background: #28a745;
font-size: 1.1em;
font-weight: bold;
}
.amount {
background: rgba(255, 255, 255, 0.2);
padding: 0.25rem 0.5rem;
border-radius: 4px;
}
.forgot-password {
display: block;
text-align: center;
margin-top: 1rem;
color: #007bff;
text-decoration: none;
}
</style>
Magyarázat: A hibaüzenetek konkrétak és konstruktívak, világosan megmondják, mi a probléma és hogyan javítható ki. Kerülik a homályos megfogalmazást, mint például az „Érvénytelen bevitel”.
Rossz megoldások
Nem kapcsolódnak hibaüzenetek a beviteli mezőkhöz
<!-- HIBÁS: A hibaüzenet nincs programozottan kapcsolva -->
<form>
<label for="phone">Telefonszám:</label>
<input id="phone" type="tel" required>
<!-- HIBA: Nincs aria-describedby vagy más kapcsolat -->
<span style="color: red;">Kérjük, adja meg telefonszámát.</span>
</form>
<!-- HIBÁS: Hibaüzenet távol a mezőtől -->
<form>
<div class="form-group">
<label for="email">E-mail:</label>
<input id="email" type="email" required>
</div>
<div class="form-group">
<label for="password">Jelszó:</label>
<input id="password" type="password" required>
</div>
<!-- HIBA: Hibaüzenetek messze a mezőktől, nincs kapcsolat -->
<div class="errors">
<p>Az e-mail cím érvénytelen.</p>
<p>A jelszó túl rövid.</p>
</div>
</form>
Probléma: A képernyőolvasók nem tudják azonosítani, hogy melyik hibaüzenet, melyik mezőhöz tartozik, mert nincs programozott kapcsolat közöttük.
Csak szín használata hibák jelölésére
<!-- HIBÁS: Csak vizuális jelzés színnel -->
<form>
<label for="zip">Irányítószám:</label>
<!-- HIBA: Csak a piros szegély jelzi a hibát -->
<input id="zip" type="text" style="border: 2px solid red;" required>
<!-- Nincs szöveges hibaüzenet -->
</form>
<!-- HIBÁS: Ikonok szöveg nélkül -->
<form>
<label for="username">Felhasználónév:</label>
<div class="input-container">
<input id="username" type="text" required>
<!-- HIBA: Csak vizuális ikon, nincs szöveges információ -->
<span class="error-icon" style="color: red;">❌</span>
</div>
</form>
<!-- HIBÁS: Háttérszín változás szöveg nélkül -->
<form>
<label for="age">Életkor:</label>
<!-- HIBA: Csak a rózsaszín háttér jelzi a hibát -->
<input id="age" type="number" style="background-color: #ffcccc;" required>
</form>
Probléma: A színvak vagy gyengénlátó felhasználók nem érzékelik a színváltozásokat, és nincs alternatív módja a hibák azonosításának.
Nem jelenik meg a hibaüzenet
<!-- HIBÁS: Néma validáció -->
<form>
<label for="required-field">Kötelező mező:</label>
<input id="required-field" type="text" required>
<button type="submit">Küldés</button>
<script>
// HIBA: Csak console.log, nincs felhasználói visszajelzés
document.querySelector('form').addEventListener('submit', function(e) {
const input = document.getElementById('required-field');
if (!input.value) {
e.preventDefault();
console.log('Hiba: Kötelező mező üres'); // Felhasználó nem látja!
}
});
</script>
</form>
<!-- HIBÁS: Alert popup-ok -->
<form>
<label for="email-bad">E-mail:</label>
<input id="email-bad" type="email" required>
<button type="submit">Küldés</button>
<script>
// HIBA: Alert popup nem akadálymentes és zavaró
document.querySelector('form').addEventListener('submit', function(e) {
const email = document.getElementById('email-bad');
if (!email.value) {
e.preventDefault();
alert('E-mail cím megadása kötelező!'); // Rossz UX
}
});
</script>
</form>
<!-- HIBÁS: Rejtett hibaüzenetek -->
<form>
<label for="password-bad">Jelszó:</label>
<input id="password-bad" type="password" required>
<!-- HIBA: Hibaüzenet létezik, de sosem válik láthatóvá -->
<div id="password-error" style="display: none; visibility: hidden;">
Jelszó szükséges
</div>
<button type="submit">Küldés</button>
</form>
Probléma: A felhasználók nem kapnak visszajelzést a hibákról, így nem tudják, mit javítsanak ki.
A fókusz a küldés gombon marad hiba esetén
<!-- HIBÁS: Rossz fókusz kezelés -->
<form id="bad-focus-form">
<div>
<label for="name-bad">Név:</label>
<input id="name-bad" type="text" required>
<div id="name-bad-error" style="display: none; color: red;"></div>
</div>
<div>
<label for="email-bad-focus">E-mail:</label>
<input id="email-bad-focus" type="email" required>
<div id="email-bad-focus-error" style="display: none; color: red;"></div>
</div>
<button type="submit" id="submit-bad">Küldés</button>
</form>
<script>
document.getElementById('bad-focus-form').addEventListener('submit', function(e) {
e.preventDefault();
const nameField = document.getElementById('name-bad');
const emailField = document.getElementById('email-bad-focus');
const submitButton = document.getElementById('submit-bad');
let hasErrors = false;
// Hibák ellenőrzése
if (!nameField.value) {
document.getElementById('name-bad-error').textContent = 'Név kötelező';
document.getElementById('name-bad-error').style.display = 'block';
hasErrors = true;
}
if (!emailField.value) {
document.getElementById('email-bad-focus-error').textContent = 'E-mail kötelező';
document.getElementById('email-bad-focus-error').style.display = 'block';
hasErrors = true;
}
if (hasErrors) {
// HIBA: Fókusz a küldés gombon marad
submitButton.focus(); // Rossz! Nem segít a hibák megtalálásában
// HIBA: Nincs scroll a hibákhoz
// A felhasználó nem tudja, hol vannak a hibák
}
});
</script>
<!-- HIBÁS: Nincs hibák összesítő -->
<form id="no-summary-form">
<!-- Sok mező... -->
<div>
<label for="field1">Mező 1:</label>
<input id="field1" type="text" required>
</div>
<div>
<label for="field2">Mező 2:</label>
<input id="field2" type="text" required>
</div>
<div>
<label for="field3">Mező 3:</label>
<input id="field3" type="text" required>
</div>
<div>
<label for="field4">Mező 4:</label>
<input id="field4" type="text" required>
</div>
<div>
<label for="field5">Mező 5:</label>
<input id="field5" type="text" required>
</div>
<button type="submit">Küldés</button>
<!-- HIBA: Nincs hibák összesítő a tetején -->
<!-- Hosszú űrlapnál a felhasználó nem látja az összes hibát -->
</form>
Probléma: A billentyűzetes felhasználók és képernyőolvasó használók nehezen találják meg és javítják ki a hibákat, ha a fókusz nem a hibás mezőre kerül.
Források
Iratkozz fel hírlevelünkre!
Amennyiben szeretnél első kézből értesülni az új bejegyzésekről, iratkozz fel hírlevelünkre!