3.2.2 - A bemenet megadása

Röviden a szabványpontról

A WCAG 2.2 Success Criterion 3.2.2 (On Input) előírja, hogy amikor egy felhasználó egy felhasználói felület komponenssel lép kapcsolatba, amely megváltoztatja a tartalom kontextusát (például űrlap beküldése vagy opció kiválasztása), a változás csak azután következhet be, hogy a felhasználó befejezte a bevitelt és kifejezetten jelezte, hogy készen van. Ez azt jelenti, hogy a változások nem történhetnek meg automatikusan minden beviteli változásnál, például billentyűleütésnél vagy kiválasztás megváltoztatásánál, kivéve, ha a változás visszafordítható vagy a felhasználót előre figyelmeztetik.

Cél: Megelőzni a váratlan változásokat, amelyek összezavarhatják vagy megtévesztik a felhasználókat, különösen azokat, akik kisegítő technológiákat, vagy billentyűzetes navigációt használnak, azáltal, hogy biztosítjuk, hogy a felhasználók kontrollja alatt álljon az hogy, mikor történnek meg a változások.

Mire vonatkozik: Minden olyan felhasználói felület komponensre, amely a felhasználói interakció hatására kontextus változást okozhat, beleértve az űrlapokat, legördülő menüket, csúszkákat, és egyéb interaktív elemeket.

Kiket érint

Elsődleges felhasználók: Kognitív fogyatékossággal, motoros károsodással élő emberek, vagy azok, akik kisegítő technológiákat használnak, mint például képernyőolvasók és kizárólag billentyűzetes navigáció. Ezek a felhasználók nehezen boldogulnak a váratlan változásokkal, amelyek túl gyorsan, vagy világos felhasználói szándék nélkül történnek.

Másodlagos előnyök: Minden felhasználónak előnyös a véletlen változások megelőzése, és ezzel frusztráció csökkentése, valamint a felület kiszámíthatóságának és kontrolljának javítása révén.

Tesztelés

  1. Kizárólag billentyűzetes tesztelés: Navigálj a felületen csak a billentyűzet használatával és ellenőrizd, hogy a változások nem történnek meg automatikusan részleges bevitelnél, hanem csak a kifejezett műveletek után, mint például az Enter megnyomása vagy egy gomb kattintása
  2. Képernyőolvasó tesztelés: Használj képernyőolvasót az űrlap vezérlőkkel vagy widgetekkel való interakcióhoz és erősítsd meg, hogy a kontextus változások (mint oldal frissítések vagy tartalom újratöltések) csak felhasználói megerősítés után történnek
  3. Manuális beviteli tesztelés: Legördülő menük és csúszkák esetén ellenőrizd, hogy a felület csak akkor hajt-e végre változást, miután a felhasználó befejezte a bevitelt vagy kiválasztást.
  4. Automatizált tesztelő eszközök: Használj eszközöket, mint az axe DevTools a beviteli eseményekre váratlanul kiváltódó kontextus változásokkal kapcsolatos problémák észlelésére
  5. Felhasználói tesztelés kisegítő technológia felhasználókkal: Figyelj meg valós fogyatékossággal élő felhasználókat, hogy megbizonyosodj arról, hogy a felület kiszámíthatóan viselkedik és változások csak kifejezett felhasználói bevitel után történnek.

Jó gyakorlatok

1. Küldés gombok létrehozása az űrlapokhoz

<form>
  <label for="email">E-mail cím:</label>
  <input id="email" type="email" name="email" placeholder="pelda@email.hu">
  
  <label for="nev">Teljes név:</label>
  <input id="nev" type="text" name="nev" placeholder="Kovács János">
  
  <label for="uzenet">Üzenet:</label>
  <textarea id="uzenet" name="uzenet" placeholder="Írja ide üzenetét..."></textarea>
  
  <!-- Csak felhasználói kattintás után küldi el -->
  <button type="submit">Üzenet küldése</button>
</form>

<script>
// Helyes: várakozás a felhasználó kifejezett küldési szándékára
document.querySelector('form').addEventListener('submit', function(e) {
  e.preventDefault();
  
  // Validálás és megerősítés
  const email = document.getElementById('email').value;
  const nev = document.getElementById('nev').value;
  
  if (!email || !nev) {
    alert('Kérjük, töltse ki az összes kötelező mezőt.');
    return;
  }
  
  // Küldje el az űrlapot csak megerősítés után
  if (confirm('Biztosan elküldi az üzenetet?')) {
    console.log('Üzenet elküldve!');
    // Itt történne a tényleges küldés
  }
});
</script>

Magyarázat: Az űrlap csak akkor kerül elküldésre, amikor a felhasználó kifejezetten a „Küldés” gombra kattint, nem pedig a változást követően azonnal.

2. Legördülő menük megerősítő gombokkal

<div class="beallitas-panel">
  <label for="nyelv">Válasszon nyelvet:</label>
  <select id="nyelv" name="nyelv" aria-describedby="nyelv-info">
    <option value="hu">Magyar</option>
    <option value="en">English</option>
    <option value="de">Deutsch</option>
    <option value="fr">Français</option>
  </select>
  
  <div id="nyelv-info" class="info-szoveg">
    A nyelv megváltoztatásához válasszon egy opciót, majd kattintson az Alkalmazás gombra.
  </div>
  
  <button type="button" onclick="nyelvBeallitas()" class="alkalmazas-gomb">
    Nyelv alkalmazása
  </button>
  
  <button type="button" onclick="visszavonas()" class="visszavonas-gomb">
    Mégse
  </button>
</div>

<div class="termek-szuro">
  <label for="kategoria">Termék kategória:</label>
  <select id="kategoria" name="kategoria" aria-describedby="kategoria-info">
    <option value="">Minden kategória</option>
    <option value="elektronika">Elektronika</option>
    <option value="ruhazkodas">Ruházat</option>
    <option value="otthon">Otthon és kert</option>
    <option value="sport">Sport és szabadidő</option>
  </select>
  
  <label for="ar-tartomany">Ár tartomány:</label>
  <select id="ar-tartomany" name="ar-tartomany">
    <option value="">Bármely ár</option>
    <option value="0-10000">0 - 10.000 Ft</option>
    <option value="10000-50000">10.000 - 50.000 Ft</option>
    <option value="50000+">50.000 Ft felett</option>
  </select>
  
  <div id="kategoria-info" class="info-szoveg">
    A szűrők alkalmazásához kattintson a "Szűrés" gombra.
  </div>
  
  <button type="button" onclick="szuresAlkalmazasa()" class="szures-gomb">
    Termékek szűrése
  </button>
</div>

<script>
function nyelvBeallitas() {
  const valasztottNyelv = document.getElementById('nyelv').value;
  
  // Megerősítés kérése
  if (confirm(`Biztosan megváltoztatja a nyelvet erre: ${getNyelvNev(valasztottNyelv)}? Az oldal újra fog töltődni.`)) {
    // Nyelv beállítása
    localStorage.setItem('nyelv', valasztottNyelv);
    
    // Felhasználó tájékoztatása
    alert('Nyelv beállítva! Az oldal újra töltődik...');
    
    // Oldal újratöltése
    window.location.reload();
  }
}

function getNyelvNev(kod) {
  const nyelvek = {
    'hu': 'Magyar',
    'en': 'English', 
    'de': 'Deutsch',
    'fr': 'Français'
  };
  return nyelvek[kod] || kod;
}

function visszavonas() {
  // Eredeti érték visszaállítása
  const eredetiNyelv = localStorage.getItem('nyelv') || 'hu';
  document.getElementById('nyelv').value = eredetiNyelv;
  
  alert('Változtatások visszavonva.');
}

function szuresAlkalmazasa() {
  const kategoria = document.getElementById('kategoria').value;
  const arTartomany = document.getElementById('ar-tartomany').value;
  
  // Szűrési paraméterek összeállítása
  let szuroFeltetelek = [];
  if (kategoria) szuroFeltetelek.push(`Kategória: ${kategoria}`);
  if (arTartomany) szuroFeltetelek.push(`Ár: ${arTartomany} Ft`);
  
  if (szuroFeltetelek.length === 0) {
    alert('Minden termék megjelenítése.');
  } else {
    alert(`Szűrés alkalmazva: ${szuroFeltetelek.join(', ')}`);
  }
  
  // Itt történne a tényleges szűrés
  console.log('Szűrési feltételek:', {kategoria, arTartomany});
}

// Billentyűzet támogatás
document.addEventListener('keydown', function(e) {
  if (e.key === 'Enter') {
    const aktiv = document.activeElement;
    
    // Ha select elemben vagyunk, ne alkalmazzuk automatikusan
    if (aktiv.tagName === 'SELECT') {
      e.preventDefault();
      
      // Megfelelő alkalmazás gomb keresése
      const szuloDiv = aktiv.closest('.beallitas-panel, .termek-szuro');
      if (szuloDiv) {
        const alkalmazasGomb = szuloDiv.querySelector('.alkalmazas-gomb, .szures-gomb');
        if (alkalmazasGomb) {
          alkalmazasGomb.focus();
        }
      }
    }
  }
});
</script>

<style>
.beallitas-panel, .termek-szuro {
  border: 1px solid #ccc;
  padding: 1rem;
  margin: 1rem 0;
  border-radius: 4px;
  background: #f9f9f9;
}

.info-szoveg {
  font-size: 0.9em;
  color: #666;
  margin: 0.5rem 0;
  font-style: italic;
}

.alkalmazas-gomb, .szures-gomb {
  background: #007bff;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 0.5rem;
}

.visszavonas-gomb {
  background: #6c757d;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
}

.alkalmazas-gomb:hover, .szures-gomb:hover {
  background: #0056b3;
}

.visszavonas-gomb:hover {
  background: #545b62;
}

select, button {
  margin: 0.25rem;
  padding: 0.5rem;
}

label {
  display: block;
  margin-top: 0.5rem;
  font-weight: bold;
}
</style>

Magyarázat: A legördülő menük kiválasztása nem okoz azonnali változást; a felhasználónak kifejezetten meg kell nyomnia az „Alkalmazás” gombot a változtatások érvényesítéséhez.

3. Csúszkák és tartomány bevitelek kontrollált frissítéssel

<div class="hangeroszabo">
  <label for="hangeroszabo-csuska">Hangerő beállítása:</label>
  <div class="csuska-container">
    <span class="hangeroszint">0</span>
    <input 
      id="hangeroszabo-csuska" 
      type="range" 
      min="0" 
      max="100" 
      value="50"
      aria-describedby="hangeroszint-info"
      oninput="hangerosegElonezet(this.value)"
      onchange="hangerosegBeallitas(this.value)"
    >
    <span class="hangeroszint">100</span>
  </div>
  
  <div id="hangeroszint-info" class="aktualis-ertek">
    Jelenlegi hangerő: <span id="jelenlegi-hangeroszint">50</span>%
  </div>
  
  <div class="csuska-info">
    A hangerő változtatása csak a csúszka elengedése után lép érvénybe.
  </div>
</div>

<div class="ar-szuro">
  <label for="ar-csuska">Maximális ár szűrő:</label>
  <div class="csuska-container">
    <span class="ar-cimke">0 Ft</span>
    <input 
      id="ar-csuska" 
      type="range" 
      min="0" 
      max="500000" 
      step="10000"
      value="100000"
      aria-describedby="ar-info"
      oninput="arElonezet(this.value)"
      onchange="arSzuresBeallitas(this.value)"
    >
    <span class="ar-cimke">500.000 Ft</span>
  </div>
  
  <div id="ar-info" class="aktualis-ertek">
    Kiválasztott maximális ár: <span id="jelenlegi-ar">100.000</span> Ft
  </div>
  
  <div class="csuska-info">
    A termékek szűrése csak a csúszka elengedése után történik meg.
  </div>
  
  <button type="button" onclick="arSzuresAlkalmazas()" class="szures-alkalmazas">
    Ár szűrő alkalmazása
  </button>
</div>

<div class="kepernyo-fenyesseg">
  <label for="fenyesseg-csuska">Képernyő fényerő:</label>
  <div class="csuska-container">
    <span class="fenyesseg-ikon">🔅</span>
    <input 
      id="fenyesseg-csuska" 
      type="range" 
      min="10" 
      max="100" 
      value="75"
      aria-describedby="fenyesseg-info"
      oninput="fenyessegElonezet(this.value)"
      onchange="fenyessegBeallitas(this.value)"
    >
    <span class="fenyesseg-ikon">🔆</span>
  </div>
  
  <div id="fenyesseg-info" class="aktualis-ertek">
    Jelenlegi fényerő: <span id="jelenlegi-fenyesseg">75</span>%
  </div>
  
  <div class="visszavonas-opcio">
    <button type="button" onclick="fenyessegVisszavonas()" class="visszavonas">
      Eredeti fényerő visszaállítása
    </button>
  </div>
</div>

<script>
let eredetiHangeroszint = 50;
let eredetiAr = 100000;
let eredetiFenyesseg = 75;
let ideiglenesFenyesseg = 75;

// Hangerő előnézet (nem alkalmazza véglegesen)
function hangerosegElonezet(ertek) {
  document.getElementById('jelenlegi-hangeroszint').textContent = ertek;
  
  // Vizuális visszajelzés, hogy ez csak előnézet
  const info = document.getElementById('hangeroszint-info');
  info.style.fontStyle = 'italic';
  info.style.color = '#666';
}

// Hangerő végleges beállítása (csak onchange eseménynél)
function hangerosegBeallitas(ertek) {
  console.log(`Hangerő beállítva: ${ertek}%`);
  
  // Visszajelzés, hogy a változás véglegesen alkalmazva lett
  const info = document.getElementById('hangeroszint-info');
  info.style.fontStyle = 'normal';
  info.style.color = '#000';
  
  // Megerősítő üzenet
  announceChange(`Hangerő beállítva ${ertek} százalékra`);
}

// Ár előnézet
function arElonezet(ertek) {
  document.getElementById('jelenlegi-ar').textContent = Number(ertek).toLocaleString('hu-HU');
  
  const info = document.getElementById('ar-info');
  info.style.fontStyle = 'italic';
  info.style.color = '#666';
}

// Ár szűrés beállítása
function arSzuresBeallitas(ertek) {
  console.log(`Ár szűrő előkészítve: ${ertek} Ft`);
  
  const info = document.getElementById('ar-info');
  info.style.fontStyle = 'normal';
  info.style.color = '#000';
}

// Ár szűrő alkalmazása gombbal
function arSzuresAlkalmazas() {
  const ertek = document.getElementById('ar-csuska').value;
  console.log(`Ár szűrő alkalmazva: ${ertek} Ft`);
  
  announceChange(`Termékek szűrve ${Number(ertek).toLocaleString('hu-HU')} forint maximum árral`);
}

// Fényerő előnézet
function fenyessegElonezet(ertek) {
  ideiglenesFenyesseg = ertek;
  document.getElementById('jelenlegi-fenyesseg').textContent = ertek;
  
  // Vizuális előnézet alkalmazása
  document.body.style.filter = `brightness(${ertek}%)`;
  
  const info = document.getElementById('fenyesseg-info');
  info.style.fontStyle = 'italic';
  info.style.color = '#666';
}

// Fényerő végleges beállítása
function fenyessegBeallitas(ertek) {
  eredetiFenyesseg = ertek;
  console.log(`Fényerő véglegesen beállítva: ${ertek}%`);
  
  const info = document.getElementById('fenyesseg-info');
  info.style.fontStyle = 'normal';
  info.style.color = '#000';
  
  announceChange(`Képernyő fényerő beállítva ${ertek} százalékra`);
}

// Fényerő visszavonása
function fenyessegVisszavonas() {
  document.getElementById('fenyesseg-csuska').value = eredetiFenyesseg;
  document.getElementById('jelenlegi-fenyesseg').textContent = eredetiFenyesseg;
  document.body.style.filter = `brightness(${eredetiFenyesseg}%)`;
  
  announceChange(`Fényerő visszaállítva az eredeti ${eredetiFenyesseg} százalékra`);
}

// Képernyőolvasó értesítése változásokról
function announceChange(uzenet) {
  const announcement = document.createElement('div');
  announcement.setAttribute('role', 'status');
  announcement.setAttribute('aria-live', 'polite');
  announcement.className = 'sr-only';
  announcement.textContent = uzenet;
  document.body.appendChild(announcement);
  
  setTimeout(() => {
    if (announcement.parentNode) {
      document.body.removeChild(announcement);
    }
  }, 1000);
}

// Billentyűzet támogatás csúszkákhoz
document.addEventListener('keydown', function(e) {
  const aktiv = document.activeElement;
  
  if (aktiv.type === 'range') {
    // Arrow keys használatához ne legyen automatikus frissítés
    if (e.key === 'ArrowLeft' || e.key === 'ArrowRight' || 
        e.key === 'ArrowUp' || e.key === 'ArrowDown') {
      
      // Csak értékfrissítés, nem végleges alkalmazás
      setTimeout(() => {
        const event = new Event('input');
        aktiv.dispatchEvent(event);
      }, 0);
    }
    
    // Enter vagy Space lenyomására véglegesítés
    if (e.key === 'Enter' || e.key === ' ') {
      const event = new Event('change');
      aktiv.dispatchEvent(event);
    }
  }
});
</script>

<style>
.hangeroszabo, .ar-szuro, .kepernyo-fenyesseg {
  border: 1px solid #ddd;
  padding: 1.5rem;
  margin: 1rem 0;
  border-radius: 8px;
  background: #f8f9fa;
}

.csuska-container {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 1rem 0;
}

.csuska-container input[type="range"] {
  flex: 1;
  height: 6px;
  background: #ddd;
  border-radius: 3px;
  outline: none;
}

.csuska-container input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  background: #007bff;
  border-radius: 50%;
  cursor: pointer;
}

.csuska-container input[type="range"]::-moz-range-thumb {
  width: 20px;
  height: 20px;
  background: #007bff;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}

.csuska-container input[type="range"]:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

.aktualis-ertek {
  font-size: 1.1em;
  font-weight: bold;
  margin: 0.5rem 0;
}

.csuska-info {
  font-size: 0.9em;
  color: #666;
  margin-top: 0.5rem;
  font-style: italic;
}

.szures-alkalmazas, .visszavonas {
  background: #28a745;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
  margin-top: 0.5rem;
}

.visszavonas {
  background: #6c757d;
}

.szures-alkalmazas:hover {
  background: #218838;
}

.visszavonas:hover {
  background: #545b62;
}

.hangeroszint, .ar-cimke {
  font-size: 0.9em;
  color: #666;
  min-width: 60px;
  text-align: center;
}

.fenyesseg-ikon {
  font-size: 1.2em;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
</style>

Magyarázat: A csúszkák mozgatása során csak előnézeti változtatásokat mutatunk, a végleges beállítás csak akkor történik meg, amikor a felhasználó befejezi a mozgatást (onchange esemény).

4. Visszavonás és megerősítés opciók biztosítása

<div class="beallitasok-panel">
  <h2>Profil beállítások</h2>
  
  <div class="beallitas-csoport">
    <label for="ertesitesek">E-mail értesítések:</label>
    <select id="ertesitesek" name="ertesitesek" onchange="ertesitesValtozas(this)">
      <option value="mind">Minden értesítés</option>
      <option value="fontos">Csak fontos értesítések</option>
      <option value="nincs">Nincs értesítés</option>
    </select>
  </div>
  
  <div class="beallitas-csoport">
    <label for="tema">Weboldal témája:</label>
    <select id="tema" name="tema" onchange="temaValtozas(this)">
      <option value="vilagos">Világos téma</option>
      <option value="sotet">Sötét téma</option>
      <option value="automatikus">Automatikus</option>
    </select>
  </div>
  
  <div class="beallitas-csoport">
    <label for="nyelv">Felület nyelve:</label>
    <select id="nyelv" name="nyelv" onchange="nyelvValtozas(this)">
      <option value="hu">Magyar</option>
      <option value="en">English</option>
      <option value="de">Deutsch</option>
    </select>
  </div>
  
  <!-- Visszavonás sáv -->
  <div id="visszavonas-sav" class="visszavonas-sav elrejtett" role="alert" aria-live="polite">
    <span class="visszavonas-uzenet"></span>
    <div class="visszavonas-gombok">
      <button type="button" onclick="valtozasVisszavonas()" class="visszavon-gomb">
        Visszavonás
      </button>
      <button type="button" onclick="valtozasElfogadas()" class="elfogad-gomb">
        Elfogadás
      </button>
    </div>
    
    <div class="visszavonas-idozito">
      <span class="idozito-szoveg">Automatikus elfogadás: <span id="idozito">10</span> másodperc</span>
      <div class="progress-bar">
        <div id="progress" class="progress-fill"></div>
      </div>
    </div>
  </div>
</div>

<script>
let aktualisValtozas = null;
let visszavonasIdozito = null;
let progressIdozito = null;
let eredetiBeallitasok = {
  ertesitesek: 'mind',
  tema: 'vilagos',
  nyelv: 'hu'
};

function ertesitesValtozas(select) {
  beallitasValtozas('ertesitesek', select.value, 'E-mail értesítések');
}

function temaValtozas(select) {
  beallitasValtozas('tema', select.value, 'Weboldal témája');
  
  // Téma előnézet alkalmazása
  alkalmazTemaElonezet(select.value);
}

function nyelvValtozas(select) {
  beallitasValtozas('nyelv', select.value, 'Felület nyelve');
}

function beallitasValtozas(beallitasTipus, ujErtek, beallitasNev) {
  const regiErtek = eredetiBeallitasok[beallitasTipus];
  
  if (ujErtek === regiErtek) return; // Nincs változás
  
  // Aktuális változás tárolása
  aktualisValtozas = {
    tipus: beallitasTipus,
    regiErtek: regiErtek,
    ujErtek: ujErtek,
    nev: beallitasNev
  };
  
  // Visszavonás sáv megjelenítése
  mutatVisszavonasSav();
  
  // 10 másodperces időzítő indítása
  inditsaIdozitot();
}

function mutatVisszavonasSav() {
  const sav = document.getElementById('visszavonas-sav');
  const uzenet = document.querySelector('.visszavonas-uzenet');
  
  uzenet.textContent = `${aktualisValtozas.nev} megváltoztatva erre: "${getBeallitasNev(aktualisValtozas.tipus, aktualisValtozas.ujErtek)}"`;
  
  sav.classList.remove('elrejtett');
  sav.scrollIntoView({behavior: 'smooth'});
}

function getBeallitasNev(tipus, ertek) {
  const nevMap = {
    ertesitesek: {
      'mind': 'Minden értesítés',
      'fontos': 'Csak fontos értesítések', 
      'nincs': 'Nincs értesítés'
    },
    tema: {
      'vilagos': 'Világos téma',
      'sotet': 'Sötét téma',
      'automatikus': 'Automatikus'
    },
    nyelv: {
      'hu': 'Magyar',
      'en': 'English',
      'de': 'Deutsch'
    }
  };
  
  return nevMap[tipus][ertek] || ertek;
}

function inditsaIdozitot() {
  let maradekIdo = 10;
  const idozitoSpan = document.getElementById('idozito');
  const progress = document.getElementById('progress');
  
  // Korábbi időzítők törlése
  if (visszavonasIdozito) clearTimeout(visszavonasIdozito);
  if (progressIdozito) clearInterval(progressIdozito);
  
  // Progress bar frissítése
  progressIdozito = setInterval(() => {
    maradekIdo--;
    idozitoSpan.textContent = maradekIdo;
    progress.style.width = `${((10 - maradekIdo) / 10) * 100}%`;
    
    if (maradekIdo <= 0) {
      clearInterval(progressIdozito);
    }
  }, 1000);
  
  // Automatikus elfogadás
  visszavonasIdozito = setTimeout(() => {
    valtozasElfogadas();
  }, 10000);
}

function valtozasVisszavonas() {
  if (!aktualisValtozas) return;
  
  // Eredeti érték visszaállítása
  const select = document.getElementById(aktualisValtozas.tipus);
  select.value = aktualisValtozas.regiErtek;
  
  // Téma esetén vizuális visszaállítás
  if (aktualisValtozas.tipus === 'tema') {
    alkalmazTemaElonezet(aktualisValtozas.regiErtek);
  }
  
  // Visszavonás sáv elrejtése
  elrejtiVisszavonasSav();
  
  // Képernyőolvasó értesítése
  announceChange(`${aktualisValtozas.nev} visszavonva. Eredeti beállítás: ${getBeallitasNev(aktualisValtozas.tipus, aktualisValtozas.regiErtek)}`);
  
  aktualisValtozas = null;
}

function valtozasElfogadas() {
  if (!aktualisValtozas) return;
  
  // Új érték mentése
  eredetiBeallitasok[aktualisValtozas.tipus] = aktualisValtozas.ujErtek;
  
  // Speciális kezelés nyelv változásnál
  if (aktualisValtozas.tipus === 'nyelv') {
    localStorage.setItem('nyelv', aktualisValtozas.ujErtek);
  }
  
  // Visszavonás sáv elrejtése
  elrejtiVisszavonasSav();
  
  // Képernyőolvasó értesítése
  announceChange(`${aktualisValtozas.nev} elfogadva: ${getBeallitasNev(aktualisValtozas.tipus, aktualisValtozas.ujErtek)}`);
  
  aktualisValtozas = null;
}

function elrejtiVisszavonasSav() {
  const sav = document.getElementById('visszavonas-sav');
  sav.classList.add('elrejtett');
  
  // Időzítők törlése
  if (visszavonasIdozito) {
    clearTimeout(visszavonasIdozito);
    visszavonasIdozito = null;
  }
  if (progressIdozito) {
    clearInterval(progressIdozito);
    progressIdozito = null;
  }
  
  // Progress bar visszaállítása
  document.getElementById('progress').style.width = '0%';
  document.getElementById('idozito').textContent = '10';
}

function alkalmazTemaElonezet(tema) {
  const body = document.body;
  
  // Témák eltávolítása
  body.classList.remove('vilagos-tema', 'sotet-tema', 'automatikus-tema');
  
  // Új téma alkalmazása
  if (tema === 'sotet') {
    body.classList.add('sotet-tema');
  } else if (tema === 'automatikus') {
    body.classList.add('automatikus-tema');
  } else {
    body.classList.add('vilagos-tema');
  }
}

function announceChange(uzenet) {
  const announcement = document.createElement('div');
  announcement.setAttribute('role', 'status');
  announcement.setAttribute('aria-live', 'polite');
  announcement.className = 'sr-only';
  announcement.textContent = uzenet;
  document.body.appendChild(announcement);
  
  setTimeout(() => {
    if (announcement.parentNode) {
      document.body.removeChild(announcement);
    }
  }, 1000);
}

// Oldal betöltésekor eredeti téma beállítása
document.addEventListener('DOMContentLoaded', function() {
  alkalmazTemaElonezet(eredetiBeallitasok.tema);
});
</script>

<style>
.beallitasok-panel {
  max-width: 600px;
  margin: 2rem auto;
  padding: 2rem;
  border: 1px solid #ddd;
  border-radius: 8px;
  background: white;
}

.beallitas-csoport {
  margin: 1.5rem 0;
}

.beallitas-csoport label {
  display: block;
  font-weight: bold;
  margin-bottom: 0.5rem;
}

.beallitas-csoport select {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 1rem;
}

.visszavonas-sav {
  background: #fff3cd;
  border: 1px solid #ffeaa7;
  border-radius: 4px;
  padding: 1rem;
  margin-top: 1rem;
  transition: all 0.3s ease;
}

.visszavonas-sav.elrejtett {
  display: none;
}

.visszavonas-uzenet {
  display: block;
  font-weight: bold;
  margin-bottom: 1rem;
}

.visszavonas-gombok {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.visszavon-gomb {
  background: #dc3545;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
}

.elfogad-gomb {
  background: #28a745;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
}

.visszavon-gomb:hover {
  background: #c82333;
}

.elfogad-gomb:hover {
  background: #218838;
}

.visszavonas-idozito {
  font-size: 0.9em;
  color: #666;
}

.progress-bar {
  width: 100%;
  height: 6px;
  background: #e9ecef;
  border-radius: 3px;
  margin-top: 0.5rem;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: #007bff;
  width: 0%;
  transition: width 1s linear;
}

/* Témák */
.vilagos-tema {
  background: white;
  color: black;
}

.sotet-tema {
  background: #333;
  color: white;
}

.sotet-tema .beallitasok-panel {
  background: #444;
  border-color: #666;
  color: white;
}

.sotet-tema .beallitas-csoport select {
  background: #555;
  color: white;
  border-color: #666;
}

.automatikus-tema {
  background: linear-gradient(to right, #f8f9fa, #e9ecef);
  color: #333;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
</style>

Magyarázat: Azonnali változtatások esetén biztosítjuk a visszavonás lehetőségét és időt adunk a felhasználónak a módosítások átgondolására.

Helytelen megoldások

Automatikus űrlap beküldés minden beviteli változásnál

<form oninput="this.submit()">
  <input type="text" name="kereses" placeholder="Keresés...">
</form>

<!-- Másik hibás példa -->
<form>
  <input type="text" name="felhasznalonev" onkeyup="validateAndSubmit()">
  <input type="password" name="jelszo" onkeyup="validateAndSubmit()">
</form>

Probléma: Az űrlap minden billentyűleütéskor elküldi magát, ami megzavarja a még gépelő felhasználókat és túlterheli a képernyőolvasókat.

Legördülő menük azonnali oldal frissítéssel

<select onchange="window.location.href=this.value;">
  <option value="fooldal.html">Főoldal</option>
  <option value="rolunk.html">Rólunk</option>
  <option value="kapcsolat.html">Kapcsolat</option>
</select>

<!-- Másik hibás példa -->
<select onchange="document.location = this.options[this.selectedIndex].value;">
  <option value="">Válasszon kategóriát</option>
  <option value="?kategoria=elektronika">Elektronika</option>
  <option value="?kategoria=ruhazat">Ruházat</option>
</select>

Probléma: Az oldal azonnal frissül a egy menüpont kiválasztáskor, ami összezavarja a csak billentyűzetet használó és képernyőolvasó felhasználókat, akik esetleg csak böngésznek az opciók között.

Csúszkák folyamatos frissítéssel

<input type="range" min="0" max="100" oninput="updateSettings(this.value)">

<script>
function updateSettings(value) {
  // Hibás: minden apró mozdulatnál frissít
  fetch('/api/settings', {
    method: 'POST',
    body: JSON.stringify({volume: value})
  });
  
  // Az oldal tartalma is változik minden mozdulatnál
  document.getElementById('volume-display').innerHTML = 
    `<h2>Jelenlegi hangerő: ${value}</h2>`;
}
</script>

Probléma: A csúszka minden apró mozgatásánál frissítéseket küld, ami túlterheli mind a szervert, mind a kisegítő technológiákat használó felhasználókat.

Váratlan kontextus változások figyelmeztetés nélkül

<!-- Hibás: automatikus átirányítás időzítéssel -->
<script>
// Figyelmeztetés nélküli átirányítás 3 másodperc után
setTimeout(function() {
  window.location.href = 'uj-oldal.html';
}, 3000);
</script>

<!-- Hibás: popupok jelennek meg input változáskor -->
<input type="email" oninput="showEmailSuggestions()">

<script>
function showEmailSuggestions() {
  // Hibás: popup minden karakternél
  if (event.target.value.length > 2) {
    window.open('email-suggestions.html', '_blank');
  }
}
</script>

Probléma: A felhasználók nincsenek felkészítve a váratlan kontextus változásokra, ami megtévesztő és zavaró lehet.

Hibás időzítések és automatikus műveletek

<!-- Hibás: túl gyors automatikus mentés -->
<textarea oninput="autoSave()"></textarea>

<script>
function autoSave() {
  // Hibás: minden karakternél ment
  fetch('/api/save', {
    method: 'POST',
    body: JSON.stringify({content: event.target.value})
  }).then(() => {
    // Hibás: zavaró értesítés minden mentésnél
    alert('Automatikusan elmentve!');
  });
}

// Hibás: túl agresszív keresés
let searchInput = document.getElementById('search');
searchInput.addEventListener('input', function() {
  // Hibás: azonnal keres minden karakternél
  performSearch(this.value);
});

function performSearch(query) {
  if (query.length > 0) {
    // Hibás: oldal tartalom azonnal változik
    document.getElementById('results').innerHTML = 'Keresés folyamatban...';
    
    fetch(`/search?q=${query}`)
      .then(response => response.json())
      .then(data => {
        // Hibás: eredmények villognak minden karakternél
        document.getElementById('results').innerHTML = data.html;
      });
  }
}
</script>

Probléma: A túl gyakori automatikus műveletek zavarják a felhasználói élményt és túlterhelik a kisegítő technológiákat.

Rossz hibakezelés beviteli események során

<form>
  <input type="text" name="felhasznalo" oninput="validateUser(this.value)">
  <input type="password" name="jelszo" oninput="validatePassword(this.value)">
</form>

<script>
function validateUser(value) {
  if (value.length < 3) {
    // Hibás: azonnali hibaüzenet gépelés közben
    alert('A felhasználónév túl rövid!');
    return;
  }
  
  // Hibás: API hívás minden karakternél
  fetch(`/api/check-user/${value}`)
    .then(response => {
      if (!response.ok) {
        // Hibás: hibaüzenet minden elírás esetén
        alert('Ez a felhasználónév már foglalt!');
      }
    });
}

function validatePassword(value) {
  // Hibás: folyamatos popup figyelmeztetések
  if (!/[A-Z]/.test(value)) {
    alert('Tartalmaznia kell nagybetűt!');
  }
  if (!/[0-9]/.test(value)) {
    alert('Tartalmaznia kell számot!');
  }
  if (value.length < 8) {
    alert('Legalább 8 karakter hosszú legyen!');
  }
}
</script>

Probléma: A folyamatos validáció és hibaüzenetek megzavarják a felhasználókat gépelés közben, nem adnak lehetőséget a bevitel befejezésére.

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!

Ez a weboldal sütiket használ a böngészési élmény javítása és a webhely megfelelő működésének biztosítása érdekében. A webhely használatának folytatásával elismeri és elfogadja a sütik használatát.

Összes elfogadása Csak a szükségesek elfogadása