web-dev-qa-db-fra.com

Comment détecter le contenu d'une zone de texte a changé

Je veux détecter chaque fois que le contenu d'une zone de texte a changé. Je peux utiliser la méthode keyup, mais cela détectera également les frappes de touche qui ne génèrent pas de lettres, comme les touches fléchées. J'ai pensé à deux méthodes pour ce faire en utilisant l'événement keyup:

  1. Vérifier explicitement si le code ASCII de la touche appuyée est une lettre\backspace\delete
  2. Utilisez des fermetures pour mémoriser le texte dans la zone de texte avant le trait de touche et vérifiez si celui-ci a changé.

Les deux semblent un peu encombrants.

406
olamundo

Commencez à observer l'événement "d'entrée" au lieu de "changer".

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... qui est gentil et propre, mais peut être étendu à:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
696
Atul Vani

Utilisez l'événement onchange en HTML/JavaScript standard.

Dans jQuery, il s'agit de l'événement change () . Par exemple:

$('element').change(function() { // do something } );

MODIFIER

Après avoir lu quelques commentaires, qu’en est-il:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
66
Waleed Amjad

L'événement 'change' ne fonctionne pas correctement, mais le 'input' est parfait.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
44
schwarzkopfb

Que dis-tu de ça:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Cela fonctionne dans IE8/IE9, FF, Chrome

38
Catfish

Utilisez des fermetures pour mémoriser le texte de la case à cocher avant le trait de touche et vérifiez si celui-ci a changé.

Oui. Vous n'avez pas nécessairement à utiliser les fermetures, mais vous devrez vous rappeler de l'ancienne valeur et la comparer à la nouvelle.

Pourtant! Cela ne concerne toujours pas tous les changements, car il existe un moyen de modifier le contenu de la zone de texte sans pression sur une touche. Par exemple, en sélectionnant une plage de texte, puis en coupant par un clic droit. Ou le faire glisser. Ou déposer du texte d'une autre application dans la zone de texte. Ou changer un mot via la vérification orthographique du navigateur. Ou...

Donc, si vous devez détecter chaque changement, vous devez le rechercher. Vous pouvez window.setInterval vérifier le champ par rapport à sa valeur précédente toutes les secondes. Vous pouvez également relier onkeyup à la même fonction pour que les modifications are causées par des pressions de touche soient reflétées plus rapidement.

Lourd? Oui. Mais c’est cela ou faites-le simplement avec la méthode HTML habituelle et n’essayez pas de mettre à jour instantanément.

21
bobince
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Vous pouvez utiliser l'événement 'input' pour détecter le changement de contenu dans la zone de texte. N'utilisez pas 'live' pour lier l'événement car il est déconseillé dans Jquery-1.7, utilisez donc 'on'.

13
NavaRajan

Je suppose que vous cherchez à faire quelque chose d’interactif lorsque la zone de texte change (c.-à-d. Récupérer des données via ajax). Je cherchais cette même fonctionnalité. Je sais que l'utilisation d'une solution globale n'est pas la solution la plus robuste ni la plus élégante, mais c'est ce que j'ai choisi. Voici un exemple:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Un élément clé à noter ici est que j'utilise setTimeout et non setInterval car je ne veux pas envoyer plusieurs demandes en même temps. Cela garantit que le minuteur "s'arrête" lorsque le formulaire est soumis et "démarre" lorsque la demande est terminée. Je le fais en appelant checkSearchChanged lorsque mon appel ajax est terminé. Évidemment, vous pouvez développer cela pour vérifier la longueur minimale, etc.

Dans mon cas, j'utilise ASP.Net MVC afin que vous puissiez voir comment associer cela à MVC Ajax également dans le post suivant:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

5
Doug Lampe

Je recommanderais de jeter un coup d'oeil au widget de saisie semi-automatique de jQuery UI. Ils ont traité la plupart des cas là-bas car leur base de code est plus mature que la plupart des cas existants.

Vous trouverez ci-dessous un lien vers une page de démonstration afin que vous puissiez vérifier que cela fonctionne. http://jqueryui.com/demos/autocomplete/#default

Vous obtiendrez le maximum d’avantages en lisant la source et en voyant comment elle l’a résolu. Vous pouvez le trouver ici: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Fondamentalement, ils font tout, ils se lient à input, keydown, keyup, keypress, focus and blur. Ensuite, ils ont un traitement spécial pour toutes sortes de clés comme page up, page down, up arrow key and down arrow key. Une minuterie est utilisée avant d'obtenir le contenu de la zone de texte. Lorsqu'un utilisateur tape une clé qui ne correspond pas à une commande (touche haut, touche bas, etc.), il existe une minuterie qui explore le contenu après environ 300 millisecondes. Cela ressemble à ceci dans le code:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

La raison d'utiliser un minuteur est pour que l'interface utilisateur ait une chance d'être mise à jour. Lorsque Javascript est en cours d'exécution, l'interface utilisateur ne peut pas être mise à jour, par conséquent l'appel de la fonction de délai. Cela fonctionne bien pour d'autres situations telles que rester concentré sur la zone de texte (utilisée par ce code).

Vous pouvez donc utiliser le widget ou copier le code dans votre propre widget si vous n'utilisez pas l'interface utilisateur jQuery (ou dans mon cas, développez un widget personnalisé).

4
Michael Yagudaev

Je voudrais demander pourquoi vous essayez de détecter quand le contenu de la zone de texte a changé en temps réel?

Une autre solution consisterait à définir une minuterie (via setIntval?), À comparer la dernière valeur enregistrée à la valeur actuelle, puis à réinitialiser une minuterie. Cela garantirait la capture de TOUT changement, qu'il soit causé par des clés, une souris, un autre périphérique de saisie que vous n'avez pas pris en compte, ou même un changement de code JavaScript (une autre possibilité que personne n'a mentionnée) depuis une autre partie de l'application.

2
DVK

Utilisez l'événement textchange via une cale jQuery personnalisée pour la compatibilité entre navigateurs input. http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (github le plus récemment créé: - https://github.com/pandell/jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Ceci gère toutes les balises d’entrée, y compris <textarea>content</textarea>, qui ne fonctionne pas toujours avec changekeyup etc. (!). Seul jQuery on("input propertychange") gère les balises <textarea> de manière cohérente. comprendre input événement.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

test JS Bin

Cela gère également les opérations de collage, de suppression et de duplication des efforts sur Keyup.

Si vous n'utilisez pas de shim, utilisez les événements jQuery on("input propertychange").

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
1
Ber

envisagez-vous d'utiliser change event ?

$("#myTextBox").change(function() { alert("content changed"); });
1
Canavar

Quelque chose comme cela devrait fonctionner, principalement parce que focus et focusout se retrouveraient avec deux valeurs distinctes. J'utilise data ici parce qu'il stocke des valeurs dans l'élément mais ne touche pas le DOM. C'est également un moyen facile de stocker la valeur connectée à son élément. Vous pourriez tout aussi facilement utiliser une variable de portée supérieure.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
0
smcjones

Il existe un exemple de travail complet ici .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
0
user586399