La valeur d'un <input type="text">
peut changer de plusieurs manières, notamment:
Je souhaite que ma fonction JavaScript soit appelée (avec la valeur d'entrée actuelle) chaque fois qu'elle change. Et je veux qu'il soit appelé immédiatement, pas seulement lorsque l'entrée perd le focus.
Je cherche le moyen le plus propre et le plus robuste de le faire sur tous les navigateurs (en utilisant de préférence jQuery).
Exemple de cas d'utilisation: Sur la page Twitter Signup , la valeur du champ nom d'utilisateur est indiquée dans l'URL " http : // Twitter / nom d'utilisateur "en dessous.
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 une seule ligne de code. C'est aussi le plus robuste, car vous n'avez pas à vous soucier de tous les événements/façons dont une input
peut obtenir une valeur.
Les inconvénients de l'utilisation de 'setInterval' ne semblent pas s'appliquer dans ce cas:
Ce code jQuery capture les modifications immédiates de tout é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
....
}
});
});
Une solution de fantaisie en temps réel pour jQuery> = 1.9
$("#input-id").on("change keyup paste", function(){
dosomething();
})
si vous souhaitez également détecter un événement "clic", il suffit de:
$("#input-id").on("change keyup paste click", function(){
dosomething();
})
si vous utilisez jQuery <= 1.4, utilisez simplement live
au lieu de on
.
La liaison à l'événement oninput
semble fonctionner correctement dans la plupart des navigateurs rationnels. IE9 le prend également en charge, mais son implémentation est erronée (l'événement n'est pas déclenché lors de la suppression de caractères).
Avec jQuery version 1.7+, la méthode on
est utile pour se lier à l'événement de la manière suivante:
$(".inputElement").on("input", null, null, callbackFunction);
2017 réponse : le événement d'entrée fait exactement cela pour tout ce qui est plus récent que IE8.
$(el).on('input', callback)
Malheureusement, aucun événement ou ensemble d'événements ne correspond à vos critères. Les touches et les copier/coller peuvent être gérés avec l'événement keyup
. Les changements via JS sont plus compliqués. Si vous avez le contrôle sur le code qui définit la zone de texte, le mieux est de le modifier pour appeler directement votre fonction ou déclencher un événement utilisateur sur la zone de texte:
// 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 "surveiller" la zone de texte afin de détecter les modifications:
// Check the textbox every 100 milliseconds. This seems to be pretty responsive.
setInterval(watchTextbox, 100);
Ce type de surveillance active ne détectera pas les mises à jour "immédiatement", mais il semble être assez rapide pour qu'il n'y ait pas de décalage perceptible. Comme DrLouie l'a souligné dans ses commentaires, cette solution ne fonctionne probablement pas bien si vous devez surveiller de nombreuses entrées. Vous pouvez toujours régler le deuxième paramètre sur setInterval()
pour vérifier plus ou moins fréquemment.
Voici une solution légèrement différente si vous n'avez pas envie d'une autre réponse:
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érez que vous ne pouvez pas compter sur click et keyup pour capturer le collage du menu contextuel.
Ajoutez 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;
};
Trouvé cette solution à val () ne déclenche pas change () dans jQuery
En réalité, nous n'avons pas besoin de configurer des boucles pour détecter les modifications JavaScript. Nous avons déjà configuré de nombreux écouteurs d’événements pour l’élément que nous voulons détecter. le simple fait de déclencher un événement néfaste fera le travail.
$("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 de javascript de votre projet.
J'ai créé un échantillon. Puisse cela fonctionner 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>
Eh bien, le meilleur moyen est de couvrir ces trois bases que vous avez énumérées par vous-même. Un simple: onblur, onkeyup, etc. ne fonctionnera pas comme vous le souhaitez, combinez-les simplement.
KeyUp devrait couvrir les deux premiers, et si Javascript est en train de modifier la zone de saisie, j'espère que c'est votre propre javascript, ajoutez donc un rappel dans la fonction qui le modifie.
Voici un exemple de travail que j'utilise pour implémenter une variante de complétion automatique: elle remplit un sélecteur jqueryui (liste), mais je ne souhaite pas qu'elle fonctionne exactement comme la saisie automatique jqueryui, qui comporte 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>");
}
});
});
Ne pouvez-vous pas simplement utiliser l'élément <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:
<input>
.value
, mais le texte est rendu sous la forme innerText
et fait partie de son corps intérieur.<input>
ne l’est pas bien que vous ayez défini l’attribut multiline="true"
.Pour obtenir l'apparence voulue, vous pouvez bien sûr la styler en CSS, alors que l'écriture de la valeur sous la forme innerText
vous permet d'obtenir un événement:
Voici un violon .
Malheureusement, il y a quelque chose qui ne fonctionne pas dans IE et Edge, que je ne parviens pas à trouver.