Zdarzenia#

Klawiatura#

Moduł zdarzeń klawiatury # (keyboard event module) jest rozwinięciem modułu zdarzeń interfejsu użytkownika. Definiuje on interfejs KeyboardEvent oraz powiązane z klawiaturowymi urządzeniami wejściowymi następujące typy zdarzeń:

Zdarzenia klawiatury są zależne od urządzenia, to znaczy, że opierają się na możliwościach urządzeń wejściowych oraz ich odwzorowaniach w systemach operacyjnych. W zależności od uprzędzenia generującego znaki zdarzenia klawiatury mogą nie występować. Więcej szczegółów znajduje się w podrozdziale "Zdarzenia klawiatury i wartości klawiszy", z uwzględnieniem przykładów obrazujących kombinacje zdarzeń klawiatury ze zdarzeniami kompozycji i zdarzeniami wejścia.

Zdarzenia klawiatury to tylko jedna z możliwości wprowadzania tekstowego wejścia. W przypadku scenariuszy edycyjnych warto rozważyć użycie zdarzeń wejścia jako alternatywę (lub dodatek) dla zdarzeń klawiatury.

Celem zdarzenia dla zdarzeń klawiatury jest obecnie zogniskowany element, który przetwarza aktywność klawiatury. Bardzo często jest to HTML-owy element <input> lub element tekstowy z możliwością edycji, choć może być to również element zdefiniowany przez język gospodarza do przyjmowania wejścia klawiatury dla nietekstowych zadań, jak np. aktywacja klawiszy akceleratorów lub wyzwolenia jakiegoś innego zachowania. Jeśli żaden element nie posiada zogniskowania to celem zdarzenia będzie elementowe ciało (jeśli istnieje), w przeciwnym razie elementowy korzeń.

Cel zdarzenia może ulec zmianie między różnymi zdarzeniami klawiatury. Dla przykładu, zdarzenie keydown dla klawisza 'Tab' prawdopodobnie będzie miało inny cel zdarzenia niż w przypadku zdarzenia keyup w obrębie tej samej sekwencji wciśnięcia/zwolnienia klawisza. Tabulator po prostu przeniesie nam zogniskowanie na inny element, jeszcze przed wysłaniem zdarzenia keyup.

W celu zapewnienia zgodności z istniejącymi treściami wirtualne klawiatury, takie jak programowe klawiatury w bazujących na ekranie urządzeniach wejściowych powinny generować szereg zdarzeń klawiatury, mimo że nie posiadają fizycznych klawiszy.

Oznaczenia dla wartości klawiszy i znaków#

Z klawiszami związanych jest kilka często powtarzających się pojęć i wartości. W ramach łatwiejszej orientacji użyta została następująca konwencja stylistyczna:

Każdy fragment tekstu oznaczony powyższą stylizacją posiada dymek podpowiedzi (przy użyciu atrybutu title), przez co zapamiętywanie każdego koloru nie jest konieczne (wystarczy najechać kursorem myszy na ostylowany fragment tekstu).

Kolejność zdarzeń wejścia#

Zdarzenia klawiatury występują w ustalonej kolejności względem siebie i względem innych powiązanych zdarzeń. Oto typowa sekwencja zdarzeń dla każdego klawisza:

Nazwa zdarzeniaUwagi
1.keydown
2.beforeinputTylko dla klawiszy, które produkują wartość znakową.
Wszelkie domyślne akcje skojarzone z tym klawiszem, jak np. wstawienie znaku do DOM.
3.inputTylko dla klawiszy, które uaktualniły DOM.
Wszelkie zdarzenia, które są wynikiem przytrzymywania klawisza przez dłuższy okres czasu (patrz niżej).
4.keyup

Jeśli klawisz jest przytrzymywany przez dłuższy okres czasu to w zależności od środowiska następująca kolejność zdarzeń może się powtarzać:

Nazwa zdarzeniaUwagi
1.keydownZ ustawieniem właściwości KeyboardEvent.repeat na boolowskie true.
2.beforeinputTylko dla klawiszy, które produkują wartość znakową.
Wszelkie domyślne akcje skojarzone z tym klawiszem, jak np. wstawienie znaku do DOM.
3.inputTylko dla klawiszy, które uaktualniły DOM.

Zazwyczaj wszelkie domyślne akcje skojarzone z konkretnym klawiszem zostają zakończone przed wysłaniem zdarzenia keyup. To może nieco opóźnić zdarzenie keyup (choć niekoniecznie musi to być zauważalne opóźnienie).

Zdarzenia klawiatury i wartości klawiszy#

Sekcja ta gromadzi niezbędne informacje dotyczące zdarzeń klawiatury:

Wejście klawiaturowe#

Związek każdego klawisza z kompletną klawiaturą należy rozpatrywać w trzech osobnych aspektach, z których każdy różni się w zależności od modelu i konfiguracji klawiatury, ze szczególnym uwzględnieniem ustawień regionalnych:

Specyfikacja D3E definiuje jedynie mapowanie funkcjonalne w zakresie wartości key oraz wartości code, i w ramach poglądowych bardzo krótko opisuje układ klawiatury oraz legendy klawiszy.

Etykiety klawiszy#

Etykieta klawisza (nazywana też legendą) jest wizualnym oznakowaniem nadrukowanym lub wytłoczonym na nasadce klawisza (prostokątnej nasadce, która obejmuje przełącznik mechaniczny na klawiszu). Oznaczenia te zazwyczaj składają się z jednego lub większej liczby znaków, które zostaną wyprodukowane poprzez wciśnięcie klawisza (np. 'F', '8' czy 'ш'), lub nazw czy symboli, które reprezentują funkcję klawisza (np. skierowana w górę strzałka wskazująca 'Shift' lub napis 'Enter'). Należy pamiętać, że wygląd tego klawisza nie ma wpływu na jego cyfrową reprezentację, i w wielu konfiguracjach może być całkowicie błędny. Nawet sterujące czy funkcyjne klawisze, takie jak 'Enter', mogą zostać przypisane do różnych funkcji, a nawet mapowane do klawiszy alfanumerycznych.

Ze względów historycznych klawisze znaków są zazwyczaj oznaczane dużymi literami będącymi odpowiednikami produkowanych wartości znakowych, np. klawisz 'F' (klawisz oznaczany glifem 'F') wyprodukuje wartość znakową 'f' przy nieaktywnym klawiszu modyfikującym 'Shift' lub 'CapsLock'.

Wiele klawiatur zawiera klawisze, które normalnie nie produkują żadnych znaków, mimo że symbol może mieć odpowiednik w Unicode. Dla przykładu, klawisz 'Shift' może być wskazywany przez symbol , którego kod znaku w Unicode to '\u21E7', ale wciśnięcie klawisza 'Shift' nie wyprodukuje tej wartości znakowej, a sam klawisz 'Shift' w Unicode nie ma przypisanego żadnego kodu znaku.

Kody klawiszy#

Kod klawisza code jest właściwością zdarzenia klawiatury, i może być użyty do zidentyfikowania fizycznego klawisza skojarzonego ze zdarzeniem klawiatury. Jest on podobny do identyfikatorów USB ponieważ dostarcza wartość niższego poziomu (podobnie jak skankod), niezależnie od dostawcy.

Podstawowym celem wprowadzenia właściwości code jest zapewnienie zgodnego i spójnego sposobu identyfikacji klawiszy, który bazuje na ich fizycznym położeniu. Ponadto zapewnia także stabilne nazwy (neutralne względem aktualnego stanu klawiatury), które jednoznacznie identyfikują każdy klawisz na klawiaturze.

Lista prawidłowych kodów klawiszy została definiowana w specyfikacji D3E-code.

Motywacja dla wprowadzenia właściwości code#

Standardowa klawiatura PC zawiera zestaw klawiszy (nazywanych systemowymi klawiszami zapisu), które generują różne wartości klawiszy na podstawie wybranego przez użytkownika bieżącego układu klawiatury. Sytuacja taka sprawia, że trudno napisać kod, który wykrywa klawisze w oparciu o ich fizyczną lokalizację, ponieważ kod musiałby wiedzieć, jaki układ klawiszy został użyty. Rzeczywistym przykładem będzie gra, która korzysta z klawiszy 'W', 'A', 'S' i 'D' do kontroli ruchu gracza. Właściwość code rozwiązuje ten problem poprzez dostarczenie stabilnej wartości, która nie podlega wpływowi aktualnemu układowi klawiatury.

Należy podkreślić, że wartość właściwości key zależy także od aktualnego stanu klawiatury. Z tego względu kolejność w jakiej klawisze są wciskane i zwalniane w stosunku do klawiszy modyfikujących może wpływać na wartość przechowywaną we właściwości key. Właściwość code rozwiązuje ten problem poprzez dostarczenie stabilnej wartości, która nie podlega wpływowi aktualnemu stanowi klawiatury.

Różnice między właściwościami key i code#
key
Właściwość KeyboardEvent.key została przewidziana dla użytkowników, którzy są zainteresowani rozpoznaniem wciśniętego klawisza, z uwzględnieniem aktualnego układu klawiatury (włącznie z IME i martwymi klawiszami). Przykładem może być wykrycie zmodyfikowanych klawiszy lub samych klawiszy modyfikujących (np. w celu wykonania akcji w odpowiedzi na skrót klawiaturowy).
code
Właściwość KeyboardEvent.code została przewidziana dla użytkowników, którzy są zainteresowani rozpoznaniem wciśniętego klawisza, bez uwzględniania jakichkolwiek modyfikacji układu. Przykładem może być wykrycie klawiszy WASD (np. dla kontroli ruchu w grze) lub przechwycenie wszystkich klawiszy (np. w kliencie zdalnego pulpitu w celu przesłania ich wszystkich do zdalnego hosta).

W ramach utrwalenia najlepiej przeanalizować kilka teoretycznych przypadków.

Przykład 1:

Wciskamy lewy i prawy klawisz Alt.

Układ klawiatury.key.codeUwagi
US'Alt''AltLeft'DOM_KEY_LOCATION_LEFT
French'Alt''AltLeft'DOM_KEY_LOCATION_LEFT
US'Alt''AltRight'DOM_KEY_LOCATION_RIGHT
French'AltGr''AltRight'DOM_KEY_LOCATION_RIGHT

Sprawdzenie wartości atrybutu key pozwala dopasować klawisz 'Alt' bez martwienia się o to, który klawisz alternatywy został wciśnięty (lewy czy prawy). Sprawdzenie wartości atrybutu code pozwala dopasować prawy klawisz alternatywy ('AltRight') bez martwienia się o to, który układ jest obecnie w użyciu.

Należy zauważyć, że we francuskim przypadku wartości 'Alt' i 'AltGr' odzwierciedlają swoje lewe oraz prawe położenie, nawet jeśli jest tylko jeden taki klawisz.

Przykład 2:

Wciskamy pojedynczy znak cudzysłowu.

Układ klawiatury.key.codeUwagi
US''''Quote'
Japanese':''Quote'
US Intl'Dead''Quote'

Przykład pokazuje, w jaki sposób martwe klawisze zostają zakodowane we właściwościach. Wartość właściwości key bazuje na aktualnej lokalizacji, kiedy właściwość code zwraca spójną wartość.

Przykład 3:

Wciskamy klawisz '2' (z opcjonalnym klawiszem Shift).

Układ klawiatury.key.codeUwagi
US'2''Digit2'
US'@''Digit2'shiftKey był aktywny
UK'2''Digit2'
UK'"''Digit2'shiftKey był aktywny
French'é''Digit2'
French'2''Digit2'shiftKey był aktywny

Niezależnie od aktualnej lokalizacji lub stanu klawisza modyfikującego, naciskając na klawiaturze US klawisz z etykietą '2' w rezultacie zawsze otrzymamy wartość 'Digit2' we właściwości code.

Przykład 4:

Analizujemy sekwencję zdarzeń klawiatury przy wciśnięciu klawiszy 'Shift' i '2'. Obydwie sekwencje produkują znak '@', ale różnią się kolejnością, w której klawisze są zwalniane.

Pierwsza sekwencja ma następującą kolejność klawiszy: 'Shift' (wciskany), '2' (wciskany), '2' (zwalniany), 'Shift' (zwalniany).

Układ klawiaturyZdarzenie.key.codeUwagi
USkeydown'Shift''ShiftLeft'DOM_KEY_LOCATION_LEFT
USkeydown'@''Digit2'shiftKey był aktywny
USkeypress'@'''
USkeyup'@''Digit2'shiftKey był aktywny
USkeyup'Shift''ShiftLeft'DOM_KEY_LOCATION_LEFT

Druga sekwencja ma następującą kolejność klawiszy: 'Shift' (wciskany), '2' (wciskany), 'Shift' (zwalniany), '2' (zwalniany).

Układ klawiaturyZdarzenie.key.codeUwagi
USkeydown'Shift''ShiftLeft'DOM_KEY_LOCATION_LEFT
USkeydown'@''Digit2'shiftKey był aktywny
USkeypress'@'''
USkeyup'Shift''ShiftLeft'DOM_KEY_LOCATION_LEFT
USkeyup'2''Digit2'

Należy zwrócić uwagę, że wartości zawarte we właściwości key nie są identyczne między zdarzeniami keydown i keyup dla klawisza '2'. Właściwość code zapewnia spójną wartość, która nie podlega wpływowi aktualnemu stanowi modyfikatora.

Właściwość code i klawiatury wirtualne#

Przydatność właściwości code jest mniej oczywista w przypadku klawiatur wirtualnych (a także dla zdalnych kontroli i klawiatur akordowych). W ujęciu ogólnym, jeśli wirtualna (lub zdalna) klawiatura naśladuje układ i funkcjonalność standardowej klawiatury, to musi również prawidłowo ustawiać właściwość code. W przypadku klawiatur, które nie naśladują układu standardowej klawiatury, właściwość code może być ustawiana względem najbliższego dopasowania do standardowej klawiatury, lub może pozostać nieokreślona.

Dla klawiatur wirtualnych z przyciskami, które produkują różne wartość w oparciu o stany niektórych modyfikatorów, wartość właściwości code powinna być wartością właściwości key wygenerowaną przy wciśniętym przycisku, gdy urządzenie znajduje się w stanie fabrycznego resetu.

Wartości klawiszy#

Wartość klawisza jest łańcuchem znakowym (typ DOMString), która może być stosowana do wskazywania dowolnego klawisza na klawiaturze poprzez produkowaną przez niego wartość (niezależnie od jego pozycji lub stanu). Wartości klawiszy mogą być używane jako wartości dla wygenerowanych przez implementację zdarzeń klawiatury, lub jako wartości wejściowe od autorów treści do określenia żądanego wejścia (jak w przypadku skrótów klawiszowych).

Lista prawidłowych wartości klawiszy została definiowana w specyfikacji D3E-key.

Wartości klawiszy można wykorzystać do wykrycia wartości wciśniętego klawisza poprzez właściwość KeyboardEvent.key. Autorzy treści mogą otrzymać wartość znakową w postaci wielkich lub małych liter, liczb, symbolów, lub innych wyprodukowanych przez klawisze znaków, a także wartość klawiszową dla klawiszy kontrolnych, klawiszy modyfikujących, klawiszy funkcyjnych, lub innych klawiszy, które nie generują znaków. Wartości te można stosować do monitorowania poszczególnych łańcuchów znakowych wejścia, do wykrywania aktywności klawisza modyfikującego w połączeniu z innymi wejściami (np. myszą), do tworzenia wirtualnych klawiatur, i do dowolnej liczby innych zastosowań.

Wartości klawiszy mogą być również wykorzystywane przez autorów treści przy porównywaniu łańcuchów znakowych, jako wartości w atrybutach znaczników (np. accesskey), zgodnie z językiem gospodarza, lub do innych pokrewnych celów. Zgodny język gospodarza powinien udostępniać autorom treści użycie jednej z dwóch równoważnych wartości łańcuchów znakowych dla wartości klawiszy: wartość znakową lub wartość klawiszową.

Wartość klawisza nie wskazuje konkretnego klawisza na klawiaturze fizycznej, ani nie odzwierciedla wydrukowanego znaku na klawiszu. Wartość klawisza wskazuje aktualną wartość zdarzenia z uwzględnieniem aktualnego stanu wszystkich aktywnych klawiszy i wejściowych trybów klawiszy (włącznie z trybami zmian), co znajduje odzwierciedlenie w mapowaniu klawiatury przez system operacyjny. Innymi słowy wartość klawisza dla klawisza z etykietą 'O' na klawiaturze QWERTY to 'o' (bez Shifta) oraz 'O' (z Shiftem). Ponieważ użytkownik może zmapować swoją klawiaturę do dowolnej niestandardowej konfiguracji, zachęca się aby autorzy treści nie polegali na stanach aktywności klawiszy modyfikujących, i zamiast tego używali po prostu wartości zwracanej przez właściwość KeyboardEvent.key.

Aby uprościć obsługę martwego klawisza, kiedy mapowanie klawiatury systemu operacyjnego obsługuje stan martwego klawisza, bieżący stan sekwencji martwego klawisza nie jest zgłaszany przez właściwość KeyboardEvent.key. Raczej zwracana będzie wartość klawisza w postaci 'Dead'. W zamian implementacje generują zdarzenia kompozycji, które zawierają pośredni stan sekwencji martwego klawisza raportowany przy użyciu właściwości CompositionEvent.data. Dlatego też w powyższym przykładzie wartość klawisza dla klawisza z etykietą 'O' na klawiaturze QWERTY ma we właściwości CompositionEvent.data wartość 'ö' (bez Shifta, ale z operacją martwego klawisza dodającą znak diakrytyczny umlaut) oraz wartość 'Ö' (z Shiftem i operacją martwego klawisza dodającą znak diakrytyczny umlaut).

Ważne jest równie to, że nie istnieje odwzorowanie jeden do jednego między stanami zdarzeń klawiszy a wartościami klawiszy. Konkretna wartość klawisza może być kojarzona z wieloma klawiszami. Dla przykładu, wiele standardowych klawiatur zawiera więcej niż jeden klawisz z wartością klawisza 'Shift' (najczęściej rozróżnianych przy pomocą właściwości KeyboardEvent.location zwracającej stałą DOM_KEY_LOCATION_LEFT lub DOM_KEY_LOCATION_RIGHT) lub z wartością klawisza '8' (najczęściej rozróżnianych przy pomocą właściwości KeyboardEvent.location zwracającej stałą DOM_KEY_LOCATION_STANDARD lub DOM_KEY_LOCATION_NUMPAD), i niestandardowe układy klawiatur użytkowników mogą powielać dowolną wartość klawisza dla wielu scenariuszy aktywności klawiszy.

Należy podkreślić, że właściwość KeyboardEvent.location wprowadzono dla standardowych układów klawiatur, zatem nie we wszystkich przypadkach otrzymamy rzeczywiste położenie klawisza.

Na sam koniec warto nadmienić, że znaczenie reprezentacji znaku zależy od kontekstu i jest bardziej skomplikowane. Dla przykładu, w niektórych kontekstach znak gwiazdki (U+002A, '*') oznacza przypis lub emfazę (kiedy otacza fragment tekstu). Jednakże w niektórych dokumentach lub wykonywalnych programach jest ona równoważna matematycznej operacji mnożenia, kiedy w innych dokumentach lub wykonywalnych programach funkcja ta jest rezerwowana dla symbolu multiplikacji (U+00D7, '×') lub małej litery iks (U+0078, 'x'), z powodu braku klawisza multiplikacji na wielu klawiaturach i powierzchniowego podobieństwa między glifami '×' oraz 'x'. Semantyczne znaczenie lub funkcja reprezentacji znaku jest poza zakresem specyfikacji D3E.

Wartości klawiszy i Unicode#

Wartości klawiszy opisywane w specyfikacji D3E są kodami znaków Unicode, i jako takie mają pewne zalety.

Najbardziej oczywistą zaletą jest to, że autorzy treści mogą używać pełnego zestawu funkcjonalności międzynarodowego standardu języka dostępnego w implementacji, niezależnie od ograniczeń tekstowych urządzeń wejściowych w systemie. Otwiera także nowe możliwości dla wirtualnych klawiatur oraz mobilnych aplikacji bazujących na edytorach metod wejściowych.

Z wartościami klawiszy i wyrażeniami regularnymi autorzy treści mogą obsługiwać selektywne i intuicyjne zakresy dla wejścia opartego na klawiszach, w sensie zaawansowanego międzynarodowego wsparcia niezależnego od platformy, jak w przypadku poniższego pseudokodu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
if (event.key == "-" || event.key.match("\p{Sc}") || event.key.match("\p{N}")){
	// minus sign, any currency symbol, and numeric characters (regardless of key location)
	// ...
}

else if (event.key.match("\p{L}")){
	// alphabetic characters from any language, upper and lower case
	// ...
}

else{
	// ...
}

Z uwagi na fakt, że Unicode przypisuje każdy kod znaku do odpowiedniej grupy właściwej dla danego system pisma ludzkiego, jeszcze bardziej zaawansowane funkcje są możliwe. Przykładowo, autor zawartości może dopasować jedynie te znaki, które pochodzą z konkretnego skryptu (np. tybetańskiego) poprzez wyrażenie regularne w postaci \p{Tibetan}, odfiltrowując tym samym niechciane znaki, lub sprawdzić, czy kod znaku znajduje się w konkretnym bloku przy użyciu wyrażenia regularnego w postaci \p{InCyrillic}.

Implementacje powinny wspierać wykrywanie zakresów Unicode za pomocą wyrażeń regularnych, choćby przy użyciu biblioteki PCRE (Perl Compatible Regular Expressions).

Klawisze modyfikujące#

Klawiatura używa klawiszy modyfikujących do zmiany normalnego zachowania klawisza. Podobnie jak inne klawisze, klawisze modyfikujące generują zdarzenia keydown i keyup (jak pokazują późniejsze przykłady). Niektóre modyfikatory są aktywowane poprzez wciśnięcie przycisku w dół lub poprzez stałe ich przytrzymywanie, jak w przypadku 'Alt', 'Control', 'Shift', 'AltGraph' czy 'Meta'. Inne modyfikatory są aktywowane w zależności od ich stanu, jak w przypadku 'CapsLock', 'NumLock' czy 'ScrollLock'. Zmiana stanu odbywa się poprzez wciśnięcie klawisza w dół. Interfejs KeyboardEvent zapewnia dedykowane właściwości dla najpopularniejszych modyfikatorów: KeyboardEvent.altKey, KeyboardEvent.ctrlKey, KeyboardEvent.metaKey i KeyboardEvent.shiftKey, choć najbardziej uniwersalna będzie metoda KeyboardEvent.getModifierState(). Niektóre systemy operacyjne symulują klawisz modyfikujący 'AltGraph' poprzez kombinację klawiszy modyfikujących 'Alt' i 'Control'. Implementacje są zachęcane do korzystania z klawisza modyfikującego 'AltGraph'.

Poniższy przykład opisuje możliwą sekwencję zdarzeń skojarzoną z wygenerowaniem znaku Latin Capital Letter Q (U+0051) na klawiaturze US z użyciem mapowania US:

Nazwa zdarzenia.key.dataModyfikatorUwagi
1.keydown'Shift'shiftKey
2.keydown'Q'shiftKeyLatin Capital Letter Q
3.beforeinput\u0051
4.input
5.keyup'Q'shiftKey
6.keyup'Shift'

Poniższy przykład opisuje alternatywną sekwencję klawiszy do wcześniejszego przykładu, gdzie klawisz 'Shift' jest zwalniany przed klawiszem 'Q'. Wartość klawisza dla klawisza z etykietą 'Q' przy zdarzeniu keyup powróci do małej wartości:

Nazwa zdarzenia.key.dataModyfikatorUwagi
1.keydown'Shift'shiftKey
2.keydown'Q'shiftKeyLatin Capital Letter Q
3.beforeinput\u0051
4.input
5.keyup'Shift'
6.keyup'q'Latin Small Letter Q

Poniższy przykład opisuje możliwą sekwencję klawiszy, która nie generuje znaków Unicode (przy użyciu tej samej konfiguracji):

Nazwa zdarzenia.keyModyfikatorUwagi
1.keydown'Control'ctrlKey
2.keydown'v'ctrlKeyLatin Small Letter V
Zdarzenia beforeinput i input nie zostają wygenerowane.
3.keyup'v'ctrlKeyLatin Small Letter V
4.keyup'Control'

Poniższy przykład pokazuje sekwencję zdarzeń, kiedy zarówno 'Shift' jak i 'Control' są wciskane:

Nazwa zdarzenia.keyModyfikatorUwagi
1.keydown'Control'ctrlKey
2.keydown'Shift'ctrlKey, shiftKey
3.keydown'V'ctrlKey, shiftKeyLatin Capital Letter V
Zdarzenia beforeinput i input nie zostają wygenerowane.
4.keyup'V'ctrlKey, shiftKeyLatin Capital Letter V
5.keyup'Shift'ctrlKey
6.keyup'Control'

Dla klawiatur z innymi układami niż US sekwencje zdarzeń są takie same, ale wartości klawiszy bazują na bieżącym układzie klawiatury. Poniższy przykład pokazuje sekwencję zdarzeń dla klawiatury z układem Arabic:

Nazwa zdarzenia.keyModyfikatorUwagi
1.keydown'Control'ctrlKey
2.keydown'ر'ctrlKeyArabic Letter Reh
Zdarzenia beforeinput i input nie zostają wygenerowane.
3.keyup'ر'ctrlKeyArabic Letter Reh
4.keyup'Control'

Wartość klawisza w zdarzeniach keydown i keyup zmienia się w zależności od aktualnego układu klawiatury. Oznacza to, że klawisz 'v' na klawiaturze z układem US i klawisz 'ر' na klawiaturze z układem Arabic wygeneruje różne zdarzenia, mimo że są one tymi samymi fizycznymi klawiszami. Aby zidentyfikować te zdarzenia w kontekście pochodzenia od tego samego fizycznego klawisza należy skorzystać z właściwości KeyboardEvent.code.

W niektórych przypadkach klawisze modyfikujące zmieniają funkcjonalność innych klawiszy. Dla przykładu, w niektórych klawiaturach MacOS klawisz z etykietą 'delete' działa w systemie operacyjnym Windows identycznie jak klawisz 'Backspace' bez modyfikacji, ale przy modyfikacji za pomocą klawisza 'Fn' działa identycznie jak klawisz 'Delete', i wartość we właściwości KeyboardEvent.key będzie dopasowana do najwłaściwszej funkcji klawisza w obecnie zmodyfikowanym stanie.

Martwe klawisze#

Niektóre klawiatury stosują martwe klawisze do wprowadzenia złożonych sekwencji znaków. W przeciwieństwie do klasycznych sekwencji pisma ręcznego klawiatura wymaga, aby wprowadzić specjalny stan, w którym martwy klawisz jest wciśnięty i emituje znak/znaki tylko wtedy, kiedy jedna z ograniczonej ilości "legalnych" bazowych znaków zostanie wprowadzona.

Systemy operacyjne MacOS i Linux używają metod wejściowych do przetwarzania martwych klawiszy.

Martwe klawisze (we wszystkich układach klawiatur i mapowaniach) są reprezentowane przez wartość klawisza 'Dead'. W odpowiedzi na wciśnięcie któregokolwiek martwego klawisza aplikacja kliencka musi wysłać zdarzenia kompozycji, gdzie wartością właściwości CompositionEvent.data dla zdarzenia compositionupdate musi być wartość znakowa obecnego stanu łączonej sekwencji martwego klawisza.

Chociaż łączenie znaków Unicode zawsze podąża zgodnie z sekwencją pisma ręcznego, z łączącym znakiem występującym za odpowiadającą literą, to martwe wejście może odwrócić tę sekwencję, z łączącym znakiem występującym przed odpowiadającą literą. Dla przykładu, wyraz naïve używa łączącego diakrytyka ¨, i w Unicode będzie reprezentowany w sekwencji nai¨ve, ale przy martwym wejściu może być wpisany w sekwencji na¨ive.

Sekwencja wciśnięcia klawiszy COMBINING CIRCUMFLEX ACCENT (U+0302) i Latin Small Letter E (U+0065) najprawdopodobniej wyprodukuje (na francuskiej klawiaturze z francuskim mapowaniem i bez żadnego aktywnego modyfikatora) znak 'ê' (Latin Small Letter E With Circumflex) zgodnie z dokumentem "Unicode Normalization Forms":

Nazwa zdarzenia.key.isComposing.dataUwagi
1.keydown'Dead'falseCombining Circumflex Accent
2.compositionstart''
3.compositionupdate'\u0302'
4.keyup'Dead'true
5.keydown'ê'true
6.compositionupdate'ê'
7.compositionend'ê'
8.keyup'e'falseLatin Small Letter E

Zdarzenia keydown i keyup w trakcie sesji kompozycji prawdopodobnie zostałyby stłumione, ale ze względu na lepsze uwidocznienia działań użytkownika pozostawiono je w powyższym przykładzie.

Warto podkreślić, że w drugim zdarzeniu keydown (krok 5) wartość klawisza (przy założeniu braku tłumienia) nie będzie równa 'e' (Latin Small Letter E) ponieważ wartość dostarczana do aplikacji klienckiej będzie modyfikowana przez operacje martwego klawisza.

Proces ten może zostać przerwany w chwili, kiedy użytkownik wpisze nieobsługiwany bazowy znak (tj. bazowy znak, dla którego aktywny znak diakrytyczny nie jest dostępny) po naciśnięciu martwego klawisza:

Nazwa zdarzenia.key.isComposing.dataUwagi
1.keydown'Dead'falseCombining Circumflex Accent
2.compositionstart''
3.compositionupdate'\u0302'
4.keyup'Dead'true
5.keydown'q'trueLatin Small Letter Q
6.compositionupdate''
7.compositionend''
8.keyup'q'falseLatin Small Letter Q
Edytory metod wejściowych#

Specyfikacja D3E wprowadza model dla edytorów metod wejściowych poprzez interfejs CompositionEvent i dedykowane zdarzenia kompozycji. Jednakże zdarzenia kompozycji i zdarzenia klawiatury niekoniecznie muszą być mapowane w relacji jeden do jednego. Dla przykładu, otrzymanie zdarzenia keydown dla wartości klawisza Accept nie musi wcale oznaczać, że aktualnie wybrany tekst w IME jest akceptowany, lecz wskazuje jedynie, że wystąpiło wciśnięcie klawisza, w oderwaniu od funkcjonalności akceptowania IME (która normalnie generuje zdarzenie compositionend w większości systemów IME). Zdarzenia klawiatury nie mogą być używane do określenia aktualnego stanu edytora metody wejściowej, ale można to uzyskać poprzez właściwość CompositionEvent.data. W dodatku systemy IME i urządzenia różnią się pod względem funkcjonalności, a nawet tym, które klawisze służą do aktywacji konkretnej funkcji, jak chociażby klawisze 'Convert' i 'Accept' mogą być reprezentowane przez inne dostępne klawisze. Zdarzenia klawiatury odpowiadają zdarzeniom generowanym przez urządzenia wejściowe dopiero po mapowaniu układu klawiatury.

W niektórych implementacjach lub systemach konfiguracji część zdarzeń klawiatury (lub ich wartość) mogą być tłumione ze względu na stosowanie narzędzia IME.

Poniższy przykład opisuje możliwą sekwencję klawiszy dla wygenerowania znaku '市' (znak Kanji, część CJK Unified Ideographs) przy użyciu japońskiego IME. Zakłada się, że edytor metody wejściowej jest aktywny z ustawionym trybem wejściowym Japanese-Romaji. Klawisze 'Convert' i 'Accept' mogą być zastępowane innymi, w zależności od urządzenia wejściowego i konfiguracji IME, np. odpowiednio klawiszami '\u0020' (spacja) lub 'Enter':

Nazwa zdarzenia.key.isComposing.dataUwagi
1.keydown's'falseLatin Small Letter S
2.compositionstart''
3.compositionupdate's'
4.keyup's'true
5.keydown'i'trueLatin Small Letter I
6.compositionupdate'し'
7.keyup'i'true
8.keydown'Convert'trueConvert
9.compositionupdate'詩'
10.keyup'Convert'true
11.keydown'Convert'trueConvert
12.compositionupdate'市'
13.keyup'Convert'true
14.keydown'Accept'trueAccept
15.compositionend'市'
16.keyup'Accept'false

Kompozycję IME można przerwać jak w poniższym przykładzie (przy założeniu identycznych warunków jak w poprzednim przykładzie). Klawisz 'Cancel' może być zastępowany innym, w zależności od urządzenia wejściowego i konfiguracji IME, np. klawiszem '\u001B' (Escape):

Nazwa zdarzenia.key.isComposing.dataUwagi
1.keydown's'falseLatin Small Letter S
2.compositionstart''
3.compositionupdate's'
4.keyup's'true
5.keydown'i'trueLatin Small Letter I
6.compositionupdate'し'
7.keyup'i'true
8.keydown'Convert'trueConvert
9.compositionupdate'詩'
10.keyup'Convert'true
11.keydown'Convert'trueConvert
12.compositionupdate'市'
13.keyup'Convert'true
14.keydown'Cancel'trueCancel
15.compositionupdate''
16.compositionend''
17.keyup'Cancel'false

Niektóre edytory metod wejściowych (np. w systemie operacyjnym MacOS) przed anulowaniem kompozycji mogą ustawiać pusty łańcuch znakowy we właściwości CompositionEvent.data.

Tryby klawiszy edytora metody wejściowej#

Niektóre klawisze w pewnych urządzeniach zostały przewidziane do aktywacji funkcji edytora metody wejściowej lub zmiany trybu aktywności edytora metody wejściowej. Własne klawisze dla tego celu mogą być definiowane dla różnych urządzeń lub trybów językowych. Specyfikacja D3E definiuje następujące klawisze: Alphanumeric, CodeInput, FinalMode, HangulMode, HanjaMode, Hiragana, JunjaMode, KanaMode, KanjiMode, Katakana oraz RomanCharacters. Gdy jeden z tych klawiszy zostanie wciśnięty przy nieaktywności żadnego IME to oczekuje się, że odpowiedni IME zostanie uaktywniony w trybie wskazywanym przez klawisz (jeśli jest dostępny). Jeśli IME był aktywny w chwili przyciśnięcia klawisza to aktywny IME może przejść do wskazywanego trybu, lub inny IME może zostać uruchomiony, lub może to zostać zignorowane, w zależności od specyfiki urządzenia i aplikacji.

Specyfikacja D3E definiuje również inne klawisze, które przewidziano dla specyficznych operacji w edytorach metod wejściowych: Accept, AllCandidates, Cancel, Convert, Compose, FullWidth, HalfWidth, NextCandidate, Nonconvert i PreviousCandidate.

Domyślne akcje i anulowanie zdarzeń klawiatury#

Anulowanie domyślnej akcji dla zdarzenia keydown nie może wpływać na odpowiadające zdarzenie keyup, ale musi zapobiec wygenerowaniu odpowiadających zdarzeń beforeinput i input (a także keypress jeśli wspierane). Poniższy przykład opisuje możliwą sekwencję zdarzeń skojarzoną z wygenerowaniem znaku Latin Capital Letter Q (U+0051) na klawiaturze US z użyciem mapowania US:

Nazwa zdarzenia.key.dataModyfikatorUwagi
1.keydown'Shift'shiftKey
2.keydown'Q'shiftKeyPrzerywamy domyślną akcję, np. metodą Event.preventDefault().
Zdarzenia beforeinput i input (a także keypress jeśli wspierane) nie zostają wygenerowane.
3.keyup'Q'shiftKey
4.keyup'Shift'

Jeśli klawisz jest klawiszem modyfikującym to wciśnięcia klawisza muszą być ciągle uwzględnianie dla stanów modyfikatorów. Poniższy przykład opisuje możliwą sekwencję zdarzeń skojarzoną z wygenerowaniem znaku Latin Capital Letter Q (U+0051) na klawiaturze US z użyciem mapowania US:

Nazwa zdarzenia.key.dataModyfikatorUwagi
1.keydown'Shift'shiftKeyPrzerywamy domyślną akcję, np. metodą Event.preventDefault().
2.keydown'Q'shiftKey
3.beforeinput'Q'
4.input
5.keyup'Q'shiftKey
6.keyup'Shift'

Jeśli klawisz jest częścią sekwencji kilku wciśnięć, co może mieć miejsce dla martwego klawisza lub dotyczyć sekwencji w edytorze metody wejściowej, to wciśnięcia muszą zostać zignorowane tylko w sytuacji, kiedy domyślna akcja zostanie anulowana na zdarzeniu keydown. Anulowanie martwego klawisza na zdarzeniu keyup nie ma wpływu na zdarzenia beforeinput i input. Poniższy przykład prezentuje sekwencję wciśnięcia martwego klawisza 'Dead' (COMBINING CIRCUMFLEX ACCENT, U+0302)) i 'e' (Latin Small Letter E, U+0065) na francuskiej klawiaturze z francuskim mapowaniem i bez żadnego aktywnego modyfikatora:

Nazwa zdarzenia.key.dataUwagi
1.keydown'Dead'Przerywamy domyślną akcję, np. metodą Event.preventDefault().
2.keyup'Dead'
3.keydown'e'
4.beforeinput'e'
5.input
6.keyup'e'
Wytyczne dla wyboru wartości klawiszy#

Poniższy algorytm określa przeznaczoną do użycia wartość klawisza key value oraz wartość znaku char value:

  1. Jeśli istnieje odpowiednia wartość klawisza w zestawie wartości klawiszy to właściwość KeyboardEvent.key musi być łańcuchem znakowym składającym się z key value tego znaku.
  2. Jeśli klawisz generuje drukowany znak i istnieje odpowiedni kod znaku Unicode, to właściwość KeyboardEvent.key musi być łańcuchem znakowym składającym się z char value tego znaku.
  3. Jeśli więcej niż jeden klawisz został wciśnięty i kombinacja klawiszy zawiera jeden lub więcej klawiszy modyfikujących, które w rezultacie nie produkują drukowanego znaku (np. 'Control' + 'a'), to key value powinna wskazywać na drukowaną wartość klawisza, która zostałaby wyprodukowana jeśli klawisz zostałby wciśnięty z domyślnym układem klawiatury bez klawiszy modyfikujących, z wyjątkiem 'Shift' i 'AltGr'.
  4. W przeciwnym razie należy zastosować specjalną wartość 'Unidentified'.

Oto kilka praktycznych przełożeń:

Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

Zdarzenia (H1) Klawiatura (H2) Oznaczenia dla wartości klawiszy i znaków (H3) Kolejność zdarzeń wejścia (H3) Zdarzenia klawiatury i wartości klawiszy (H3) Wejście klawiaturowe (H4) Etykiety klawiszy (H5) Kody klawiszy (H4) Motywacja dla wprowadzenia właściwości code (H5) Różnice między właściwościami key i code (H5) Właściwość code i klawiatury wirtualne (H5) Wartości klawiszy (H4) Wartości klawiszy i Unicode (H5) Klawisze modyfikujące (H5) Martwe klawisze (H5) Edytory metod wejściowych (H5) Tryby klawiszy edytora metody wejściowej (H6) Domyślne akcje i anulowanie zdarzeń klawiatury (H5) Wytyczne dla wyboru wartości klawiszy (H5)