Détection onchange Textarea


132

Comment détecter un événement de modification sur textarea en utilisant javascript?
J'essaie de détecter le nombre de caractères disponibles au fur et à mesure que vous tapez.

J'ai essayé d'utiliser l'événement onchange, mais cela semble ne se déclencher que lorsque le focus est absent.

Réponses:


97

Vous devrez utiliser onkeyup et onchange pour cela. L'onchange empêchera le collage du menu contextuel, et le onkeyup se déclenchera à chaque frappe.

Voir ma réponse sur Comment imposer maxlength sur textArea pour un exemple de code.


3
Je voulais juste souligner ce que Josh a déjà dit, que vous devriez utiliser keyup, pas keydown pour cela: keydown semble être appelé avant que la modification ne soit réellement apportée à la zone de texte, vous utiliserez donc la mauvaise longueur (et vous ne le faites pas) Vous savez vraiment à quel point vous êtes: vous pourriez taper ou supprimer, et avoir du texte sélectionné, ce qui signifie que c'est plus que +/- 1).
brianmearns

65
Je donne un -1 ici, désolé! onkeyupest un événement terrible pour la détection d'entrée. Utilisez oninputet onpropertychange(pour le support IE).
Andy E

6
Le « seul » problème onchangeest pas déclenché quand une coupe / pâte de menu contextuel se produit.
Tom

4
Il est beaucoup plus réactif d'utiliser onkeydown et setTimeout afin d'obtenir une détection instantanée des changements plutôt que d'attendre que la clé soit relâchée. Si vous devez également intercepter le copier-coller, utilisez les événements couper-coller.
Kevin B

1
Attention: onkeyup peut vous poser des problèmes. Exemple: disons que vous ne devriez faire quelque chose que si le contenu d'entrée a changé. Si vous supposez qu'un keyup changera l'entrée, ce n'est pas vrai. Mettez l'accent sur l'entrée. Utilisez "tab" pour passer au champ suivant. Maintenant, utilisez "shift + tab" pour revenir à l'entrée. keyup se déclenche mais l'entrée n'a pas été réellement modifiée par l'utilisateur.
Zig Mandel

117

Nous sommes en 2012, l'ère post-PC est arrivée, et nous devons encore lutter avec quelque chose d'aussi basique que celui-ci. Cela devrait être très simple .

Jusqu'à ce que ce rêve se réalise, voici la meilleure façon de le faire, cross-browser: utilisez une combinaison des événements inputetonpropertychange , comme ceci:

var area = container.querySelector('textarea');
if (area.addEventListener) {
  area.addEventListener('input', function() {
    // event handling code for sane browsers
  }, false);
} else if (area.attachEvent) {
  area.attachEvent('onpropertychange', function() {
    // IE-specific event handling code
  });
}

L' inputévénement prend en charge IE9 +, FF, Chrome, Opera et Safari , et onpropertychangeprend en charge IE8 (cela fonctionne également avec IE6 et 7, mais il y a quelques bugs).

L'avantage d'utiliser inputet onpropertychangeest qu'ils ne se déclenchent pas inutilement (comme lorsque vous appuyez sur les touches Ctrlou Shift); donc si vous souhaitez exécuter une opération relativement coûteuse lorsque le contenu de la zone de texte change, c'est la voie à suivre .

Maintenant, IE, comme toujours, fait un demi-travail de soutien: ni inputni se onpropertychangedéclenche dans IE lorsque les caractères sont supprimés de la zone de texte. Donc, si vous devez gérer la suppression de caractères dans IE, utilisez keypress(par opposition à l'utilisation de keyup/ keydown, car ils ne se déclenchent qu'une seule fois même si l'utilisateur appuie et maintient une touche enfoncée).

Source: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/

EDIT: Il semble que même la solution ci-dessus ne soit pas parfaite, comme indiqué à juste titre dans les commentaires: la présence de la addEventListenerpropriété sur la zone de texte n'implique pas que vous travaillez avec un navigateur sensé; de même, la présence de la attachEventpropriété n'implique pas IE. Si vous voulez que votre code soit vraiment étanche, vous devriez envisager de le changer. Voir le commentaire de Tim Down pour les pointeurs.


1
C'est la meilleure approche. Je n'aime pas les inférences ici (la prise en charge du navigateur addEventListenern'implique pas la prise en charge de l' inputévénement, ou vice versa); la détection des fonctionnalités serait meilleure. Voir ce billet de blog pour une discussion à ce sujet.
Tim Down

Tout à fait d'accord avec Tim sur celui-ci. oninputC'est ainsi que nous devrions faire cela, mais vous ne devriez probablement pas utiliser addEventListenercomme test de support du navigateur. +1 dans tous les cas.
Ben D

1
Pas d'accord, l'entrée ne prendra pas en charge IE9. Couper / Coller via le menu contextuel est malheureusement également une entrée, tout comme le retour arrière. Je n'ai pas pris la peine de tester, mais je ne mettrais pas d'argent sur le pari que IE10 + a résolu ce problème.
Stefan Steiger

1
@StefanSteiger, c'est pourquoi ma réponse suggère également d'utiliser l' keypressévénement pour gérer ce cas dans IE9 (et éventuellement dans les versions ultérieures).
Vicky Chijwani

inputLe gestionnaire d' événements peut également être défini en implémentant la .oninputpropriété object.
gérer le

20
  • Pour Google-Chrome, une entrée sera suffisante (Testé sur Windows 7 avec la version 22.0.1229.94 m).
  • Pour IE 9, oninput capturera tout sauf couper via le menu contextuel et le retour arrière.
  • Pour IE 8, onpropertychange est requis pour intercepter le collage en plus de oninput.
  • Pour IE 9 + 8, onkeyup est nécessaire pour récupérer le retour arrière.
  • Pour IE 9 + 8, onmousemove est le seul moyen que j'ai trouvé pour attraper la coupure via le menu contextuel

Non testé sur Firefox.

    var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...

    function SuperDuperFunction() {
        // DoSomething
    }


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
        if(isIE) // For Chrome, oninput works as expected
            SuperDuperFunction();
    }

<textarea id="taSource"
          class="taSplitted"
          rows="4"
          cols="50"
          oninput="SuperDuperFunction();"
          onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>

1
Noms de fonctions géniaux :)
Jonas Gröger

8

Je sais que ce n'est pas exactement votre question, mais j'ai pensé que cela pourrait être utile. Pour certaines applications, il est agréable que la fonction de changement ne se déclenche pas à chaque fois qu'une touche est enfoncée. Ceci peut être réalisé avec quelque chose comme ceci:

var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);

text.onkeyup = function(){
var callcount = 0;
    var action = function(){
        alert('changed');
    }
    var delayAction = function(action, time){
        var expectcallcount = callcount;
        var delay = function(){
            if(callcount == expectcallcount){
                action();
            }
        }
        setTimeout(delay, time);
    }
    return function(eventtrigger){
        ++callcount;
        delayAction(action, 1200);
    }
}();

Cela fonctionne en testant si un événement plus récent s'est déclenché dans un certain délai. Bonne chance!


1
+1 pour l'action retardée de «limitation»! J'utilise quelque chose de similaire dans mon application.
psulek

7

Je sais que cette question était spécifique à JavaScript, cependant, il ne semble pas y avoir de moyen efficace et propre de TOUJOURS détecter quand une zone de texte change dans tous les navigateurs actuels. J'ai appris que jquery s'en est occupé pour nous. Il gère même les modifications du menu contextuel des zones de texte. La même syntaxe est utilisée quel que soit le type d'entrée.

    $('div.lawyerList').on('change','textarea',function(){
      // Change occurred so count chars...
    });

ou

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });

4
J'ai trouvé que l'événement de changement n'était pas plus cohérent avec jQuery qu'avec JS ordinaire. J'ai utilisé jQuery bind("input cut paste"...et cela fonctionne comme un charme - taper, couper et coller en utilisant le clavier ou le menu contextuel; même glisser / déposer du texte.
Lawrence Dol

2
Malheureusement, FF ne déclenche pas d' changeévénement pour textarea.
dma_k

4

Vous pouvez écouter l'événement lors du changement de zone de texte et effectuer les modifications que vous souhaitez. Voici un exemple.

(() => {
	const textArea = document.getElementById('my_text_area');
  textArea.addEventListener('input', () => {
    let textLn =  textArea.value.length;
    if(textLn >= 100) {
      textArea.style.fontSize = '10pt';
    }

  })
})()
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>


1

Keyup devrait suffire s'il est associé à l'attribut de validation / modèle d'entrée HTML5. Alors, créez un modèle (regex) pour valider l'entrée et agir sur le statut .checkValidity (). Quelque chose comme ci-dessous pourrait fonctionner. Dans votre cas, vous voudriez qu'une expression régulière corresponde à la longueur. Ma solution est en cours d'utilisation / de démonstration en ligne ici .

<input type="text" pattern="[a-zA-Z]+" id="my-input">

var myInput = document.getElementById = "my-input";

myInput.addEventListener("keyup", function(){
  if(!this.checkValidity() || !this.value){
    submitButton.disabled = true;
  } else {
    submitButton.disabled = false;
  }
});

0

Code que j'ai utilisé pour IE 11 sans jquery et juste pour une seule zone de texte:

Javascript:

// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{ 
    if (internalChange == 1)
    {
        internalChange= 0;
        return;
    }
    internalChange= 1;
    // <form> and <textarea> are the ID's of your form and textarea objects
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}

et html:

<TEXTAREA onpropertychange='limit_char(5)' ...

-1

Essaye celui-là. C'est simple, et depuis 2016, je suis sûr que cela fonctionnera sur la plupart des navigateurs.

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div>

function check(){
    var string = document.getElementById("url").value
    var left = 15 - string.length;
    document.getElementById("spn").innerHTML = left;
}

Vous obtenez donc l'URL par identifiant, mais ce n'est pas indiqué dans votre code.
AbsoluteƵERØ

-8

La meilleure chose que vous pouvez faire est de définir une fonction à appeler sur une durée donnée et cette fonction pour vérifier le contenu de votre zone de texte.

self.setInterval('checkTextAreaValue()', 50);

7
le sondage est une très mauvaise idée. Cela détruira simplement les performances. Aussi, comme d'autres postés, une solution existe
Pier-Olivier Thibault

2
Nous sommes au 21e siècle. Aucun navigateur ne devrait avoir du mal à gérer une comparaison de chaînes toutes les 50 ms. Mettez vos sélecteurs en cache et c'est une solution parfaitement acceptable.
nullité
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.