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
- 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
- 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
- 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
- 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
- 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!