Michael: JavaScript: Erkennen von aktivem "Caps Lock" bei gedrückten Ziffern-Tasten

Hallo, folgendes Problem:

In einer relativ komplexen Webanwendung (sonst alles schon fertig, es geht nur noch um partielle Verbesserungen und alles mal schnell umbauen kommt da nicht in Frage, wenn, dann auf Basis einzelner Event-Handler-Funktionen) sollen in Formular-Eingabefeldern, in denen numerische Werte erwartet werden, neben paar wenigen Ausnahmen wie Backspace und Delete ansonsten nur Ziffern eingegeben werden können.

Nun sieht es danach aus, dass u.a. auf deutschen Tastaturen bei aktivem Caps Lock zwar die Sonderzeichen statt der Ziffern eingefügt werden, sich der aktive Caps Lock aber (in diesem Fall) auch nicht so ohne Weiteres abfragen lässt. Obwohl von den im JavaScript-Code empfangenen Werten her also alles aussieht, als ob eine Ziffer gedrückt worden wäre, erscheint im Eingabefeld eben doch das Sonderzeichen, was dort eben nicht reinsoll. (Serverseitige Validierung findet auch noch statt, aber abgesehen davon soll der User vorher schon unmittelbar merken, was erlaubt ist und was nicht, bevor so ein Formular zig mal auf dem Server verarbeitet werden muss.)


Eingabefeld:


<input type="text" onkeydown="return onlyNumbers( event )">


Die Funktion onlyNumbers( ... ):


function onlyNumbers(evt, decimalseparator) {
    if ((evt.type) && (evt.type != 'keydown') && (evt.type != 'keypress')) {
        alert('please implement this function on event "onkeydown" only! In this case the event "' + evt.type + '" was triggered.');
    }
    var keyCode = evt.keyCode;
    var shiftKeyPressed = evt.shiftKey;
    var ctrlKeyPressed = evt.ctrlKey;

    if (keyCode === 8 || keyCode === 9 || keyCode === 13 || keyCode === 17 || keyCode === 27 || (ctrlKeyPressed && keyCode === 86) || (!shiftKeyPressed && keyCode >= 48 && keyCode <= 57) || (keyCode == 46) || (keyCode >= 35 && keyCode <= 40) || (keyCode >= 96 && keyCode <= 105))
        return true;
    var charCode = evt.charCode;

    if (typeof decimalseparator !== 'undefined')
    { // point (.) is always allowed charCode=46
        if (keyCode === 190)
            return true; // || charCode == decimalseparator.charCodeAt(0) || (charCode >= 48 && charCode <= 57);
    }

    return false;
}

Hat jemand irgendwann schon mal eine Lösung gefunden, wie man in JavaScript (nativ oder auch durch Dazuhängen einer kleinen Bibliothek) abfragen kann, ob bei Drücken einer Ziffer aus der Ziffern-Reihe über dem Buchstaben-Block der Caps Lock aktiv ist?

Bisher ist in der Anwendung noch alles in XHTML geschrieben. HTML5-Attribute wie

text="number"

kommen eher nicht als Lösung in Frage...

Gruß Michael

  1. Hi,

    Nun sieht es danach aus, dass u.a. auf deutschen Tastaturen bei aktivem Caps Lock zwar die Sonderzeichen statt der Ziffern eingefügt werden, sich der aktive Caps Lock aber (in diesem Fall) auch nicht so ohne Weiteres abfragen lässt.

    mal vorab gefragt: Wie wahrscheinlich ist es, dass Caps Lock aktiv ist? Wie oft kommt das vor? Ich habe noch nicht oft erlebt, dass jemand das wirklich nutzt - vor allem wegen der Fehlinterpretation der meisten deutschen Tastaturtreiber, die das als Shift Lock implementieren anstatt tatsächlich als Caps Lock, das eigentlich nur auf Buchstabentasten wirken sollte. Insofern habe ich den Eindruck, du versuchst da ein Problem zu lösen, das in freier Wildbahn so gut wie nie auftritt.

    Obwohl von den im JavaScript-Code empfangenen Werten her also alles aussieht, als ob eine Ziffer gedrückt worden wäre, erscheint im Eingabefeld eben doch das Sonderzeichen, was dort eben nicht reinsoll.

    Ja, das ist klar soweit.

    
    > <input type="text" onkeydown="return onlyNumbers( event )">
    
    

    Ich würde mal sagen, du hängst dich ans falsche Event. Meines Wissens erfolgt die eigentliche Verarbeitung des Tastendrucks im Zusammenhang mit dem keypress-Event, nicht keydown. Siehe hierzu auch weiterführende Lektüre:
    https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent

        if (keyCode === 8 || keyCode === 9 || keyCode === 13 || keyCode === 17 || keyCode === 27 || (ctrlKeyPressed && keyCode === 86) || (!shiftKeyPressed && keyCode >= 48 && keyCode <= 57) || (keyCode == 46) || (keyCode >= 35 && keyCode <= 40) || (keyCode >= 96 && keyCode <= 105))
            return true;
    

    Das kann man auch etwas übersichtlicher schreiben.

        if (typeof decimalseparator !== 'undefined')
        { // point (.) is always allowed charCode=46
            if (keyCode === 190)
                return true; // || charCode == decimalseparator.charCodeAt(0) || (charCode >= 48 && charCode <= 57);
        }
    

    Was isser denn nun, der Dezimalpunkt? 46 (U+002E) oder 190 (U+00BE)? Letzteres ist doch Käse, oder?

    So long,
     Martin

    1. Hallo Der Martin,

      vor allem wegen der Fehlinterpretation der meisten deutschen Tastaturtreiber, die das als Shift Lock implementieren anstatt tatsächlich als Caps Lock, das eigentlich nur auf Buchstabentasten wirken sollte.

      Unter Windows gab (gibt es bestimmt immer noch) unterschiedliche TastaturLayouts. deutsch (EDV) heißt das für Caps Lock statt Shift Lock.

      Bis demnächst
      Matthias

      --
      Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
      1. Hi,

        vor allem wegen der Fehlinterpretation der meisten deutschen Tastaturtreiber, die das als Shift Lock implementieren anstatt tatsächlich als Caps Lock, das eigentlich nur auf Buchstabentasten wirken sollte.

        Unter Windows gab (gibt es bestimmt immer noch) unterschiedliche TastaturLayouts. deutsch (EDV) heißt das für Caps Lock statt Shift Lock.

        stimmt, ich entsinne mich dunkel. AFAIR hatte ich das auf meinen Windows-PCs sogar meistens so eingestellt, obwohl auch ich die Caps-Lock-Funktion selten genutzt habe.

        So long,
         Martin

        1. Hallo Der Martin,

          AFAIR hatte ich das auf meinen Windows-PCs sogar meistens so eingestellt,

          ich auch.

          obwohl auch ich die Caps-Lock-Funktion selten genutzt habe.

          Bei meinem letzten Windows7 hatte ich die Taste deaktiviert. (Chip.de)

          Bis demnächst
          Matthias

          --
          Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
          1. Hallo Matthias Apsel,

            Bei meinem letzten Windows7 hatte ich die Taste deaktiviert. (Chip.de)

            Geht auch bei Windows 10.

            Bis demnächst
            Matthias

            --
            Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
          2. Tach,

            Bei meinem letzten Windows7 hatte ich die Taste deaktiviert. (Chip.de)

            besser eine sinnvolle Funktion drauf legen, z.B. ComposeKey, kann man auch für Windows nachrüsten https://github.com/samhocevar/wincompose.

            mfg
            Woodfighter

  2. Hallo Michael,

    warum prüfst du die Eingabe nicht einfach mit isNaN und ersetzt den Dezimaltrenner durch einen Punkt?

    Gruß Jürgen

  3. Bisher ist in der Anwendung noch alles in XHTML geschrieben. HTML5-Attribute wie

    text="number"
    

    kommen eher nicht als Lösung in Frage...

    Du meinst sicher <input type="number">. Dieses Attribut exisitierte in XHTML noch nicht, aber ist fester Bestandteil von HTML5. Wenn ein Browser dieses Attribut allerdings in einem XHTML-Dokument findet, dann stört ihn das nicht weiter und er wird es trotzdem nach aktuellem Stand der Dinge (lies HTML5) interpretieren. Die einzige Ausnahme wäre, wenn du den Browser explitizit in den strikten, nicht-fehlertoleranten Modus versetzt hast, das darfst du in diesem Fall nicht machen. Das Attribut gibt dir aber gewisse Vorteile, die du nicht anders erzielen kannst:

    • Der Arbeitsaufwand für dich ist geringer
    • Die Formularvalidierung funktioniert auch ohne JavaScript
    • Die Formularvalidierung ist auch für assistive Technologie und andere Peripherie zugänglich
    • Smartphones und andere mobile Geräte können eine spezialisierte virtuelle Tastatur zur Eingabe von Zahlen anbieten

    Wenn du bisher nur strikten XHTML-Code geschrieben hast und ihn nun mit HTML5 mischen musst, tut das nachvollziehbar weh, weil es irgendwie einen unsauberen Anschein hinterlässt. Defakto ist aber jeder Kompromiss den du nur Zugunsten der Reinheit deines XHTML-Codes eingegangen bist und in Zukunft noch eingehen wirst eine unsaubere Vorgehensweise. Mittel- und Langfristig solltest du also gleich zu HTML5 greifen und die Dinosaurier ruhen lassen.

    1. @@1unitedpower

      Wenn du bisher nur strikten XHTML-Code geschrieben hast und ihn nun mit HTML5 mischen musst, tut das nachvollziehbar weh

      Kann ich nicht nachvollziehen.

      Mittel- und Langfristig solltest du also gleich zu HTML5 greifen

      Kurzfristig. Und man kann HTML5 ja auch in der XML-Syntax schreiben.

      LLAP 🖖

      --
      „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
      „Hat auf dem Forum herumgelungert …“
      (Wachen in Asterix 36: Der Papyrus des Cäsar)
      1. Wenn du bisher nur strikten XHTML-Code geschrieben hast und ihn nun mit HTML5 mischen musst, tut das nachvollziehbar weh

        Kann ich nicht nachvollziehen.

        Ich finde solche instiktiven Bauchgefühle sogar sehr natürlich und nützlich wenn man mit formalen Sprachen arbeitet. In diesem Bereich folgen Syntax und Semantik ja für gewöhnlich sehr strengen Regeln, die Fehlertoleranz eines Browsers auszunutzen stellt da insofern eine Divergenz zum sonst üblichen Vorgehen dar.

        Mittel- und Langfristig solltest du also gleich zu HTML5 greifen

        Kurzfristig. Und man kann HTML5 ja auch in der XML-Syntax schreiben.

        Kurz vor einer bevorstehenden Übergabe bestehnde Komponenten von XHTML1.x nach HTML5 zu portieren ist gefährlich, da passieren Fehler. Ich habe meine Worte bewusst gewählt, um den Fragesteller nicht auf dumme Gedanken zu bringen und ins offene Messer rennen zu lassen. So ein Schtritt sollte geplant und im Team besprochen sein, nicht zuletzt da vermutlich auch Integrationstests und Personalschulungen anfallen werden, die vielleicht gar nicht der Verantwortung und des Handlungsspielraums des Fragestellers obliegen.

    2. An sich nachvollziehbar und grundsätzlich zu befürworten, dass bei zukünftigen Vorhaben moderneren Standards der Vorzug gegeben werden sollten, aber diese recht umfangreiche Anwendung, um die es geht, ist eben nicht von mir - kein Privatprojekt - und ich kann da nicht nach Belieben rumbasteln und unsaubere Vermischung von Standards sollte bei größeren Projekten mit professioneller Ausrichtung so weit wie möglich vermieden werden. Bei zukünftigen (Folge-)Projekten würde natürlich auf HTML 5 gesetzt werden.

      [Vollzitat entfernt]