web-dev-qa-db-fra.com

Comment obtenir le texte d'une zone de texte saisie pendant onKeyPress?

J'essaie d'obtenir le texte dans une zone de texte pendant que l'utilisateur y entre ( jsfiddle playground ):

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

Le code fonctionne sans erreur, sauf que la valeur de la zone input text, pendant onKeyPress est toujours la valeur avant le changement:

enter image description here

Question : Comment obtenir le texte d'une zone de texte pendant onKeyPress?

Bonus Chatter

Il y a trois événements liés à "l'utilisateur est en train de taper" dans le DOM HTML:

  • onKeyDown
  • onKeyPress
  • onKeyUp

Dans Windows , l'ordre des messages WM_Key devient important lorsque l'utilisateur appuie sur une touche et que celle-ci commence à se répéter:

  • WM_KEYDOWN('a') - l'utilisateur a abaissé le A clé
  • WM_CHAR('a') - un caractère a a été reçu de l'utilisateur
  • WM_CHAR('a') - un caractère a a été reçu de l'utilisateur
  • WM_CHAR('a') - un caractère a a été reçu de l'utilisateur
  • WM_CHAR('a') - un caractère a a été reçu de l'utilisateur
  • WM_CHAR('a') - un caractère a a été reçu de l'utilisateur
  • WM_KEYUP('a') - l'utilisateur a relâché le A clé

Cinq caractères apparaîtront dans un contrôle de texte: aaaaa

Le point important étant que vous répondez au message WM_CHAR, celui qui se répète. Sinon, vous manquez des événements quand une touche est enfoncée.

En HTML les choses sont légèrement différentes:

  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyUp

Le code HTML fournit une KeyDown et KeyPress chaque répétition de touche. Et l'événement KeyUp n'est déclenché que lorsque l'utilisateur relâche la clé.

À emporter

  • Je peux répondre à onKeyDown ou onKeyPress, mais les deux sont toujours levés avant la mise à jour du input.value.
  • Je ne peux pas répondre à onKeyUp, car cela ne se produit pas lorsque le texte de la zone de texte change.

Question: Comment obtenir le texte d'une zone de texte pendant onKeyPress?

Lecture bonus

74
Ian Boyd

La gestion de l’événement input est une solution cohérente: il s’agit des éléments pris en charge pour textarea et input dans tous les navigateurs contemporains et se déclenche exactement quand vous en avez besoin:

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

Je réécrirais un peu cela cependant:

function showCurrentValue(event)
{
    const value = event.target.value;
    document.getElementById("lblValue").innerText = value;
}
<input id="edValue" type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="lblValue"></span>
8
YakovL

Rester simple. Utilisez à la fois onKeyPress() et onKeyUp():

<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">

Cela permet d’obtenir la valeur de chaîne la plus récente (après la clé) et de la mettre à jour si l’utilisateur maintient la touche enfoncée.

jsfiddle: http://jsfiddle.net/VDd6C/8/

53
Jonathan M

la valeur de la zone de saisie, pendant onKeyPress est toujours la valeur avant le changement

C'est intentionnel: Cela permet à l'écouteur d'événements d'annuler la frappe.

Si les écouteurs d'événement annule l'événement , la valeur n'est pas mise à jour. Si l'événement n'est pas annulé, la valeur est mise à jour, mais après l'appel de l'écouteur d'événements .

Pour obtenir la valeur après la mise à jour de la valeur du champ, planifiez l'exécution d'une fonction sur la prochaine boucle d'événements. La manière habituelle de faire est d’appeler setTimeout avec un délai d’attente de 0:

$('#field').keyup(function() {
    var $field = $(this);

    // this is the value before the keypress
    var beforeVal = $field.val();

    setTimeout(function() {

        // this is the value after the keypress
        var afterVal = $field.val();
    }, 0);
});

Essayez ici: http://jsfiddle.net/Q57gY/2/

Modifier : certains navigateurs (par exemple, Chrome) ne déclenchent pas d’événements de pression de touche pour le retour arrière; modification de la pression sur la touche pour saisir le code.

19
Arnaud Le Blanc

gardez-le compact.
Chaque fois que vous appuyez sur une touche, la fonction edValueKeyPress() est appelée.
Vous avez également déclaré et initialisé des variables dans cette fonction - ce qui ralentit le processus et nécessite également plus de temps processeur et de mémoire.
Vous pouvez simplement utiliser ce code - dérivé d'une simple substitution.

function edValueKeyPress()
{
    document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}

C'est tout ce que vous voulez, et c'est plus rapide!

5
Wajahath

Aucune des réponses à ce jour n'offre une solution complète. Il y a pas mal de problèmes à résoudre:

  1. Toutes les touches ne sont pas transmises aux gestionnaires keydown et keypress (par exemple, les touches de retour arrière et de suppression sont supprimées par certains navigateurs).
  2. La manipulation de keydown n'est pas une bonne idée. Il y a des situations où une touche enfoncée n'entraîne PAS une pression sur une touche!
  3. Les solutions de style setTimeout() sont retardées sous les navigateurs Web Google Chrome/Blink jusqu'à ce que l'utilisateur cesse de taper.
  4. Les événements de souris et tactiles peuvent être utilisés pour effectuer des actions telles que couper, copier et coller. Ces événements ne déclencheront pas d'événements clavier.
  5. En fonction de la méthode de saisie, le navigateur peut ne pas notifier que l'élément a été modifié avant que l'utilisateur ne quitte le champ.

Une solution plus correcte gérera les événements keypress, keyup, input et change.

Exemple:

<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>

<script>
function UpdateDisplay()
{
    var inputelem = document.getElementById("editvalue");
    var s = inputelem.value;

    var labelelem = document.getElementById("labelvalue");
    labelelem.innerText = s;
}

// Initial update.
UpdateDisplay();

// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>

Violon:

http://jsfiddle.net/VDd6C/2175/

Le traitement des quatre événements intercepte tous les cas Edge. Lors de l'utilisation de la saisie d'un utilisateur, tous les types de méthodes de saisie doivent être pris en compte et la fonctionnalité inter-navigateur et inter-périphérique doit être vérifiée. Le code ci-dessus a été testé dans Firefox, Edge et Chrome sur le bureau, ainsi que sur les appareils mobiles que je possède.

3
CubicleSoft
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%;  margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>

<script>
    function isNumberKey(evt) {
        var charCode = (evt.which) ? evt.which : event.keyCode;
        if (charCode > 31 && (charCode < 48 || charCode > 57)) {
            return false;
        }
        return true;
    }
</script>
3
raksh pal

Il y a donc des avantages et des inconvénients pour chaque événement. Les événements onkeypress et onkeydown ne récupèrent pas la dernière valeur et onkeypress ne se déclenche pas pour les caractères non imprimables dans certains navigateurs. L'événement onkeyup ne détecte pas le moment où une touche est maintenue enfoncée pour plusieurs caractères.

Ceci est un peu hacky, mais faire quelque chose comme

function edValueKeyDown(input) {
    var s = input.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: "+s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />

semble gérer le meilleur des mondes.

1
dx_over_dt

En utilisant event.key, nous pouvons obtenir des valeurs avant leur saisie dans la zone de saisie HTML. Voici le code.

function checkText()
{
  console.log("Value Entered which was prevented was - " + event.key);
  
  //Following will prevent displaying value on textbox
  //You need to use your validation functions here and return value true or false.
  return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />
1
vibs2006

Je concatène normalement la valeur du champ (c'est-à-dire avant sa mise à jour) avec la clé associée à l'événement de clé. Les utilisations suivantes de JS récentes doivent donc être ajustées pour prendre en charge les anciens IE.

Exemple récent de JS

document.querySelector('#test').addEventListener('keypress', function(evt) {
    var real_val = this.value + String.fromCharCode(evt.which);
    if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
    alert(real_val);
}, false);

Prise en charge des exemples d'IE plus anciens

//get field
var field = document.getElementById('test');

//bind, somehow
if (window.addEventListener)
    field.addEventListener('keypress', keypress_cb, false);
else
    field.attachEvent('onkeypress', keypress_cb);

//callback
function keypress_cb(evt) {
    evt = evt || window.event;
    var code = evt.which || evt.keyCode,
        real_val = this.value + String.fromCharCode(code);
    if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}

[EDITER - cette approche désactive par défaut les touches utilisées pour des tâches telles que l'espace arrière, CTRL + A. Le code ci-dessus s'adapte aux premiers, mais aurait besoin de bricoler davantage pour permettre les derniers et quelques autres éventualités. Voir le commentaire de Ian Boyd ci-dessous.]

1
Utkanos

facile...

Dans votre gestionnaire d’événements keyPress, écrivez

void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
    var tb = sender as TextBox;
    var startPos = tb.SelectionStart;
    var selLen= tb.SelectionLength;

    var afterEditValue = tb.Text.Remove(startPos, selLen)
                .Insert(startPos, e.KeyChar.ToString()); 
    //  ... more here
}
1
Charles Bretana

Essayez de concaténer l'événement charCode à la valeur que vous obtenez. Voici un exemple de mon code:

<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>

js:

function cnum(event, str) {
    var a = event.charCode;
    var ab = str.value + String.fromCharCode(a);
    document.getElementById('demo').innerHTML = ab;
}

La valeur dans ab obtiendra la dernière valeur du champ de saisie.

0
Rama Krishna