2.5.2 - Mutatóművelet megszakítása

Röviden a szabványpontról

A WCAG 2.5.2 (Pointer Cancellation) előírja, hogy minden mutatóval (egér, érintés, stylus) kiváltott művelet megszakítható vagy visszavonható legyen a befejezés előtt. Ez olyan interaktív tartalomra vonatkozik, ahol egy mutató művelet változást indít el, például gomb aktiválása, űrlap elküldése vagy elem húzása.

Mire vonatkozik: Interaktív tartalomra, ahol mutató művelet változást indít el: gomb aktiválás, űrlap küldés, elemek húzása.

Cél: A véletlenszerű vagy nem szándékos műveletek elkerülése, különösen akkor, ha azok mutatóeszköz (egér, érintőképernyő, stylus) használatával történnek. Ez segíti:

  • A szándékolatlan műveletek megelőzését (pl. véletlen kattintásból eredő hibák)
  • A felhasználók számára a műveletek megszakításának lehetőségét
  • A mozgáskorlátozott felhasználók biztonságosabb interakcióját
  • A segítő technológiákat használók számára a megbízhatóbb vezérlést

Kiket érint

Elsődleges felhasználók: Mozgáskorlátozottak, akiknek nehézséget okoz a pontos mutató mozgások vezérlése, beleértve a remegéssel vagy korlátozott kézügyességgel élőket. Érintőeszköz felhasználók, akik véletlenül érinthetnek vagy húzhatnak.

Másodlagos előnyök: Javítja az általános használhatóságot azáltal, hogy csökkenti a véletlen műveletek okozta frusztrációt minden felhasználó számára, beleértve a mobileszköz felhasználókat, vagy ideiglenes korlátozottsággal élőket.

Tesztelés

  1. Húzás művelet megszakítása: Kezdj el húzni egy elemet és nézd meg, hogy megszakíthatod-e a húzást a mutató elengedésével a célterületen kívül, vagy az Escape billentyű megnyomásával
  2. Dupla érintés vagy hosszú nyomás tesztelése: Ellenőrizd, hogy a dupla érintés vagy hosszú nyomás műveletek megszakíthatók-e a befejezés előtt
  3. Billentyűzet alternatívák használata: Győződj meg róla, hogy a billentyűzetes felhasználók megszakíthatják a műveleteket olyan billentyűkkel, mint az Escape
  4. Véletlen érintések szimulálása: Érintőeszközökön próbálj megérinteni egy interaktív elemet és mozgasd el az ujjad elengedés előtt, hogy meggyőződj róla, a művelet nem aktiválódik
  5. Képernyőolvasó tesztelés: Ellenőrizd, hogy a segítő technológia felhasználók megszakíthatják a mutató által kezdeményezett műveleteket, különösen egyéni vezérlőknél

Jó megoldások

1. Megszakítható húzás és ejtés

<!-- Jó: Húzás megszakítható elengedéssel célterületen kívül -->
<div class="huzas-container">
  <div class="huzas-forras">
    <div id="huzhatò-elem-1" 
         class="huzhatò-elem" 
         draggable="true" 
         aria-grabbed="false" 
         tabindex="0">
      📄 Dokumentum 1
    </div>
    <div id="huzhatò-elem-2" 
         class="huzhatò-elem" 
         draggable="true" 
         aria-grabbed="false" 
         tabindex="0">
      📄 Dokumentum 2
    </div>
    <div id="huzhatò-elem-3" 
         class="huzhatò-elem" 
         draggable="true" 
         aria-grabbed="false" 
         tabindex="0">
      📄 Dokumentum 3
    </div>
  </div>
  
  <div class="huzas-celok">
    <div id="mappa-1" 
         class="huzas-cel" 
         data-accept="document">
      📁 Projekt mappa
    </div>
    <div id="kuka" 
         class="huzas-cel kukà" 
         data-accept="document">
      🗑️ Törlés
    </div>
  </div>
  
  <div class="huzas-info">
    <p><strong>Használat:</strong> Húzd a dokumentumokat a mappába vagy a kukába. Megszakítás: engedj el a célterületen kívül vagy nyomd meg az Escape billentyűt.</p>
  </div>
</div>

<style>
.huzas-container {
  max-width: 600px;
  margin: 20px auto;
  padding: 20px;
  border: 2px dashed #ddd;
  border-radius: 8px;
}

.huzas-forras {
  margin-bottom: 30px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 4px;
}

.huzhatò-elem {
  display: inline-block;
  padding: 12px 20px;
  margin: 5px;
  background: white;
  border: 2px solid #007bff;
  border-radius: 4px;
  cursor: grab;
  user-select: none;
  transition: all 0.2s ease;
}

.huzhatò-elem:hover {
  background: #e7f1ff;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.huzhatò-elem:focus {
  outline: 2px solid #ffc107;
  outline-offset: 2px;
}

.huzhatò-elem[aria-grabbed="true"] {
  cursor: grabbing;
  opacity: 0.7;
  transform: rotate(5deg);
  background: #fff3cd;
  border-color: #ffc107;
}

.huzas-celok {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.huzas-cel {
  flex: 1;
  padding: 30px 20px;
  border: 3px dashed #6c757d;
  border-radius: 8px;
  text-align: center;
  background: #f8f9fa;
  transition: all 0.3s ease;
  min-height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
}

.huzas-cel.drag-over {
  border-color: #28a745;
  background: #d4edda;
  transform: scale(1.05);
}

.huzas-cel.kukà.drag-over {
  border-color: #dc3545;
  background: #f8d7da;
}

.huzas-info {
  background: #e9ecef;
  padding: 15px;
  border-radius: 4px;
  font-size: 14px;
}
</style>

<script>
let huzasBeleFogott = false;
let huzottElem = null;

// Húzás indítása
document.querySelectorAll('.huzhatò-elem').forEach(elem => {
  elem.addEventListener('dragstart', function(e) {
    huzasBeleFogott = true;
    huzottElem = this;
    this.setAttribute('aria-grabbed', 'true');
    
    // Drag képe
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/html', this.innerHTML);
    e.dataTransfer.setData('text/plain', this.textContent);
  });
  
  elem.addEventListener('dragend', function(e) {
    // Jó: Húzás vége - megszakítás vagy befejezés
    this.setAttribute('aria-grabbed', 'false');
    huzasBeleFogott = false;
    
    // Ha nem volt sikeres drop, visszaállítás
    if (e.dataTransfer.dropEffect === 'none') {
      console.log('Húzás megszakítva - elem visszaáll eredeti helyére');
    }
    
    huzottElem = null;
  });
  
  // Billentyűzet támogatás húzáshoz
  elem.addEventListener('keydown', function(e) {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      // Billentyűzetes "húzás" mód aktiválása
      billentyuzetesHuzasStart(this);
    }
    
    // Jó: Escape megszakítja a húzást
    if (e.key === 'Escape' && this.getAttribute('aria-grabbed') === 'true') {
      e.preventDefault();
      this.setAttribute('aria-grabbed', 'false');
      huzasBeleFogott = false;
      console.log('Húzás megszakítva Escape-pel');
    }
  });
});

// Cél területek kezelése
document.querySelectorAll('.huzas-cel').forEach(cel => {
  cel.addEventListener('dragover', function(e) {
    e.preventDefault(); // Engedélyezi a drop-ot
    this.classList.add('drag-over');
  });
  
  cel.addEventListener('dragleave', function(e) {
    this.classList.remove('drag-over');
  });
  
  cel.addEventListener('drop', function(e) {
    e.preventDefault();
    this.classList.remove('drag-over');
    
    // Jó: Csak ha valóban a célterületre ejtették
    if (huzottElem && huzasBeleFogott) {
      const action = this.id === 'kuka' ? 'törölve' : 'áthelyezve';
      console.log(`Elem ${action}: ${huzottElem.textContent}`);
      
      // Valós alkalmazásban itt történne az áthelyezés/törlés
      if (this.id === 'kuka') {
        huzottElem.style.animation = 'fadeOut 0.3s ease-out forwards';
        setTimeout(() => huzottElem.remove(), 300);
      } else {
        // Vizuális visszajelzés a sikeres áthelyezésről
        huzottElem.style.background = '#d4edda';
        setTimeout(() => huzottElem.style.background = '', 1000);
      }
    }
  });
});

// Billentyűzetes húzás támogatás
let billentyuzetHuzasMod = false;
let aktivisHuzottElem = null;

function billentyuzetesHuzasStart(elem) {
  if (billentyuzetHuzasMod) {
    // Már húzás módban - befejezés
    billentyuzetesHuzasEnd();
    return;
  }
  
  billentyuzetHuzasMod = true;
  aktivisHuzottElem = elem;
  elem.setAttribute('aria-grabbed', 'true');
  
  // Célterületek kiemelése
  document.querySelectorAll('.huzas-cel').forEach(cel => {
    cel.style.border = '3px solid #007bff';
    cel.setAttribute('tabindex', '0');
  });
  
  console.log('Billentyűzetes húzás mód: navigálj a célterületre és nyomd meg az Enter-t');
}

function billentyuzetesHuzasEnd() {
  if (aktivisHuzottElem) {
    aktivisHuzottElem.setAttribute('aria-grabbed', 'false');
  }
  
  billentyuzetHuzasMod = false;
  aktivisHuzottElem = null;
  
  // Célterületek visszaállítása
  document.querySelectorAll('.huzas-cel').forEach(cel => {
    cel.style.border = '';
    cel.removeAttribute('tabindex');
  });
}

// Billentyűzetes drop kezelés
document.querySelectorAll('.huzas-cel').forEach(cel => {
  cel.addEventListener('keydown', function(e) {
    if ((e.key === 'Enter' || e.key === ' ') && billentyuzetHuzasMod && aktivisHuzottElem) {
      e.preventDefault();
      
      const action = this.id === 'kuka' ? 'törölve' : 'áthelyezve';
      console.log(`Elem ${action} billentyűzettel: ${aktivisHuzottElem.textContent}`);
      
      billentyuzetesHuzasEnd();
    }
  });
});

// Globális Escape kezelés
document.addEventListener('keydown', function(e) {
  if (e.key === 'Escape') {
    if (billentyuzetHuzasMod) {
      e.preventDefault();
      console.log('Billentyűzetes húzás megszakítva');
      billentyuzetesHuzasEnd();
    }
  }
});

// CSS animáció
const style = document.createElement('style');
style.textContent = `
@keyframes fadeOut {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(0.8); }
}
`;
document.head.appendChild(style);
</script>

A húzás műveletek megszakíthatóak a célterületen kívüli elengedéssel, vagy az Escape billentyűvel. A billentyűzetes alternatíva is támogatott.

2. Gomb mutató megszakítással

<!-- Jó: Gombok, amelyek megszakíthatók a mutató elengedésével -->
<div class="gomb-teszt-container">
  <h3>Megszakítható gombok</h3>
  
  <button id="kuldes-gomb" class="biztos-gomb">
    📧 Üzenet küldése
  </button>
  
  <button id="torles-gomb" class="veszelyes-gomb">
    🗑️ Fiók törlése
  </button>
  
  <button id="mentes-gomb" class="fontos-gomb">
    💾 Változtatások mentése
  </button>
  
  <div class="gomb-info">
    <p><strong>Tipp:</strong> Nyomd meg és tartsd a gombot, majd húzd el a mutatót a gombról a megszakításhoz.</p>
  </div>
  
  <div id="status-uzenet" class="status-uzenet"></div>
</div>

<style>
.gomb-teszt-container {
  max-width: 500px;
  margin: 20px auto;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 8px;
}

.biztos-gomb, .veszelyes-gomb, .fontos-gomb {
  display: block;
  width: 100%;
  padding: 15px 20px;
  margin: 10px 0;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.2s ease;
  position: relative;
  overflow: hidden;
}

.biztos-gomb {
  background: #007bff;
  color: white;
}

.biztos-gomb:hover {
  background: #0056b3;
}

.biztos-gomb:focus {
  outline: 2px solid #ffc107;
  outline-offset: 2px;
}

.veszelyes-gomb {
  background: #dc3545;
  color: white;
}

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

.veszelyes-gomb:focus {
  outline: 2px solid #ffc107;
  outline-offset: 2px;
}

.fontos-gomb {
  background: #28a745;
  color: white;
}

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

.fontos-gomb:focus {
  outline: 2px solid #ffc107;
  outline-offset: 2px;
}

.gomb-aktiv {
  transform: scale(0.98);
  box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
}

.gomb-info {
  background: #e9ecef;
  padding: 15px;
  border-radius: 4px;
  margin: 20px 0;
  font-size: 14px;
}

.status-uzenet {
  padding: 10px;
  border-radius: 4px;
  margin-top: 10px;
  min-height: 20px;
  transition: all 0.3s ease;
}

.status-uzenet.siker {
  background: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
}

.status-uzenet.megszakitva {
  background: #fff3cd;
  color: #856404;
  border: 1px solid #ffeaa7;
}

.status-uzenet.hiba {
  background: #f8d7da;
  color: #721c24;
  border: 1px solid #f5c6cb;
}
</style>

<script>
// Gomb állapot követése
const gombAllapotok = new Map();

function gombEventHandler(gombId) {
  const gomb = document.getElementById(gombId);
  const statusElem = document.getElementById('status-uzenet');
  
  let mutatoLenyomva = false;
  let mutatoAGombon = true;
  
  // Jó: Mutató lenyomás - még nem aktiválás
  gomb.addEventListener('pointerdown', function(e) {
    mutatoLenyomva = true;
    mutatoAGombon = true;
    this.classList.add('gomb-aktiv');
    
    statusElem.textContent = 'Gomb lenyomva - húzd el a megszakításhoz...';
    statusElem.className = 'status-uzenet';
    
    console.log(`${gombId}: Mutató lenyomva`);
  });
  
  // Jó: Mutató mozgás követése
  gomb.addEventListener('pointerenter', function(e) {
    if (mutatoLenyomva) {
      mutatoAGombon = true;
      this.classList.add('gomb-aktiv');
      statusElem.textContent = 'Mutató vissza a gombon - elengedéskor aktiválódik';
    }
  });
  
  gomb.addEventListener('pointerleave', function(e) {
    if (mutatoLenyomva) {
      mutatoAGombon = false;
      this.classList.remove('gomb-aktiv');
      statusElem.textContent = 'Mutató elmozdult a gombról - elengedéskor megszakítás';
      statusElem.className = 'status-uzenet megszakitva';
    }
  });
  
  // Jó: Mutató elengedés - aktiválás vagy megszakítás
  gomb.addEventListener('pointerup', function(e) {
    if (mutatoLenyomva) {
      this.classList.remove('gomb-aktiv');
      
      if (mutatoAGombon) {
        // Aktiválás
        executeGombAction(gombId);
        statusElem.textContent = `${this.textContent} - művelet végrehajtva!`;
        statusElem.className = 'status-uzenet siker';
      } else {
        // Megszakítás
        statusElem.textContent = 'Művelet megszakítva - mutató nem a gombon volt elengedéskor';
        statusElem.className = 'status-uzenet megszakitva';
      }
    }
    
    mutatoLenyomva = false;
    mutatoAGombon = true;
  });
  
  // Jó: Mutató megszakítás kezelése
  gomb.addEventListener('pointercancel', function(e) {
    mutatoLenyomva = false;
    mutatoAGombon = true;
    this.classList.remove('gomb-aktiv');
    
    statusElem.textContent = 'Mutató művelet megszakítva (pointercancel)';
    statusElem.className = 'status-uzenet megszakitva';
    
    console.log(`${gombId}: Mutató megszakítva`);
  });
  
  // Billentyűzet támogatás
  gomb.addEventListener('keydown', function(e) {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      
      // Billentyűzettel azonnali aktiválás (nincs megszakítási lehetőség)
      executeGombAction(gombId);
      statusElem.textContent = `${this.textContent} - végrehajtva billentyűzettel!`;
      statusElem.className = 'status-uzenet siker';
    }
  });
  
  // Jó: Escape megszakítás támogatás
  gomb.addEventListener('keydown', function(e) {
    if (e.key === 'Escape' && mutatoLenyomva) {
      e.preventDefault();
      mutatoLenyomva = false;
      mutatoAGombon = true;
      this.classList.remove('gomb-aktiv');
      
      statusElem.textContent = 'Gomb művelet megszakítva Escape-pel';
      statusElem.className = 'status-uzenet megszakitva';
    }
  });
}

function executeGombAction(gombId) {
  switch(gombId) {
    case 'kuldes-gomb':
      console.log('Üzenet elküldve!');
      // Valós alkalmazásban: űrlap küldés, API hívás, stb.
      break;
      
    case 'torles-gomb':
      // Megerősítés kérése veszélyes műveletnél
      if (confirm('Biztosan törölni szeretnéd a fiókot? Ez a művelet visszavonhatatlan!')) {
        console.log('Fiók törölve!');
        // Valós alkalmazásban: törlési API hívás
      } else {
        const statusElem = document.getElementById('status-uzenet');
        statusElem.textContent = 'Fiók törlés megszakítva felhasználó által';
        statusElem.className = 'status-uzenet megszakitva';
      }
      break;
      
    case 'mentes-gomb':
      console.log('Változtatások mentve!');
      // Valós alkalmazásban: adatok mentése
      break;
      
    default:
      console.log(`${gombId} aktiválva`);
  }
}

// Event handler-ek beállítása minden gombhoz
['kuldes-gomb', 'torles-gomb', 'mentes-gomb'].forEach(gombEventHandler);

// Státusz üzenet automatikus eltűntetése
let statusTimeout;
document.getElementById('status-uzenet').addEventListener('DOMSubtreeModified', function() {
  clearTimeout(statusTimeout);
  statusTimeout = setTimeout(() => {
    this.textContent = '';
    this.className = 'status-uzenet';
  }, 5000);
});
</script>

A gombok csak akkor aktiválódnak, ha a mutató a gombon van elengedéskor. A művelet megszakítható a mutató elmozgatásával, vagy az Escape billentyűvel.

3. Érintőeszközök támogatása

<!-- Jó: Érintő interakciók megszakítási lehetőséggel -->
<div class="erintesi-teszt-container">
  <h3>Érintő gesztusok tesztelése</h3>
  
  <div class="erintesi-terület">
    <div id="erintesi-gomb-1" class="erintesi-gomb">
      📱 Hosszú nyomás tesztelése
    </div>
    
    <div id="erintesi-gomb-2" class="erintesi-gomb">
      👆 Dupla érintés tesztelése
    </div>
    
    <div id="huzas-elem" class="huzas-terület">
      ↔️ Húzható terület
    </div>
  </div>
  
  <div class="erintesi-info">
    <p><strong>Hosszú nyomás:</strong> Érintsd meg és tartsd 1 másodpercig. Megszakítás: húzd el az ujjad.

<p><strong>Dupla érintés:</strong> Érintsd meg kétszer gyorsan. Megszakítás: várj a második érintés előtt.

<p><strong>Húzás:</strong> Húzd vízszintesen. Megszakítás: engedj el 50 pixel előtt.

Az érintőeszközökön a hosszú nyomás, dupla érintés és húzás műveletek mind megszakíthatók a megfelelő gesztus befejezése előtt.

Rossz gyakorlatok

Azonnali aktiválás „pointer down” eseménynél

<!-- Rossz: Művelet aktiválása már a lenyomáskor -->
<button id="rossz-gomb-1" class="rossz-gomb">Rossz gomb 1</button>
<button id="rossz-gomb-2" class="rossz-gomb">Rossz gomb 2</button>

<script>
// Rossz: Azonnali aktiválás pointerdown-nál
document.getElementById('rossz-gomb-1').addEventListener('pointerdown', function() {
  alert('Művelet azonnal végrehajtva!'); // Nincs megszakítási lehetőség
});

// Rossz: onclick és onpointerdown együtt
document.getElementById('rossz-gomb-2').onclick = function() {
  alert('Click aktiválás!');
};

document.getElementById('rossz-gomb-2').onpointerdown = function() {
  alert('Pointer down aktiválás!'); // Dupla aktiválás + nincs megszakítás
};
</script>

Probléma: A műveletek kiváltása már a mutató lenyomásakor nem ad lehetőséget a megszakításra, ami véletlen aktiválásokhoz vezet.

„Pointer cancel” esemény figyelmen kívül hagyása

<!-- Rossz: Pointercancel esemény kezelésének hiánya -->
<div id="rossz-huzas" class="rossz-huzas-terület">
  Rossz húzható terület
</div>

<script>
// Rossz: Nincs pointercancel kezelés
const rosszHuzas = document.getElementById('rossz-huzas');
let rosszHuzasAktiv = false;

rosszHuzas.addEventListener('pointerdown', function(e) {
  rosszHuzasAktiv = true;
  console.log('Húzás indítva');
});

rosszHuzas.addEventListener('pointermove', function(e) {
  if (rosszHuzasAktiv) {
    // Húzás folytatása
    console.log('Húzás folyik...');
  }
});

rosszHuzas.addEventListener('pointerup', function(e) {
  if (rosszHuzasAktiv) {
    console.log('Húzás befejezve - művelet végrehajtva');
    // Művelet végrehajtása minden esetben
    rosszHuzasAktiv = false;
  }
});

// Rossz: Nincs pointercancel event listener
// Ha a rendszer megszakítja a pointer eseményt, a változó true marad
// és a húzás állapot nem áll vissza helyesen

// Rossz: Nincs Escape billentyű támogatás sem
// A felhasználók nem tudják megszakítani a húzást billentyűzettel
</script>

Probléma: A pointercancel esemény figyelmen kívül hagyása azt jelenti, hogy a felhasználók nem tudják megszakítani a mutató műveleteket.

Húzás és ejtés megszakítás nélkül

<!-- Rossz: Húzás művelet megszakítási lehetőség nélkül -->
<div class="rossz-dnd-container">
  <div id="rossz-huzható" class="rossz-huzható-elem" draggable="true">
    Rossz húzható elem
  </div>
  
  <div id="rossz-cél" class="rossz-cél-terület">
    Rossz cél terület
  </div>
</div>

<script>
// Rossz: Nincs megszakítási lehetőség
const rosszHuzható = document.getElementById('rossz-huzható');
const rosszCél = document.getElementById('rossz-cél');

rosszHuzható.addEventListener('dragstart', function(e) {
  console.log('Húzás indítva');
  // Rossz: Nincs státusz jelzés vagy megszakítási info
});

rosszHuzható.addEventListener('dragend', function(e) {
  // Rossz: Nem ellenőrzi, hogy sikeres volt-e a drop
  console.log('Húzás végrehajtva minden esetben');
  // Még ha a felhasználó a célterületen kívül engedte el, 
  // akkor is végrehajtódik valamilyen művelet
});

rosszCél.addEventListener('dragover', function(e) {
  e.preventDefault(); // Ez rendben van
});

rosszCél.addEventListener('drop', function(e) {
  e.preventDefault();
  console.log('Elem eldobva');
  // Rossz: Nincs megerősítés vagy visszavonási lehetőség
  
  // Azonnal végrehajtja a műveletet
  rosszHuzható.style.display = 'none'; // Elem eltűnik
});

// Rossz: Nincs Escape billentyű kezelés
// Rossz: Nincs vizuális visszajelzés a megszakítási lehetőségekről
// Rossz: Nincs undo funkció

// Rossz: Touch eszközökön nincs alternatív módszer
rosszHuzható.addEventListener('touchstart', function(e) {
  // Próbál saját touch-based drag-et implementálni
  // de nincs megszakítási lehetőség
});

rosszHuzható.addEventListener('touchmove', function(e) {
  // Vizuális mozgatás
  const touch = e.touches[0];
  this.style.position = 'absolute';
  this.style.left = touch.clientX + 'px';
  this.style.top = touch.clientY + 'px';
  
  // Rossz: Nincs lehetőség a művelet megszakítására
});

rosszHuzható.addEventListener('touchend', function(e) {
  // Rossz: Azonnal "eldobja" az elemet ahol az ujj felengedődött
  // Nincs ellenőrzés, hogy valóban célterületen van-e
  console.log('Touch húzás befejezve - művelet végrehajtva');
  this.style.display = 'none'; // Elem eltűnik
});
</script>

<style>
.rossz-dnd-container {
  padding: 20px;
  border: 2px solid #dc3545;
  border-radius: 8px;
  margin: 20px 0;
}

.rossz-huzható-elem {
  padding: 15px;
  background: #dc3545;
  color: white;
  margin-bottom: 20px;
  cursor: grab;
  border-radius: 4px;
}

.rossz-cél-terület {
  padding: 30px;
  border: 2px dashed #6c757d;
  background: #f8f9fa;
  text-align: center;
  border-radius: 4px;
}
</style>

Probléma: A húzás és ejtés műveletek, amelyeket nem lehet megszakítani a célterületen kívüli elengedéssel vagy az Escape megnyomásával, nem felelnek meg a szabványnak.

Komplex gesztusok visszavonási lehetőség nélkül

<!-- Rossz: Összetett gesztusok azonnali végrehajtással -->
<div id="rossz-gesztur-terület" class="rossz-gesztur-container">
  Rossz gesztus terület - rajzolj "Z" alakot
</div>

<script>
// Rossz: Komplex gesztus azonnali végrehajtással
const rosszGesztusElem = document.getElementById('rossz-gesztur-terület');
let gesztusUtvonal = [];
let gesztusAktiv = false;

rosszGesztusElem.addEventListener('touchstart', function(e) {
  gesztusAktiv = true;
  gesztusUtvonal = [];
  
  const touch = e.touches[0];
  gesztusUtvonal.push({
    x: touch.clientX,
    y: touch.clientY,
    time: Date.now()
  });
});

rosszGesztusElem.addEventListener('touchmove', function(e) {
  if (!gesztusAktiv) return;
  
  const touch = e.touches[0];
  gesztusUtvonal.push({
    x: touch.clientX,
    y: touch.clientY,
    time: Date.now()
  });
  
  // Rossz: Valós időben ellenőrzi a mintát és azonnal végrehajt
  if (gesztusUtvonal.length > 10) {
    const mintaElfogadott = ellenorizZMintat(gesztusUtvonal);
    
    if (mintaElfogadott) {
      // Rossz: Azonnal végrehajtja a műveletet
      console.log('Z minta felismerve - művelet végrehajtva!');
      alert('Kritikus művelet végrehajtva!');
      
      // Rossz: Nincs lehetőség a visszavonásra
      // A művelet már megtörtént
      gesztusAktiv = false;
      gesztusUtvonal = [];
    }
  }
});

rosszGesztusElem.addEventListener('touchend', function(e) {
  // Rossz: Végső ellenőrzés és azonnali végrehajtás
  if (gesztusAktiv && gesztusUtvonal.length > 5) {
    const vegesoEllenorzes = ellenorizZMintat(gesztusUtvonal);
    
    if (vegesoEllenorzes) {
      console.log('Gesztus befejezve - művelet végrehajtva!');
      // Nincs megszakítási vagy visszavonási lehetőség
    }
  }
  
  gesztusAktiv = false;
  gesztusUtvonal = [];
});

// Rossz: Nincs touchcancel kezelés
// Rossz: Nincs Escape billentyű támogatás
// Rossz: Nincs vizuális előnézet vagy megerősítés

function ellenorizZMintat(utvonal) {
  // Egyszerű Z minta ellenőrzés (rossz implementáció)
  if (utvonal.length < 10) return false;
  
  const kezdo = utvonal[0];
  const veg = utvonal[utvonal.length - 1];
  
  // Nagyon egyszerűsített logika
  return Math.abs(veg.x - kezdo.x) > 50 && Math.abs(veg.y - kezdo.y) > 30;
}

// Rossz: Dupla érintés azonnali végrehajtással
rosszGesztusElem.addEventListener('dblclick', function(e) {
  // Rossz: Azonnali végrehajtás dupla kattintásra
  alert('Dupla kattintás - azonnali művelet!');
  console.log('Kritikus művelet végrehajtva dupla kattintással');
  // Nincs megszakítási lehetőség
});

// Rossz: Kontextus menü letiltása anélkül, hogy alternatívát adna
rosszGesztusElem.addEventListener('contextmenu', function(e) {
  e.preventDefault(); // Letiltja a jobb kattintást
  // De nem ad alternatív hozzáférést a funkciókhoz
});
</script>

<style>
.rossz-gesztur-container {
  width: 300px;
  height: 200px;
  border: 2px solid #dc3545;
  background: #f8d7da;
  margin: 20px auto;
  padding: 20px;
  text-align: center;
  border-radius: 8px;
  touch-action: none; /* Rossz: Minden alapértelmezett touch viselkedést letilt */
}
</style>

Probléma: Az összetett gesztusok, amelyek azonnal végrehajtják a műveleteket visszavonási, vagy megerősítési lehetőség nélkül, nem biztosítják a megfelelő felhasználói kontrollt.

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