Überprüfen Sie, ob ein Schlüssel nicht verfügbar ist.

91

Gibt es eine Möglichkeit zu erkennen, ob ein Schlüssel derzeit in JavaScript nicht verfügbar ist?

Ich weiß über das "Keydown" -Ereignis Bescheid, aber das brauche ich nicht. Einige Zeit nach dem Drücken der Taste möchte ich feststellen können, ob sie noch gedrückt ist.

PS Das größte Problem scheint zu sein, dass sich der Schlüssel nach einiger Zeit zu wiederholen beginnt und Keydown- und Keyup-Ereignisse wie ein Unhold auslöst. Hoffentlich gibt es nur eine einfache isKeyDown (Schlüsselfunktion), aber wenn nicht, muss dieses Problem behoben / umgangen werden.

Daniel X Moore
quelle
6
Ein häufiges Problem mit den Antworten, die ich hier sehe, ist, dass, wenn Sie eine Taste gedrückt halten, dann die Registerkarten ändern oder den Fokus ändern, die Taste nach oben drücken und dann zurückschalten, der Code glaubt, dass die Taste gedrückt ist, bis Sie sie erneut drücken oder bewegen die Maus über die Seite. :-(
Eric Mickelsen

Antworten:

71

Gibt es eine Möglichkeit zu erkennen, ob ein Schlüssel derzeit in JavaScript nicht verfügbar ist?

Nee. Die einzige Möglichkeit ist die Überwachung jeder keyupund keydownund Erinnerung.

Nach einiger Zeit beginnt sich der Schlüssel zu wiederholen und löst Keydown- und Keyup-Ereignisse wie ein Unhold aus.

Es sollte nicht. Sie werden sich definitiv keypresswiederholen, und in vielen Browsern werden Sie auch wiederholt keydown, aber wenn Sie sich keyupwiederholen, ist es ein Fehler.

Leider ist dies kein völlig unbekannter Fehler: Unter Linux, Chromium und Firefox (wenn es unter GTK + ausgeführt wird, das in beliebten Distributionen wie Ubuntu verwendet wird) werden beide wiederholte Keyup-Keypress-Keydown-Sequenzen für gehaltene Tasten generiert. die unmöglich zu unterscheiden sind von jemandem, der den Schlüssel wirklich schnell hämmert.

Bobince
quelle
14
Sie, mein Herr, sind ein Gentleman und ein Gelehrter. Chromium und Firefox unter Ubuntu sind meine primäre Entwicklungsumgebung, sodass das Problem, das ich gesehen habe, genau erklärt wird. Hoffentlich wird es besser, sonst könnte diese Timer-Hack-Lösung die einzige Problemumgehung sein.
Daniel X Moore
3
Ja, es ist frustrierend, dass diesbezüglich keine Fortschritte erzielt werden. Siehe bugs.launchpad.net/ubuntu/+bug/369880 . Ich schreibe ein Browsergame und meine Problemumgehung besteht im Moment darin, mich an die Modifizierertasten (Umschalt, Strg usw.) zu halten, die sich überhaupt nicht wiederholen.
Bobince
2
Nein, es ist möglich, sie von echten wiederholten Tastendrücken durch das Fehlen entsprechender keyupEreignisse zu unterscheiden.
Mako
4
Ist dies 8 Jahre später noch der Fall? Diese Antwort muss möglicherweise aktualisiert werden.
Marco Lavagnino
3
Parsing-Hilfe: (Linux && (Chromium || (Firefox && GTK +)))
Bobince
133

Neben der Verwendung von keyupund den keydownListenern, um zu verfolgen, wann die Taste herunter und wieder hoch geht, gibt es tatsächlich einige Eigenschaften, die Ihnen mitteilen, ob bestimmte Tasten gedrückt sind.

window.onmousemove = function (e) {
  if (!e) e = window.event;
  if (e.shiftKey) {/*shift is down*/}
  if (e.altKey) {/*alt is down*/}
  if (e.ctrlKey) {/*ctrl is down*/}
  if (e.metaKey) {/*cmd is down*/}
}

Diese sind auf allen Browser erzeugte Ereignisobjekte zur Verfügung, wie sie aus keydown, keyupund keypress, so dass Sie verwenden mousemove- nicht haben.

Ich habe versucht, meine eigenen Ereignisobjekte mit document.createEvent('KeyboardEvent')und zu generieren document.createEvent('KeyboardEvent')und danach zu suchen e.shiftKey, aber ich hatte kein Glück.

Ich verwende Chrome 17 auf dem Mac

Devin G Rhode
quelle
Ich benutze dies sowohl in neuen als auch in alten Browsern, sogar in HTAs
Jakob Sternberg,
1
Gibt es eine Möglichkeit, diese Antwort zu implementieren, wenn eine Nummer derzeit nicht verfügbar ist? Ich habe versucht, mit if (e.keyCode == 49) {console.log ("1 ist unten");} aber funktioniert nicht :(
Roberto Sepúlveda Bravo
Hey @ RobertoSepúlvedaBravo Robert scheint Ihre Frage bei der nächsten Antwort zu beantworten. ;)
Mark Odey
Eigentlich sollten Sie beim Keyup nicht nach e.shiftKey suchen, wenn Sie Shift meinen. Verwenden Sie stattdessen e.shiftKey, z. B. onclick.
Maciek
45

Meine Lösung:

var pressedKeys = {};
window.onkeyup = function(e) { pressedKeys[e.keyCode] = false; }
window.onkeydown = function(e) { pressedKeys[e.keyCode] = true; }

Ich kann jetzt überprüfen, ob irgendwo im Skript eine Taste gedrückt wurde, indem ich überprüfe

pressedKeys["code of the key"]

Wenn es wahr ist, wird die Taste gedrückt.

Robert
quelle
2
Da Tasten bereits eine Funktion sind, ist möglicherweise ein anderer Variablenname besser.
Rabe
1
Dies funktioniert nicht, um zu erkennen, ob die Alt-Taste gedrückt ist oder nicht.
Michael
1
Dies ist
Jonathan Spiller
11

Ich glaube nicht, dass es so etwas wie eine isKeyDown-Funktion gibt, aber Sie könnten Ihre eigene schreiben.

Erstellen Sie grundsätzlich ein Array, dessen Länge der Anzahl der zu überwachenden Schlüssel entspricht. Aktualisieren Sie dann mithilfe der Dokumente / Seiten / Steuerelemente keyUp und keyDown das Array mit dem Status dieses Schlüssels.

Schreiben Sie dann eine Funktion, die prüft, ob eine bestimmte Taste gedrückt ist, und einen Bool zurückgibt.

var keyEnum = { W_Key:0, A_Key:1, S_Key:2, D_Key:3 };
var keyArray = new Array(4);

function onKeyDown()
{
    // Detect which key was pressed
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = true;
    // Repeat for each key you care about...
}

function onKeyUp()
{
    // Detect which key was released
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = false;
    // Repeat for each key you care about...
}

function isKeyDown(key)
{
    return keyArray[key];
}

Das sollte erreichen, was Sie wollen.

FallenAvatar
quelle
1
Dies ist gut und in der Tat Teil der Lösung, aber es behebt nicht den Keyup-Wiederholungsfehler, den ich erleide. Siehe Bobince's Antwort.
Daniel X Moore
4
Dies ist keine gute Lösung, da Sie immer mehr Wenns schreiben würden. Eine "keyList = {};" als Objekt akzeptiert "keyList [key] = true;" ohne die Notwendigkeit einer Aufzählung oder Begrenzung, da es Zeichenfolgenindizes / -eigenschaften verwendet und für alle Schlüssel funktioniert.
SparK
5

Ich bin hier gelandet, um zu überprüfen, ob bereits etwas im Browser integriert ist, aber es scheint, dass dies nicht der Fall ist. Dies ist meine Lösung (sehr ähnlich zu Roberts Antwort):

"use strict";

const is_key_down = (() => {
    const state = {};

    window.addEventListener('keyup', (e) => state[e.key] = false);
    window.addEventListener('keydown', (e) => state[e.key] = true);

    return (key) => state.hasOwnProperty(key) && state[key] || false;
})();

Sie können dann überprüfen, ob eine Taste mit gedrückt wurde is_key_down('ArrowLeft').

antonagestam
quelle
1

Andere Leute haben diese Art von Frage schon einmal gestellt (obwohl ich hier momentan keine offensichtlichen Betrüger sehe).

Ich denke, die Antwort ist, dass das keydownEreignis (und sein Zwilling keyup) alle Informationen sind, die Sie erhalten. Das Wiederholen ist ziemlich fest mit dem Betriebssystem verbunden, und ein Anwendungsprogramm hat kaum die Möglichkeit, das BIOS nach dem tatsächlichen Status des Schlüssels abzufragen.

Was Sie tun können und müssen, wenn Sie dies zum Laufen bringen müssen, ist das programmgesteuerte Abprallen des Schlüssels. Im Wesentlichen können Sie bewerten keydownund keyupsich selbst , sondern eine ignorieren keyupEreignis , wenn es Platz zu schnell nach dem letzten nimmt keydown... oder im Wesentlichen, sollten Sie Ihre Antwort verzögern keyuplange genug um sicher zu sein , gibt es kein anderes ist keydownEreignis mit etwas folgenden wie 0,25 Sekunden von der keyup.

Dies würde die Verwendung einer Zeitgeberaktivität und die Aufzeichnung der Millisekundenzeiten für frühere Ereignisse umfassen. Ich kann nicht sagen, dass es eine sehr ansprechende Lösung ist, aber ...

Carl Smotricz
quelle
2
Ich hatte Angst, dass es dazu kommen könnte.
Daniel X Moore
1
/*
Tracks what keys are currently down on the keyboard
*/

function keyboard_module(onUpdate){
    var kb = {};
    var unicode_mapping = {};
    document.onkeydown = function(e){
        var unicode=e.charCode? e.charCode : e.keyCode
        var key = getKey(unicode);
        kb[key] = true;
        if(onUpdate){
            onUpdate(kb);
        }
    }

    document.onkeyup = function(e){
        var unicode=e.charCode? e.charCode : e.keyCode
        var key = getKey(unicode);
        delete kb[key];
        if(onUpdate){
            onUpdate(kb);
        }
    }

    function getKey(unicode){
        if(unicode_mapping[unicode]){
            var key = unicode_mapping[unicode];
        }else{
            var key= unicode_mapping[unicode] = String.fromCharCode(unicode);
        }
        return key;
    }
    return kb;
}

function testing(kb){
    console.log('These are the down keys', kb);
}


var keyboard = keyboard_module(testing);

....
//somewhere else in the code
if(keyboard['K']){/*do something special */}
RobKohr
quelle
Nicht sicher, ob String.fromCharCode (Unicode); ist eine schnelle Suche oder nicht, deshalb habe ich unicode_mapping Objekt. Wenn Sie ultraschnell sind, müssen Sie möglicherweise etwas herausziehen, um diesen Code ein wenig zu reduzieren. Da dies bei Key-Downs wiederholt aufgerufen wird, ist die Geschwindigkeit wichtig, weshalb ich das Mapping pessimistisch hinzugefügt habe.
RobKohr
1

Der folgende Code ist was ich benutze:

var altKeyDownCount = 0;
window.onkeydown = function (e) {
    if (!e) e = window.event;
    if (e.altKey) {
        altKeyDownCount++;
        if (30 < altKeyDownCount) {
            $('.key').removeClass('hidden');
            altKeyDownCount = 0;
        }
        return false;
    }
}

window.onkeyup = function (e) {
    if (!e) e = window.event;
    altKeyDownCount = 0;
    $('.key').addClass('hidden');
}

Wenn der Benutzer die Alt-Taste einige Zeit (ca. 2 Sekunden) gedrückt hält, wird eine Gruppe von Beschriftungen (class = 'key hidden') angezeigt. Wenn Sie die Alt-Taste loslassen, verschwinden die Beschriftungen. jQuery und Bootstrap werden beide verwendet.

Johnny
quelle
und was passiert, wenn "Tab" gedrückt wird, während Alt gedrückt ist?
Michael
1

Ich weiß, dass dies eine sehr alte Frage ist, aber es gibt eine sehr leichte (~ 0,5 KB) JavaScript-Bibliothek, die das inkonsistente Auslösen von Tastaturereignishandlern bei Verwendung der DOM-API effektiv "patcht".

Die Bibliothek ist Keydrown .

Hier ist das operative Codebeispiel, das für meine Zwecke gut funktioniert hat, indem nur die Taste geändert wurde, auf der der Listener eingestellt werden soll:

kd.P.down(function () {
  console.log('The "P" key is being held down!');
});

kd.P.up(function () {
  console.clear();
});

// This update loop is the heartbeat of Keydrown
kd.run(function () {
  kd.tick();
});

Ich habe Keydrown in mein clientseitiges JavaScript integriert, um eine korrekte Pausenanimation in einem Rotlicht-Grünlicht-Spiel zu erhalten, das ich schreibe. Sie können das gesamte Spiel hier ansehen . (Hinweis: Wenn Sie dies in Zukunft lesen, sollte das Spiel vollständig und spielbar sein :-D!)

Ich hoffe das hilft.

Buildpax
quelle
1

Ich habe die obigen Antworten gescannt und der vorgeschlagene keydown/ keyupAnsatz funktioniert nur unter besonderen Umständen. Wenn der Benutzer die Alt-Tabs entfernt oder eine neue Geste verwendet, um ein neues Browserfenster oder einen neuen Tab zu öffnen, keydownwird a registriert. Dies ist in Ordnung, da zu diesem Zeitpunkt nicht erkennbar ist, ob der Schlüssel von der Web-App überwacht wird , oder ist eine Standardbrowser- oder Betriebssystemverknüpfung. Wenn Sie zur Browserseite zurückkehren, wird der Schlüssel immer noch gehalten, obwohl er in der Zwischenzeit freigegeben wurde. Oder eine Taste wird einfach gedrückt gehalten, während der Benutzer mit der Maus zu einem anderen Tab oder einer anderen Anwendung wechselt und diese dann außerhalb unserer Seite loslässt.

Modifizierertasten ( Shiftusw.) können über mousemoveusw. überwacht werden, vorausgesetzt, dass beim Zurückschieben mindestens eine Mausinteraktion erwartet wird, was häufig der Fall ist.

Für die meisten alle anderen Tasten ( mit Ausnahme von Modifikatoren Tab, Deleteaber einschließlich Space, Enter), die Überwachung keypressfür die meisten Anwendungen funktionieren würde - statt ein Schlüssel zum Feuer wird weiterhin nach unten. Aufgrund der Periodizität des keypressFeuers tritt jedoch eine gewisse Latenz beim Zurücksetzen des Schlüssels auf . Wenn keypressnicht weiter geschossen wird, können die meisten Tasten grundsätzlich ausgeschlossen werden . In Kombination mit den Modifikatoren ist dies ziemlich luftdicht, obwohl ich nicht untersucht habe, was ich mit Tabund tun soll Backspace.

Ich bin mir sicher, dass es da draußen eine Bibliothek gibt, die über diese DOM-Schwäche abstrahiert, oder vielleicht hat sich eine DOM-Standardänderung darum gekümmert, da es sich um eine ziemlich alte Frage handelt.

Robert Monfera
quelle
Tastendruck ist jetzt veraltet. In Chrome scheint es überhaupt nicht zu funktionieren.
eadsjr
0

Schauen Sie sich diese Antwort an und verwenden Sie onkeyupund onkeydown. Hier finden Sie genauere Informationen zu diesen Ereignissen.

Claudiu
quelle
1
Der von Ihnen angegebene Link bezieht sich auf Mausereignisse, bei denen die automatische Wiederholung kein Problem darstellt.
Carl Smotricz
Key-Up und Key-Down werden nicht wiederholt. Tastendruck könnte.
Claudiu
Nun, selbst wenn sie es tun, stellte ich mir so etwas wie die Lösung von TJMonk15 vor und wollte es einfach nicht aufschreiben
Claudiu
1
Der Wortlaut dieser beiden Fragen ist genau der gleiche. Seltsamer Zufall oder etwas mehr?
Mitch Lindgren
2
@Mitch: Wow ... das ist ziemlich unglaublich. Ich weiß nicht, warum jemand zwei Konten erstellen würde, um dieselbe Frage zu stellen. oder wahrscheinlicher, diese Person hat gerade die andere Frage kopiert und für Schlüssel angepasst
Claudiu
0

Dies funktioniert in Firefox und Chrome.

Ich musste eine spezielle HTML-Datei lokal öffnen (durch Drücken von, Enterwenn die Datei im Datei-Explorer unter Windows ausgewählt ist), entweder nur zum Anzeigen der Datei oder zum Bearbeiten in einem speziellen Online-Editor.

Daher wollte ich zwischen diesen beiden Optionen unterscheiden, indem ich die CtrlTaste-gedrückt hielt oder nicht, während ich drückte Enter.

Wie Sie alle aus allen Antworten hier verstanden haben, scheint dies nicht wirklich möglich zu sein, aber hier ist ein Weg, der dieses Verhalten auf eine Weise nachahmt, die für mich akzeptabel war.

So funktioniert das:

Wenn Sie Ctrlbeim Öffnen der Datei die Taste-gedrückt halten, wird im Javascript-Code niemals ein Keydown-Ereignis ausgelöst. Ein Keyup-Ereignis wird jedoch ausgelöst (wenn Sie die Ctrl-Taste endgültig loslassen). Der Code erfasst das.

Der Code deaktiviert auch Schlüsselereignisse (sowohl Keyup als auch Keydown), sobald einer von ihnen auftritt. Wenn Sie Ctrlalso nach dem Öffnen der Datei die Taste- drücken , geschieht nichts.

window.onkeyup = up;
window.onkeydown = down;
function up(e) {
  if (e.key === 'F5') return; // if you want this to work also on reload with F5.

  window.onkeyup = null;
  window.onkeyup = null;
  if (e.key === 'Control') {
    alert('Control key was released. You must have held it down while opening the file, so we will now load the file into the editor.');
  }         
}
function down() {
  window.onkeyup = null;
  window.onkeyup = null;
}
Magnus
quelle
-3
$('#mytextbox').keydown(function (e) {
            if (e.keyCode == 13) {
                if (e.altKey) {
                    alert("alt is pressed");
                }
            }
 });

Wenn Sie Alt + Eingabetaste drücken, wird die Warnung angezeigt.

Mokarom
quelle