3.3.4 - Hibamegelőzés (jogi, pénzügyi, adat)
Röviden a szabványpontról
A WCAG 2.2 Success Criterion 3.3.4 (Error Prevention – Legal, Financial, Data) megköveteli, hogy azokon a weboldalakon, ahol a felhasználói műveletek jogi kötelezettségekhez, pénzügyi tranzakciókhoz, adatmódosításokhoz vagy felhasználói tesztek beküldéséhez vezethetnek, a következők közül legalább egynek igaznak kell lennie: a beküldés visszavonható (a felhasználók visszavonhatják a műveletet), a bevitt adatokat ellenőrzik beviteli hibák szempontjából és a felhasználók lehetőséget kapnak a javításra, vagy mechanizmust biztosítanak az információk áttekintésére, megerősítésére és javítására a végső beküldés előtt.
Cél: Megelőzni a súlyos hibákat, amelyek negatívan befolyásolhatják a felhasználókat azzal, hogy biztosítják számukra az irányítást és áttekinthetőséget a kritikus műveletek végrehajtása előtt. Ez elsősorban űrlapokra, pénztári folyamatokra, jogi megállapodásokra és adatbeviteli felületekre vonatkozik.
Mire vonatkozik: Minden olyan webes tartalomra, ahol a felhasználói műveletek komoly következményekkel járhatnak, beleértve a vásárlási folyamatokat, regisztrációs űrlapokat, adatmódosító funkciókat, pénzügyi tranzakciókat és jogi dokumentumok aláírását.
Kiket érint
Elsődleges felhasználók: Kognitív fogyatékossággal, gyengénlátással, mozgásszervi akadályozottsággal élő emberek, vagy bárki, aki hibázhat a komplexitás vagy stressz miatt. Ezek a felhasználók különösen profitálnak a megerősítési lépésekből és a hibajavítási lehetőségekből.
Másodlagos előnyök: Minden felhasználó számára előnyös a kevesebb hiba és a világosabb folyamatok, javítva az oldal általános használhatóságát és megbízhatóságát. Különösen értékes stresszes helyzetekben, mint például online vásárlás vagy fontos űrlapok kitöltése.
Tesztelés
- Űrlap folyamatok áttekintése: Ellenőrizd, hogy a kritikus űrlapok rendelkeznek-e megerősítési lépéssel vagy hibák áttekintésével a végső beküldés előtt
- Érvénytelen beküldések tesztelése: Írj be helytelen vagy hiányos adatokat és nézd meg, hogy a rendszer észleli-e a hibákat és lehetővé teszi-e a javítást
- Visszavonás funkció tesztelése: Visszavonható műveletek esetén (pl. adatok törlése) ellenőrizd, hogy a felhasználók könnyen vissza tudják-e vonni a műveletet
- Billentyűzetes és képernyőolvasó tesztelés: Biztosítsd, hogy a hibaüzenetek és áttekintési lépések hozzáférhetőek és világosan kommunikálnak
- Felhasználói teszt: Figyeld meg a felhasználókat tranzakciók vagy jogi űrlapok kitöltése közben, hogy azonosítsd, képesek-e könnyen javítani az esetlegesen felmerülő hibákat
Jó gyakorlatok
1. Megerősítő oldal a végső beküldés előtt
<!-- ONLINE VÁSÁRLÁS - Rendelés megerősítés -->
<form id="vasarlas-form" class="checkout-form" novalidate>
<div class="form-section">
<h2>Rendelési adatok</h2>
<div class="form-group">
<label for="szallitasi-nev">Szállítási név *</label>
<input
type="text"
id="szallitasi-nev"
name="szallitasi_nev"
required
aria-describedby="szallitasi-nev-error"
autocomplete="name"
>
<div id="szallitasi-nev-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="szallitasi-cim">Szállítási cím *</label>
<input
type="text"
id="szallitasi-cim"
name="szallitasi_cim"
required
aria-describedby="szallitasi-cim-error"
autocomplete="street-address"
>
<div id="szallitasi-cim-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="bankkartya-szam">Bankkártya szám *</label>
<input
type="text"
id="bankkartya-szam"
name="bankkartya_szam"
required
pattern="[0-9]{16}"
aria-describedby="bankkartya-szam-help bankkartya-szam-error"
autocomplete="cc-number"
>
<div id="bankkartya-szam-help" class="field-help">
16 számjegyű bankkártya szám szóközök nélkül
</div>
<div id="bankkartya-szam-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="bankkartya-lej">Lejárat (HH/ÉÉ) *</label>
<input
type="text"
id="bankkartya-lej"
name="bankkartya_lej"
required
pattern="[0-9]{2}/[0-9]{2}"
placeholder="12/25"
aria-describedby="bankkartya-lej-error"
autocomplete="cc-exp"
>
<div id="bankkartya-lej-error" class="error-message" role="alert" style="display: none;"></div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn-primary">Rendelés áttekintése</button>
</div>
</form>
<!-- MEGERŐSÍTŐ OLDAL -->
<div id="rendeles-megerosito" class="confirmation-page" style="display: none;">
<h2>Rendelés áttekintése</h2>
<p>Kérjük, ellenőrizze minden adatot a végleges rendelés leadása előtt.</p>
<div class="rendeles-osszegzo">
<h3>Szállítási adatok</h3>
<div class="adat-sor">
<strong>Név:</strong> <span id="confirm-nev"></span>
</div>
<div class="adat-sor">
<strong>Cím:</strong> <span id="confirm-cim"></span>
</div>
<h3>Fizetési adatok</h3>
<div class="adat-sor">
<strong>Kártya:</strong> <span id="confirm-kartya"></span>
</div>
<h3>Összeg</h3>
<div class="adat-sor vegosszeg">
<strong>Végösszeg:</strong> <span id="confirm-osszeg"></span>
</div>
</div>
<div class="confirmation-actions">
<button type="button" id="rendeles-szerkesztes" class="btn-secondary">
Adatok szerkesztése
</button>
<button type="button" id="rendeles-vegleges" class="btn-primary">
Rendelés véglegesítése
</button>
</div>
</div>
<!-- JAVASCRIPT A MEGERŐSÍTÉSHEZ -->
<script>
const vasarlasForm = document.getElementById('vasarlas-form');
const megerositoOldal = document.getElementById('rendeles-megerosito');
const szerkesztesGomb = document.getElementById('rendeles-szerkesztes');
const veglegesGomb = document.getElementById('rendeles-vegleges');
// Űrlap beküldés - megerősítő oldal megjelenítése
vasarlasForm.addEventListener('submit', function(esemeny) {
esemeny.preventDefault();
// Adatok validálása
if (validalasRendeles()) {
// Adatok betöltése a megerősítő oldalra
document.getElementById('confirm-nev').textContent =
document.getElementById('szallitasi-nev').value;
document.getElementById('confirm-cim').textContent =
document.getElementById('szallitasi-cim').value;
document.getElementById('confirm-kartya').textContent =
'****' + document.getElementById('bankkartya-szam').value.slice(-4);
document.getElementById('confirm-osszeg').textContent = '25.990 Ft';
// Oldal váltás
vasarlasForm.style.display = 'none';
megerositoOldal.style.display = 'block';
// Fókusz a megerősítő oldal címére
megerositoOldal.querySelector('h2').focus();
}
});
// Vissza az űrlaphoz
szerkesztesGomb.addEventListener('click', function() {
megerositoOldal.style.display = 'none';
vasarlasForm.style.display = 'block';
document.getElementById('szallitasi-nev').focus();
});
// Végleges rendelés
veglegesGomb.addEventListener('click', function() {
// Itt történik a tényleges rendelés beküldése
alert('Rendelés sikeresen leadva!');
// Átirányítás a köszönő oldalra
window.location.href = '/koszonjuk';
});
// Validáció függvény
function validalasRendeles() {
let ervenyesForm = true;
const szallitasiNev = document.getElementById('szallitasi-nev');
const szallitasiCim = document.getElementById('szallitasi-cim');
const bankkartya = document.getElementById('bankkartya-szam');
const lejarat = document.getElementById('bankkartya-lej');
// Név validálás
if (szallitasiNev.value.trim() === '') {
mutatHiba('szallitasi-nev-error', 'A szállítási név megadása kötelező.');
ervenyesForm = false;
} else {
rejtsHiba('szallitasi-nev-error');
}
// Cím validálás
if (szallitasiCim.value.trim() === '') {
mutatHiba('szallitasi-cim-error', 'A szállítási cím megadása kötelező.');
ervenyesForm = false;
} else {
rejtsHiba('szallitasi-cim-error');
}
// Bankkártya validálás
if (!/^[0-9]{16}$/.test(bankkartya.value.replace(/\s/g, ''))) {
mutatHiba('bankkartya-szam-error', 'Érvénytelen bankkártya szám. 16 számjegy szükséges.');
ervenyesForm = false;
} else {
rejtsHiba('bankkartya-szam-error');
}
// Lejárat validálás
if (!/^[0-9]{2}\/[0-9]{2}$/.test(lejarat.value)) {
mutatHiba('bankkartya-lej-error', 'Érvénytelen lejárat formátum. HH/ÉÉ formában adja meg.');
ervenyesForm = false;
} else {
rejtsHiba('bankkartya-lej-error');
}
return ervenyesForm;
}
function mutatHiba(hibaMezoId, hibaUzenet) {
const hibaMezo = document.getElementById(hibaMezoId);
hibaMezo.textContent = hibaUzenet;
hibaMezo.style.display = 'block';
hibaMezo.setAttribute('aria-live', 'assertive');
}
function rejtsHiba(hibaMezoId) {
const hibaMezo = document.getElementById(hibaMezoId);
hibaMezo.style.display = 'none';
hibaMezo.removeAttribute('aria-live');
}
</script>
2. Azonnali validálás és hibajavítási javaslatok
<!-- REGISZTRÁCIÓ - Azonnali validálással -->
<form id="reg-form" class="registration-form" novalidate>
<div class="form-section">
<h2>Új felhasználói fiók</h2>
<div class="form-group">
<label for="reg-email">E-mail cím *</label>
<input
type="email"
id="reg-email"
name="email"
required
aria-describedby="reg-email-help reg-email-error"
autocomplete="email"
>
<div id="reg-email-help" class="field-help">
Valós e-mail címét adja meg az aktiváláshoz
</div>
<div id="reg-email-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="reg-jelszo">Jelszó *</label>
<input
type="password"
id="reg-jelszo"
name="jelszo"
required
minlength="8"
aria-describedby="reg-jelszo-help reg-jelszo-error"
autocomplete="new-password"
>
<div id="reg-jelszo-help" class="field-help">
Legalább 8 karakter, tartalmazzon számot és nagybetűt
</div>
<div id="reg-jelszo-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label for="reg-jelszo-meg">Jelszó megerősítése *</label>
<input
type="password"
id="reg-jelszo-meg"
name="jelszo_megerosites"
required
aria-describedby="reg-jelszo-meg-error"
autocomplete="new-password"
>
<div id="reg-jelszo-meg-error" class="error-message" role="alert" style="display: none;"></div>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="reg-feltetel" name="feltetel" required>
Elfogadom a <a href="/feltetel" target="_blank">felhasználási feltételeket</a> *
</label>
<div id="reg-feltetel-error" class="error-message" role="alert" style="display: none;"></div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn-primary">Regisztráció</button>
</div>
</form>
<script>
const regForm = document.getElementById('reg-form');
const emailMezo = document.getElementById('reg-email');
const jelszоMezo = document.getElementById('reg-jelszo');
const jelszоMegMezo = document.getElementById('reg-jelszo-meg');
const feltetelMezo = document.getElementById('reg-feltetel');
// E-mail validálás gépelés közben
emailMezo.addEventListener('input', function() {
const emailErtek = this.value.trim();
const emailError = document.getElementById('reg-email-error');
if (emailErtek === '') {
rejtsHiba('reg-email-error');
} else if (!emailValidacio(emailErtek)) {
mutatHiba('reg-email-error', 'Kérjük, érvényes e-mail címet adjon meg (pl. nev@domain.hu).');
} else {
rejtsHiba('reg-email-error');
}
});
// Jelszó validálás
jelszоMezo.addEventListener('input', function() {
const jelszоErtek = this.value;
const jelszоError = document.getElementById('reg-jelszo-error');
if (jelszоErtek.length === 0) {
rejtsHiba('reg-jelszo-error');
} else if (jelszоErtek.length < 8) {
mutatHiba('reg-jelszo-error', 'A jelszó legalább 8 karakter legyen.');
} else if (!/[A-Z]/.test(jelszоErtek)) {
mutatHiba('reg-jelszo-error', 'A jelszó tartalmazzon legalább egy nagybetűt.');
} else if (!/[0-9]/.test(jelszоErtek)) {
mutatHiba('reg-jelszo-error', 'A jelszó tartalmazzon legalább egy számot.');
} else {
rejtsHiba('reg-jelszo-error');
}
// Jelszó megerősítés ellenőrzése ha van érték
if (jelszоMegMezo.value.length > 0) {
jelszоMegerositesValidacio();
}
});
// Jelszó megerősítés validálás
jelszоMegMezo.addEventListener('input', jelszоMegerositesValidacio);
function jelszоMegerositesValidacio() {
const jelszо = jelszоMezo.value;
const jelszоMeg = jelszоMegMezo.value;
const jelszоMegError = document.getElementById('reg-jelszo-meg-error');
if (jelszоMeg.length === 0) {
rejtsHiba('reg-jelszo-meg-error');
} else if (jelszо !== jelszоMeg) {
mutatHiba('reg-jelszo-meg-error', 'A két jelszó nem egyezik meg.');
} else {
rejtsHiba('reg-jelszo-meg-error');
}
}
// Űrlap beküldés validálása
regForm.addEventListener('submit', function(esemeny) {
esemeny.preventDefault();
if (teljesValidacio()) {
// Sikeres regisztráció
alert('Regisztráció sikeres! Aktiváló e-mail elküldve.');
// Itt történne a tényleges regisztráció
}
});
function teljesValidacio() {
let ervenyesForm = true;
// E-mail ellenőrzés
if (!emailValidacio(emailMezo.value.trim())) {
mutatHiba('reg-email-error', 'Érvényes e-mail cím megadása kötelező.');
ervenyesForm = false;
}
// Jelszó ellenőrzés
if (jelszоMezo.value.length < 8) {
mutatHiba('reg-jelszo-error', 'A jelszó legalább 8 karakter legyen.');
ervenyesForm = false;
}
// Jelszó megerősítés
if (jelszоMezo.value !== jelszоMegMezo.value) {
mutatHiba('reg-jelszo-meg-error', 'A két jelszó nem egyezik meg.');
ervenyesForm = false;
}
// Feltételek elfogadása
if (!feltetelMezo.checked) {
mutatHiba('reg-feltetel-error', 'A regisztrációhoz el kell fogadnia a felhasználási feltételeket.');
ervenyesForm = false;
}
return ervenyesForm;
}
function emailValidacio(email) {
const emailMinta = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailMinta.test(email);
}
function mutatHiba(hibaMezoId, hibaUzenet) {
const hibaMezo = document.getElementById(hibaMezoId);
hibaMezo.textContent = hibaUzenet;
hibaMezo.style.display = 'block';
hibaMezo.setAttribute('aria-live', 'assertive');
}
function rejtsHiba(hibaMezoId) {
const hibaMezo = document.getElementById(hibaMezoId);
hibaMezo.style.display = 'none';
hibaMezo.removeAttribute('aria-live');
}
</script>
3. Visszavonás opció kritikus műveleteknél
<!-- ADAT TÖRLÉS - Visszavonási lehetőséggel -->
<div class="felhasznalo-beallitasok">
<h2>Fiók beállítások</h2>
<div class="beallitas-csoport">
<h3>Fiók törlése</h3>
<p>Figyelem: Ez a művelet törli az összes adatát és beállítását.</p>
<button type="button" id="fiok-torles-gomb" class="btn-danger">
Fiók törlése
</button>
</div>
</div>
<!-- MEGERŐSÍTŐ DIALÓGUS -->
<div id="torles-megersito" class="modal" style="display: none;" role="dialog" aria-labelledby="torles-cim" aria-modal="true">
<div class="modal-content">
<h3 id="torles-cim">Fiók törlésének megerősítése</h3>
<p>Biztos, hogy törölni szeretné a fiókját? Ez a művelet nem vonható vissza!</p>
<p>Az összes adata, beleértve a beállításokat, üzeneteket és dokumentumokat, véglegesen törlődik.</p>
<div class="modal-actions">
<button type="button" id="torles-megse" class="btn-secondary">Mégse</button>
<button type="button" id="torles-megersites" class="btn-danger">Igen, törlöm a fiókot</button>
</div>
</div>
</div>
<!-- VISSZAVONÁSI ÜZENET -->
<div id="torles-visszavonasi" class="undo-message" style="display: none;" role="alert" aria-live="assertive">
<div class="undo-content">
<span>Fiók törlése elkezdődött. </span>
<button type="button" id="torles-visszavon" class="btn-primary">Visszavonás</button>
<span id="visszavon-ido" class="countdown">(30 másodperc)</span>
</div>
</div>
<script>
const fiokTorlesGomb = document.getElementById('fiok-torles-gomb');
const torlesMegersito = document.getElementById('torles-megersito');
const torlesMegse = document.getElementById('torles-megse');
const torlesMegersites = document.getElementById('torles-megersites');
const torlesVisszavonasi = document.getElementById('torles-visszavonasi');
const torlesVisszavon = document.getElementById('torles-visszavon');
const visszavonIdo = document.getElementById('visszavon-ido');
let torlesTimeout;
let visszavonTimeout;
let visszavonIdoHatra = 30;
// Törlés gomb megnyomása
fiokTorlesGomb.addEventListener('click', function() {
torlesMegersito.style.display = 'flex';
torlesMegersito.focus();
});
// Törlés mégse
torlesMegse.addEventListener('click', function() {
torlesMegersito.style.display = 'none';
fiokTorlesGomb.focus();
});
// Törlés megerősítése
torlesMegersites.addEventListener('click', function() {
torlesMegersito.style.display = 'none';
// Törlés folyamat indítása 30 másodperces visszavonással
inditsaTorlesVisszavonast();
});
// Törlés visszavonás indítása
function inditsaTorlesVisszavonast() {
// Visszavonási üzenet megjelenítése
torlesVisszavonasi.style.display = 'block';
torlesVisszavon.focus();
// Visszavonási időzítő indítása
visszavonTimeout = setInterval(function() {
visszavonIdoHatra--;
visszavonIdo.textContent = `(${visszavonIdoHatra} másodperc)`;
if (visszavonIdoHatra <= 0) {
// Idő lejárt, törlés véglegesítése
clearInterval(visszavonTimeout);
veglegesitesTorles();
}
}, 1000);
}
// Törlés visszavonása
torlesVisszavon.addEventListener('click', function() {
clearInterval(visszavonTimeout);
torlesVisszavonasi.style.display = 'none';
visszavonIdoHatra = 30;
visszavonIdo.textContent = '(30 másodperc)';
// Visszavonás megerősítése
alert('Fiók törlése megszakítva. Adatai biztonságban vannak.');
fiokTorlesGomb.focus();
});
// Törlés véglegesítése
function veglegesitesTorles() {
torlesVisszavonasi.style.display = 'none';
// Itt történne a tényleges törlés
alert('Fiók sikeresen törölve. Átirányítás a főoldalra...');
// Átirányítás
setTimeout(function() {
window.location.href = '/';
}, 2000);
}
// Dialógus bezárása ESC billentyűvel
document.addEventListener('keydown', function(esemeny) {
if (esemeny.key === 'Escape' && torlesMegersito.style.display === 'flex') {
torlesMegse.click();
}
});
</script>
Rossz gyakorlatok
Kerülendő megoldások:
- Hibaellenőrzés vagy megerősítés nélküli beküldés: Űrlapok beküldése a bevitelek validálása vagy fontos tranzakciók megerősítése nélkül
- Rejtett vagy homályos hibaüzenetek: Hibák, amelyek nem világosan magyarázottak vagy nem hozzáférhetőek a képernyőolvasók számára
- Visszavonás nélküli műveletek: Olyan műveletek, mint például egy adat azonnali és visszavonhatatlan törlése
- Automatikus űrlap beküldés: Űrlapok automatikus beküldése felhasználói áttekintés nélkül, különösen kritikus érzékeny adatok esetében (pl. banki adatok fizetésnél stb.)
- Félrevezető megerősítések: Olyan megerősítő üzenetek, amelyek nem tükrözik pontosan a végrehajtandó műveletet
Példa rossz gyakorlatra
<!-- ROSSZ GYAKORLAT - Validálás és megerősítés nélküli vásárlás -->
<form>
<input type="text" name="bankkartya" placeholder="Bankkártya szám">
<input type="text" name="nev" placeholder="Név">
<input type="text" name="cim" placeholder="Cím">
<button type="submit">Vásárlás most</button>
</form>
<!-- Nincs validálás, nincs megerősítés, nincsenek hibaüzenetek -->
<!-- ROSSZ GYAKORLAT - Azonnali törlés visszavonás nélkül -->
<button onclick="torlesAdat()" class="torles-gomb">
Összes adat törlése
</button>
<script>
function torlesAdat() {
// Azonnal törli az adatokat megerősítés nélkül
alert('Adatok törölve!');
// Nincs visszavonási lehetőség
}
</script>
<!-- ROSSZ GYAKORLAT - Automatikus form beküldés -->
<form>
<input type="text" name="email" onchange="this.form.submit()">
<input type="password" name="jelszo" onchange="this.form.submit()">
<!-- Automatikusan beküldi a formot változás esetén -->
</form>
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!