Klávesnice:zmáčknutí a zvednutí kláves

Než se dostaneme ke klávesnici, všimněte si prosím, že na moderních zařízeních existují jiné způsoby, jak „něco zadat“. Lidé například používají rozpoznávání řeči (zejména na mobilních zařízeních) nebo kopírování/vkládání pomocí myši.

Pokud tedy chceme sledovat jakýkoli vstup do <input> pole, pak události klávesnice nestačí. Je tu další událost s názvem input sledovat změny <input> pole, jakýmkoli způsobem. A pro takový úkol to může být lepší volba. Probereme to později v kapitole Události:změna, zadání, vyjmutí, kopírování, vložení.

Události klávesnice by se měly používat, když chceme ovládat akce klávesnice (počítá se i virtuální klávesnice). Chcete-li například reagovat na klávesy se šipkami Nahoru a Dolů nebo klávesové zkratky (včetně kombinací kláves).

Testovací stojan

Chcete-li lépe porozumět událostem klávesnice, můžete použít níže uvedený teststand.

Vyzkoušejte různé kombinace kláves v textovém poli.

Resultscript.jsstyle.cssindex.html
kinput.onkeydown = kinput.onkeyup = kinput.onkeypress = handle;

let lastTime = Date.now();

function handle(e) {
 if (form.elements[e.type + 'Ignore'].checked) return;

 area.scrollTop = 1e6;

 let text = e.type +
 ' key=' + e.key +
 ' code=' + e.code +
 (e.shiftKey ? ' shiftKey' : '') +
 (e.ctrlKey ? ' ctrlKey' : '') +
 (e.altKey ? ' altKey' : '') +
 (e.metaKey ? ' metaKey' : '') +
 (e.repeat ? ' (repeat)' : '') +
 "\n";

 if (area.value && Date.now() - lastTime > 250) {
 area.value += new Array(81).join('-') + '\n';
 }
 lastTime = Date.now();

 area.value += text;

 if (form.elements[e.type + 'Stop'].checked) {
 e.preventDefault();
 }
}
#kinput {
 font-size: 150%;
 box-sizing: border-box;
 width: 95%;
}

#area {
 width: 95%;
 box-sizing: border-box;
 height: 250px;
 border: 1px solid black;
 display: block;
}

form label {
 display: inline;
 white-space: nowrap;
}
<!DOCTYPE HTML>
<html>

<head>
 <meta charset="utf-8">
 <link rel="stylesheet" href="style.css">
</head>

<body>

 <form id="form" onsubmit="return false">

 Prevent default for:
 <label>
 <input type="checkbox" name="keydownStop" value="1"> keydown</label>&nbsp;&nbsp;&nbsp;
 <label>
 <input type="checkbox" name="keyupStop" value="1"> keyup</label>

 <p>
 Ignore:
 <label>
 <input type="checkbox" name="keydownIgnore" value="1"> keydown</label>&nbsp;&nbsp;&nbsp;
 <label>
 <input type="checkbox" name="keyupIgnore" value="1"> keyup</label>
 </p>

 <p>Focus on the input field and press a key.</p>

 <input type="text" placeholder="Press keys here" id="kinput">

 <textarea id="area" readonly></textarea>
 <input type="button" value="Clear" onclick="area.value = ''" />
 </form>
 <script src="script.js"></script>


</body>
</html>

Stisknutí klávesy a klávesa

keydown události nastanou, když je stisknuta klávesa a poté keyup – až bude vydán.

event.code a event.key

key vlastnost objektu události umožňuje získat znak, zatímco code vlastnost objektu události umožňuje získat „kód fyzického klíče“.

Například stejný klíč Z lze stisknout s nebo bez Shift . To nám dává dva různé znaky:malá písmena z a velká písmena Z .

event.key je přesně ta postava a bude jiná. Ale event.code je stejný:

Klíč event.key event.code
Z z (malá písmena) KeyZ
Shift+Z Z (velká písmena) KeyZ

Pokud uživatel pracuje s různými jazyky, přepnutím do jiného jazyka by vznikl zcela jiný znak namísto "Z" . To se stane hodnotou event.key , zatímco event.code je vždy stejný:"KeyZ" .

„KeyZ“ a další kódy tlačítek

Každá klávesa má kód, který závisí na jejím umístění na klávesnici. Klíčové kódy popsané ve specifikaci kódu událostí uživatelského rozhraní.

Například:

  • Klávesy s písmeny mají kódy "Key<letter>" :"KeyA" , "KeyB" atd.
  • Číselné klíče mají kódy:"Digit<number>" :"Digit0" , "Digit1" atd.
  • Speciální klíče jsou kódovány svými názvy:"Enter" , "Backspace" , "Tab" atd.

Existuje několik rozšířených rozložení klávesnice a specifikace poskytuje kódy kláves pro každé z nich.

Další kódy najdete v alfanumerické části specifikace nebo stačí stisknout klávesu na výše uvedeném testovacím stojanu.

Na případu záleží:"KeyZ" , nikoli "keyZ"

Zdá se to zřejmé, ale lidé stále dělají chyby.

Vyvarujte se prosím překlepů:je to KeyZ , nikoli keyZ . Kontrola jako event.code=="keyZ" nebude fungovat:první písmeno "Key" musí být velká písmena.

Co když klíč nedává žádný znak? Například Shift nebo F1 nebo jiné. Pro tyto klíče event.key je přibližně stejný jako event.code :

Klíč event.key event.code
F1 F1 F1
Backspace Backspace Backspace
Shift Shift ShiftRight nebo ShiftLeft

Upozorňujeme, že event.code přesně určuje, která klávesa je stisknuta. Například většina klávesnic má dva Shift klávesy:na levé a pravé straně. event.code nám přesně říká, která z nich byla stisknuta, a event.key je zodpovědný za „význam“ klávesy:co to je („Shift“).

Řekněme, že chceme zpracovat klávesovou zkratku:Ctrl+Z (nebo Cmd+Z pro Mac). Většina textových editorů na něj zachytí akci „Zpět“. Můžeme nastavit posluchače na keydown a zkontrolujte, která klávesa je stisknuta.

Je zde dilema:v takovém posluchači bychom měli zkontrolovat hodnotu event.key nebo event.code ?

Na jedné straně hodnota event.key je znak, mění se v závislosti na jazyku. Pokud má návštěvník v OS několik jazyků a přepíná mezi nimi, stejná klávesa dává různé znaky. Proto má smysl zkontrolovat event.code , je to vždy stejné.

Takhle:

document.addEventListener('keydown', function(event) {
 if (event.code == 'KeyZ' && (event.ctrlKey || event.metaKey)) {
 alert('Undo!')
 }
});

Na druhou stranu je problém s event.code . Pro různá rozložení klávesnice může mít stejná klávesa různé znaky.

Zde je například rozložení pro USA („QWERTY“) a německé rozložení („QWERTZ“) pod ním (z Wikipedie):

Pro stejný klíč má americké rozložení „Z“, zatímco německé rozložení má „Y“ (písmena jsou prohozena).

Doslova event.code se bude rovnat KeyZ pro lidi s německým rozložením, když stisknou Y .

Pokud zaškrtneme event.code == 'KeyZ' v našem kódu pak pro lidi s německým rozložením takový test projde, když stisknou Y .

Zní to opravdu divně, ale je to tak. Specifikace takové chování výslovně zmiňuje.

Takže event.code může odpovídat nesprávnému znaku pro neočekávané rozvržení. Stejná písmena v různých rozvrženích se mohou mapovat na různé fyzické klíče, což vede k různým kódům. Naštěstí se to děje pouze u několika kódů, např. keyA , keyQ , keyZ (jak jsme viděli) a nestává se to u speciálních klíčů, jako je Shift . Seznam najdete ve specifikaci.

Chcete-li spolehlivě sledovat znaky závislé na rozvržení, event.key může být lepší způsob.

Na druhé straně event.code má tu výhodu, že zůstává vždy stejný, vázaný na umístění fyzického klíče. Takže klávesové zkratky, které na to spoléhají, fungují dobře i v případě změny jazyka.

Chceme pracovat s klávesami závislými na rozvržení? Potom event.key je správná cesta.

Nebo chceme, aby klávesová zkratka fungovala i po změně jazyka? Potom event.code může být lepší.

Automatické opakování

Pokud je klávesa stisknuta dostatečně dlouho, začne se „automaticky opakovat“:keydown spouští znovu a znovu, a když je uvolněn, konečně dostaneme keyup . Je tedy normální mít mnoho keydown a jeden keyup .

U událostí spouštěných automatickým opakováním má objekt události event.repeat vlastnost nastavena na true .

Výchozí akce

Výchozí akce se liší, protože existuje mnoho možných věcí, které mohou být iniciovány klávesnicí.

Například:

  • Na obrazovce se objeví postava (nejviditelnější výsledek).
  • Znak je smazán (Smazat klíč).
  • Stránka se posune (PageDown klíč).
  • Prohlížeč otevře dialogové okno „Uložit stránku“ (Ctrl+S )
  • …a tak dále.

Zabránění výchozí akci na keydown může většinu z nich zrušit, s výjimkou speciálních klíčů založených na operačním systému. Například ve Windows Alt+F4 zavře aktuální okno prohlížeče. A neexistuje způsob, jak to zastavit tím, že zabráníte výchozí akci v JavaScriptu.

Například <input> níže očekává telefonní číslo, takže nepřijímá klíče kromě číslic, + , () nebo - :

<script>
function checkPhoneKey(key) {
 return (key >= '0' && key <= '9') || ['+','(',')','-'].includes(key);
}
</script>
<input onkeydown="return checkPhoneKey(event.key)" placeholder="Phone, please" type="tel">

onkeydown handler zde používá checkPhoneKey pro kontrolu stisknutého tlačítka. Pokud je platný (od 0..9 nebo jeden z +-() ), pak vrátí true , jinak false .

Jak víme, false hodnota vrácená obslužnou rutinou události, přiřazená pomocí vlastnosti DOM nebo atributu, jako je výše, brání výchozí akci, takže v <input> se nic neobjeví pro klíče, které neprojdou testem. (true vrácená hodnota nemá na nic vliv, pouze vrací false záleží)

Upozorňujeme, že speciální klávesy, jako je Backspace , Vlevo , Vpravo , nefungují ve vstupu. To je vedlejší efekt přísného filtru checkPhoneKey . Tyto klíče způsobí, že vrátí false .

Uvolněme filtr trochu tím, že povolíme klávesy se šipkami Vlevo , Vpravo a Smazat , Backspace :

<script>
function checkPhoneKey(key) {
 return (key >= '0' && key <= '9') ||
 ['+','(',')','-','ArrowLeft','ArrowRight','Delete','Backspace'].includes(key);
}
</script>
<input onkeydown="return checkPhoneKey(event.key)" placeholder="Phone, please" type="tel">

Nyní šipky a mazání fungují dobře.

I když máme klíčový filtr, stále lze zadat cokoli pomocí myši a kliknout pravým tlačítkem + Vložit. Mobilní zařízení poskytují další prostředky pro zadávání hodnot. Filtr tedy není 100% spolehlivý.

Alternativním přístupem by bylo sledování oninput událost – spustí se po jakákoliv úprava. Zde můžeme zkontrolovat nový input.value a upravte jej/zvýrazněte <input> když je neplatný. Nebo můžeme použít oba obslužné rutiny událostí společně.

Starší

V minulosti existoval keypress událost a také keyCode , charCode , which vlastnosti objektu události.

Při práci s nimi bylo tolik nekompatibilit prohlížečů, že vývojáři specifikace neměli jinou možnost, než je všechny zavrhnout a vytvořit nové, moderní události (popsané výše v této kapitole). Starý kód stále funguje, protože je prohlížeče stále podporují, ale už je není potřeba používat.

Mobilní klávesnice

Při použití virtuálních/mobilních klávesnic, formálně známých jako IME (Input-Method Editor), standard W3C uvádí, že e.keyCode události KeyboardEvent by mělo být 229 a e.key by mělo být "Unidentified" .

I když některé z těchto klávesnic mohou stále používat správné hodnoty pro e.key , e.code , e.keyCode … při stisknutí určitých kláves, jako jsou šipky nebo backspace, neexistuje žádná záruka, takže logika vaší klávesnice nemusí na mobilních zařízeních vždy fungovat.

Shrnutí

Stisknutí klávesy vždy vygeneruje událost klávesnice, ať už jde o klávesy se symboly nebo speciální klávesy jako Shift nebo Ctrl a tak dále. Jedinou výjimkou je Fn klíč, který se někdy vyskytuje na klávesnici notebooku. Neexistuje pro to žádná událost klávesnice, protože je často implementována na nižší úrovni než OS.

Události klávesnice:

  • keydown – při stisknutí klávesy (automaticky se opakuje, pokud je klávesa stisknuta dlouho),
  • keyup – při uvolnění klíče.

Vlastnosti události hlavní klávesnice:

  • code – „kód klíče“ ("KeyA" , "ArrowLeft" a tak dále), specifické pro fyzické umístění klávesy na klávesnici.
  • key – znak ("A" , "a" a tak dále), pro klávesy bez znaků, jako je Esc , má obvykle stejnou hodnotu jako code .

V minulosti byly události klávesnice někdy používány ke sledování uživatelského vstupu do polí formuláře. To není spolehlivé, protože vstup může pocházet z různých zdrojů. Máme input a change události pro zpracování jakéhokoli vstupu (popsané dále v kapitole Události:změna, zadání, vyjmutí, kopírování, vložení). Spouštějí se po jakémkoliv vstupu, včetně kopírování-vkládání nebo rozpoznávání řeči.

Události klávesnice bychom měli používat, když opravdu chceme klávesnici. Například pro reakci na klávesové zkratky nebo speciální klávesy.