Comment détecter si la touche enfoncée produira un caractère dans une zone de texte?

J'ai une zone de texte régulière:

<input type="text"> 

J'utilise jQuery pour gérer les événements liés aux clés:

$("input:text").keydown(function() {
    // keydown code
}).keypress(function() {
    // keypress code
}).keyup(function() {
    // keyup code
});

L'utilisateur se concentre sur une zone de texte et appuie sur différentes touches de son clavier (les habituelles: lettres, chiffres, Maj, RETOUR ARRIÈRE, espace,...). J'ai besoin de détecter lorsque l'utilisateur appuie sur une touche qui va augmenter la longueur de la zone de texte valeur. Par exemple, la touche "A" l'augmentera, la touche "SHIFT" ne l'augmentera pas.

Je me souviens avoir regardé une conférence de PPK où il a mentionné la différence entre les deux. Cela a quelque chose à voir avec l'événement - keydown vs keypress - et peut - être avec les propriétés de l'événement-key, char, keyCode.

mise à Jour!

J'ai besoin de connaître cette information dans les gestionnaires keydown ou keypress. Je ne peux pas attendre que l'événement keyup se produise.

Pourquoi j'ai besoin de cette:

J'ai une zone de texte dont la taille change dynamiquement en fonction de l'entrée de l'utilisateur. Vous pouvez jeter un oeil à ceci Démo: http://vidasp.net/tinydemos/variable-size-text-box.html

Dans la démo, j'ai un gestionnaire keydown et keyup. Le gestionnaire keyup ajuste la taille de la zone de texte en fonction de la valeur d'entrée. Cependant, le gestionnaire keydown définit la taille sur 1 caractère plus grand que la valeur d'entrée. La raison pour laquelle je fais cela est que si Je ne l'ai pas fait, le caractère déborderait en dehors de la zone de texte et seulement lorsque l'utilisateur lâcherait la clé, la zone de texte se développerait. Cela fait un peu bizarre. C'est pourquoi je je dois anticiper le nouveau caractère - j'agrandis la zone de texte sur chaque keydown, ergo, avant que le caractère n'apparaisse dans la zone de texte. Comme vous pouvez le voir dans la démo, cette méthode ressemble beaucoup.

Cependant, le problème est le retour arrière et les touches fléchées - elles développeront également la zone de texte sur keydown, et seulement sur keyup la taille de la zone de texte sera corrigée.

Un travail autour de:

Une solution consisterait à détecter les touches BACKSPACE, SHIFT et fléchées manuellement et agir en fonction de cela:

// keydown handler
function(e) {
    var len = $(this).val().length;
    if (e.keyCode === 37 || e.keyCode === 39 ||
        e.keyCode === 16) { // ARROW LEFT or ARROW RIGHT or SHIFT key
        return;
    } else if (e.keyCode === 8) { // BACKSPACE key
        $(this).attr("size", len <= 1 ? 1 : len - 1);
    } else {
        $(this).attr("size", len === 0 ? 1 : len + 1);
    }
}

Cela fonctionne (et ressemble beaucoup) pour BACKSPACE, Maj, Flèche gauche et flèche droite. Cependant, je voudrais avoir une solution plus robuste.

31
demandé sur Šime Vidas 2010-11-15 00:14:09

8 réponses

Je pense que cela fera le travail, ou si ce n'est pas très proche et n'aura besoin que de modifications mineures. La chose que vous devez vous rappeler est que vous ne pouvez rien dire de manière fiable sur n'importe quel caractère qui peut être tapé dans un événement keydown ou keyup: que tout doit être fait dans un gestionnaire keypress. La ressource définitive pour les événements clés est http://unixpapa.com/js/key.html

Vous devez également considérer les pâtes, que ce code ne gérera pas. Vous devrez avoir un gestionnaire d'événements paste distinct (bien que cet événement ne soit pas pris en charge dans Firefox

function isCharacterKeyPress(evt) {
    if (typeof evt.which == "undefined") {
        // This is IE, which only fires keypress events for printable keys
        return true;
    } else if (typeof evt.which == "number" && evt.which > 0) {
        // In other browsers except old versions of WebKit, evt.which is
        // only greater than zero if the keypress is a printable key.
        // We need to filter out backspace and ctrl/alt/meta key combinations
        return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
    }
    return false;
}

<input type="text" onkeypress="alert(isCharacterKeyPress(event))">
28
répondu Tim Down 2010-11-15 01:17:13

La solution possible que je peux trouver est de vérifier la longueur de la clé dans l'événement.

Par exemple:-

<input type="text" id="testId" onkeyup="keyChecking(event)" />

<script type="text/javascript">
function keyChecking(event) {

    if (event.key.length == 1) {
        alert("key produced character " + event.key);
    } else {
        alert("Key DOES NOT produce character");

        const alphabets = "AZaz09";
        const key = event.key;
        var notEvenASymbol = false;

        for (let i = 0; i < key.length; i++) {
            var charCode = key.charCodeAt(i);
            if ((charCode >= alphabets.charCodeAt(0) && charCode <= alphabets.charCodeAt(1)) ||
                (charCode >= alphabets.charCodeAt(2) && charCode <= alphabets.charCodeAt(3)) ||
                (charCode >= alphabets.charCodeAt(4) && charCode <= alphabets.charCodeAt(5))
            ) {
                notEvenASymbol = true;
                console.log(charCode);
                break;
            }
        }

        if (notEvenASymbol) {
            alert("Key DOES NOT produce even a symbol");
        }
        console.log(event.key);

    }
}    
</script>

Donc, si vous appuyez sur des caractères / Symboles, le event.key contiendra ce caractère et sa longueur sera 1. Si vous appuyez sur la touche de caractère V, puis le event.key aura la valeur V, mais si vous appuyez sur la touche enter puis il contiendra la valeur de Entrer, si vous appuyez sur shift puis Shift et ainsi de suite. Par conséquent, si une clé ne produit pas de caractère, sa longueur sera plus grand que 1.

Mise à Jour

Certaines touches spéciales du clavier produisent un symbole et sa longueur peut être supérieure à 1, alors j'ai modifié le code pour qu'il puisse alerter même si ce n'est pas un symbole. Par exemple: - sa longueur est 2. Certains claviers mobiles ont des touches de raccourci pour de tels symboles.

Une touche non caractère / symbole dans le clavier sera toujours une combinaison d'alphabets, de caractères numériques ou des deux, par exemple: - F2, Maj .

Merci @ Vicky Chijwani pour attirer l'attention sur ce scénario.

9
répondu Visruth 2017-10-19 20:02:48

OK, je pense que je l'ai. La solution est un peu hackish, mais fonctionne vraiment bien.

Sur keydown, faites un setTimeout pour 1 milliseconde, qui appelle une fonction pour vérifier / modifier la longueur de votre boîte de saisie.

Http://jsfiddle.net/rygar/e2wQM/

Cela semble très bien fonctionner, surtout dans quelques endroits où votre version ne fonctionne pas (par exemple backspace, CTRL+V, ou en sélectionnant tout un tas de texte et en appuyant sur delete)

Edit: même setTimeout avec un 0ms le retard semble fonctionner!

4
répondu Jeff 2010-11-15 04:44:28

Vous devez utiliser la propriété keyEventArgs.Clé dans la fonction keydown, cela renverra la valeur numérique qui dépendra du système.

Voici un lien qui contient les différents codes clés pour les différents navigateurs et systèmes d'exploitation:

Http://www.quirksmode.org/js/keys.html

3
répondu mariana soffer 2010-11-14 22:09:04

Voici une solution beaucoup plus simple qui a bien fonctionné pour moi:

if(String.fromCharCode(event.keyCode).match(/(\w|\s)/g)) {
  //pressed key is a char
} else {
  //pressed key is a non-char
  //e.g. 'esc', 'backspace', 'up arrow'
}

Cela ne nécessite pas de sonder un élément DOM (ce qui ajouterait de la latence et de la laideur).

3
répondu MikeX 2017-03-12 09:33:02

Ce n'est peut-être pas la méthode que vous recherchez, mais vous pouvez simplement vérifier la valeur de this.value.length dans votre fonction keydown. La valeur de retour est la longueur du texte dans le champ de saisie avant l'ajout du nouveau caractère. Donc, si vous vérifiez à nouveau la longueur dans la fonction keyup, elle sera plus grande si l'utilisateur appuie sur un caractère, mais la même chose si l'utilisateur appuie sur la touche Maj.

1
répondu Jeff 2010-11-14 21:27:03

Je suppose que vous configurez un compteur sur la longueur d'un champ de saisie, auquel cas vous n'avez pas besoin d'être aussi chic, vous pouvez simplement continuer à assigner la longueur du champ à une variable, et quand l'utilisateur arrive à votre longueur maximale, il suffit d'appuyer sur delete ou backspace comme ceci:

$("input:text").keypress(function() {
var current = $(this).val().length;
if (current >= 130) {
if (e.which != 0 && e.which != 8) {
e.preventDefault();
}
}
}

Vous pouvez également utiliser la variable current pour afficher le compteur, ou faire maxlength - current pour faire un compte à rebours du nombre de caractères restants

1
répondu Liam Bailey 2010-11-14 21:32:23

Votre objectif est de garder la zone de texte plus grande que le texte qui y a été entré.

J'accomplirais cela en prévoyant d'avoir de la place pour deux caractères supplémentaires (Pas un) dans la zone de texte. Alors:

// pseudo-code.... 
old_len = textbox.value.length
keyUp function() {
  var new_len = textbox.value.length
  if (new_len != old_len) {
    old_len = new_len
    textbox.style.size = new_len + 2 // pseudo code.
  }
}

L'avantage est que vous n'avez pas besoin de descendre dans le monde occulte des codes de touche.

1
répondu Larry K 2010-11-15 03:06:49