Détecter tous les changements à a (immédiatement) en utilisant JQuery

il y a plusieurs façons dont la valeur d'un <input type="text"> peut changer, y compris:

  • pressions sur les touches
  • copier / coller
  • modifié par JavaScript
  • auto-complétés par navigateur ou une barre d'outils

je veux que ma fonction JavaScript soit appelée (avec la valeur d'entrée actuelle) chaque fois qu'elle change. Et je veux que ça s'appelle tout de suite, pas seulement quand l'entrée perd concentrer.

je suis à la recherche de la manière la plus propre et la plus robuste de le faire à travers tous les navigateurs (en utilisant jQuery de préférence).

exemple de cas d'utilisation: sur la page inscription Twitter , le nom d'utilisateur la valeur du champ est affichée dans l'url " http://twitter/ username " ci-dessous.

356
demandé sur Sankar 2009-12-22 21:40:08

16 réponses

ce code jQuery capte les changements immédiats à n'importe quel élément, et devrait fonctionner sur tous les navigateurs:

 $('.myElements').each(function() {
   var elem = $(this);

   // Save current value of element
   elem.data('oldVal', elem.val());

   // Look for changes in the value
   elem.bind("propertychange change click keyup input paste", function(event){
      // If value has changed...
      if (elem.data('oldVal') != elem.val()) {
       // Updated stored value
       elem.data('oldVal', elem.val());

       // Do action
       ....
     }
   });
 });
322
répondu phatmann 2014-11-05 18:19:09

une solution de fantaisie en temps réel pour jQuery > = 1.9

$("#input-id").on("change keyup paste", function(){
    dosomething();
})

si vous voulez aussi détecter" click "événement, juste:

$("#input-id").on("change keyup paste click", function(){
    dosomething();
})

si vous utilisez jQuery <= 1.4, utilisez simplement live au lieu de on .

108
répondu Felix 2018-04-21 20:39:56

malheureusement, je pense que setInterval gagne le prix:

<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>

c'est la solution la plus propre, avec seulement 1 ligne de code. C'est aussi le plus robuste, puisque vous n'avez pas à vous soucier de tous les événements/façons dont un input peut obtenir une valeur.

les inconvénients de l'utilisation de "setInterval" ne semblent pas s'appliquer dans ce cas:

  • Les 100ms de latence? pour de nombreuses applications, 100ms est assez rapide.
  • charge ajoutée sur le navigateur? en général, ajouter beaucoup d'empattements lourds sur votre page est mauvais. Mais dans ce cas précis, la charge de page ajoutée est indétectable.
  • il n'est pas adapté à beaucoup d'entrées? la plupart des pages n'ont pas plus d'une poignée d'entrées, que vous pouvez renifler tout dans le même setInterval.
95
répondu Dustin Boswell 2009-12-22 21:47:52

se liant à l'événement oninput semble bien fonctionner dans la plupart des navigateurs sains. IE9 le supporte aussi, mais l'implémentation est boguée (l'événement n'est pas déclenché lors de la suppression de caractères).

avec la version 1.7 de jQuery+ la méthode on est utile pour lier à l'événement comme ceci:

$(".inputElement").on("input", null, null, callbackFunction);
55
répondu HRJ 2012-03-28 05:36:18

2017 réponse : le événement d'entrée fait exactement cela pour quelque chose de plus récent que IE8.

$(el).on('input', callback)
25
répondu Chris F Carroll 2017-10-25 10:28:56

Malheureusement, il n'existe aucun événement ou série d'événements correspondant à vos critères. Les touches et copier / coller peuvent être manipulées avec l'événement keyup . Les changements à travers JS sont plus compliqués. Si vous avez le contrôle sur le code qui définit la textbox, votre meilleur pari est de le modifier pour soit appeler votre fonction directement ou déclencher un événement utilisateur sur la textbox:

// Compare the textbox's current and last value.  Report a change to the console.
function watchTextbox() {
  var txtInput = $('#txtInput');
  var lastValue = txtInput.data('lastValue');
  var currentValue = txtInput.val();
  if (lastValue != currentValue) {
    console.log('Value changed from ' + lastValue + ' to ' + currentValue);
    txtInput.data('lastValue', currentValue);
  }
}

// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());

// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);

// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
  $('#txtInput').val('abc def').trigger('set');
});

si vous n'avez pas le contrôle sur ce code, vous pouvez utiliser setInterval() pour "regarder" zone de texte pour les changements:

// Check the textbox every 100 milliseconds.  This seems to be pretty responsive.
setInterval(watchTextbox, 100);

ce type de surveillance active ne capte pas les mises à jour "immédiatement", mais il semble être assez rapide qu'il n'y ait pas de retard perceptible. Comme DrLouie souligné dans les commentaires, cette solution n'a probablement pas bien si vous avez besoin de regarder beaucoup d'entrées. Vous pouvez toujours ajuster le 2e paramètre de setInterval() pour vérifier plus ou moins fréquemment.

15
répondu Annabelle 2009-12-22 20:00:34

Voici une solution légèrement différente si vous n'avez aimé aucune des autres réponses:

var field_selectors = ["#a", "#b"];
setInterval(function() { 
  $.each(field_selectors, function() { 
    var input = $(this);
    var old = input.attr("data-old-value");
    var current = input.val();
    if (old !== current) { 
      if (typeof old != 'undefined') { 
        ... your code ...
      }
      input.attr("data-old-value", current);
    }   
  }   
}, 500);

considère que tu ne peux pas te fier à click and keyup pour capturer la pâte de menu de contexte.

6
répondu Peder 2012-01-09 10:16:30

j'ai créé un exemple. Peut-il va travailler pour vous.

var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;

var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
    clearTimeout(typingTimer);
    if ($('#tyingBox').val) {
        typingTimer = setTimeout(function () {
            $("p.content").html('Typing...');
        }, doneTypingInterval);
    }
});

$('#tyingBox').keyup(function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function () {
        $("p.content").html(oldData);
    }, finaldoneTypingInterval);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>

http://jsfiddle.net/utbh575s /

3
répondu Ambuj Khanna 2014-10-22 07:48:04

en fait, nous n'avons pas besoin de configurer des boucles pour détecter les changements javaScript. Nous mettons déjà en place de nombreux écouteurs d'événements à l'élément que nous voulons détecter. déclencher n'importe quel événement nuisible fera l'affaire.

$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});

$("input[name='test-element']").val("test").trigger("blur");

et ofc ceci n'est disponible que si vous avez le contrôle total sur les modifications javascript sur votre projet.

3
répondu Serdar 2017-06-01 15:17:06

Ajouter ce code quelque part, cela fera l'affaire.

var originalVal = $.fn.val;
$.fn.val = function(){
    var result =originalVal.apply(this,arguments);
    if(arguments.length>0)
        $(this).change(); // OR with custom event $(this).trigger('value-changed');
    return result;
};

a Trouvé cette solution au val() n'est pas de déclencher un changement() en jQuery

3
répondu lpradhap 2017-10-31 07:25:19

Eh bien, la meilleure façon est de couvrir ces trois bases que vous avez énumérées par vous-même. Un simple: onblur,: onkeyup, etc ne fonctionnera pas pour ce que vous voulez, il suffit de les combiner.

KeyUp devrait couvrir les deux premiers, et si Javascript est en train de modifier la boîte de saisie, Eh bien j'espère que c'est votre propre javascript, alors il suffit d'ajouter un rappel dans la fonction qui le modifie.

1
répondu idrumgood 2009-12-22 19:03:25

voici un exemple fonctionnel que j'utilise pour implémenter une variation autocomplete la popule un sélecteur jqueryui (list), mais je ne veux pas qu'il fonctionne exactement comme l'autocomplete jqueryui qui fait un menu déroulant.

$("#tagFilter").on("change keyup paste", function() {
     var filterText = $("#tagFilter").val();
    $("#tags").empty();
    $.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
        function(data) {
            var i;
            for (i = 0; i < data.length; i++) {
                var tag = data[i].value;
                $("#tags").append("<li class=\"tag\">" + tag + "</li>");
            }
        }); 
});
1
répondu clearlight 2017-03-05 12:44:15

ne pouvez-vous pas utiliser <span contenteditable="true" spellcheck="false"> à la place de <input type="text"> ?

<span> (avec contenteditable="true" spellcheck="false" comme attributs) se distingue par <input> principalement parce que:

  • il n'est pas stylé comme un <input> .
  • il n'a pas de propriété value , mais le texte est rendu comme innerText et fait partie de son corps intérieur.
  • c'est multiligne alors que <input> n'est pas bien que vous positionniez l'attribut multiline="true" .

pour accomplir l'apparence, vous pouvez, bien sûr, le style dans CSS, tandis que l'écriture de la valeur comme innerText vous pouvez obtenir pour lui un événement:

voici un violon .

malheureusement il y a quelque chose qui ne fonctionne pas vraiment dans IE et Edge, que je suis incapable de trouver.

0
répondu Davide Cannizzo 2018-02-01 16:08:35

vous pouvez voir cet exemple et choisir quels sont les événements qui vous intéressent:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>evetns</title>
</head>
<body>
<form>
    <input class="controlevents" id="i1" type="text" /><br />
    <input class="controlevents" id="i2" type="text" /><br />
    <input class="controlevents" id="i3" type="text" /><br />
    <input class="controlevents" id="i4" type="text" /><br />
    <input class="controlevents" id="i5" type="text" /><br />
</form>
<div id="datatext"></div>
</body>
</html>
<script>
$(function(){

function testingevent(ev){
    if (ev.currentTarget.tagName=="INPUT")
        $("#datatext").append("<div>id : " + ev.currentTarget.id + ", tag: " + ev.currentTarget.tagName + ", type: "+ ev.type +"</div>");
}   

    var eventlist = ["resizeend","rowenter","dragleave","beforepaste","dragover","beforecopy","page","beforeactivate","beforeeditfocus","controlselect","blur",
                    "beforedeactivate","keydown","dragstart","scroll","propertychange","dragenter","rowsinserted","mouseup","contextmenu","beforeupdate",
                    "readystatechange","mouseenter","resize","copy","selectstart","move","dragend","rowexit","activate","focus","focusin","mouseover","cut",
                    "mousemove","focusout","filterchange","drop","blclick","rowsdelete","keypress","losecapture","deactivate","datasetchanged","dataavailable",
                    "afterupdate","mousewheel","keyup","movestart","mouseout","moveend","cellchange","layoutcomplete","help","errorupdate","mousedown","paste",
                    "mouseleave","click","drag","resizestart","datasetcomplete","beforecut","change","error","abort","load","select"];

    var inputs = $(".controlevents");

    $.each(eventlist, function(i, el){
        inputs.bind(el, testingevent);
    });

});
</script>
-2
répondu andres descalzo 2009-12-22 20:55:23

je suis peut-être en retard à la fête ici, mais vous ne pouvez pas juste utiliser le .change () event que jQuery fournit.

vous devriez pouvoir faire quelque chose comme ...

$(#CONTROLID).change(function(){
    do your stuff here ...
});

vous pouvez toujours le lier à une liste de contrôles avec quelque chose comme ...

var flds = $("input, textarea", window.document);

flds.live('change keyup', function() {
    do your code here ...
});

Le vivre liant assure que tous les éléments qui existent sur la page maintenant et dans l'avenir.

-3
répondu Andy Crouch 2010-06-11 08:20:01

C'est le plus rapide et propre façon de faire :

j'utilise Jquery-- >

$('selector').on('change', function () {
    console.log(this.id+": "+ this.value);
});

ça marche plutôt bien pour moi.

-4
répondu Despertaweb 2013-09-10 13:20:54