[javascript] Detect all changes to a <input type="text"> (immediately) using JQuery

There are many ways the value of a <input type="text"> can change, including:

  • keypresses
  • copy/paste
  • modified with JavaScript
  • auto-completed by browser or a toolbar

I want my JavaScript function to be called (with the current input value) any time it changes. And I want it to be called right away, not just when the input loses focus.

I'm looking for the cleanest and most robust way to do this across all browsers (using jQuery preferably).

This question is related to javascript jquery html

The answer is


Can't you just use <span contenteditable="true" spellcheck="false"> element in place of <input type="text">?

<span> (with contenteditable="true" spellcheck="false" as attributes) distincts by <input> mainly because:

  • It's not styled like an <input>.
  • It doesn't have a value property, but the text is rendered as innerText and makes part of its inner body.
  • It's multiline whereas <input> isn't although you set the attribute multiline="true".

To accomplish the appearance you can, of course, style it in CSS, whereas writing the value as innerText you can get for it an event:

Here's a fiddle.

Unfortunately there's something that doesn't actually work in IE and Edge, which I'm unable to find.


Although this question was posted 10 years ago, I believe that it still needs some improvements. So here is my solution.

$(document).on('propertychange change click keyup input paste', 'selector', function (e) {
    // Do something here
});

The only problem with this solution is, it won't trigger if the value changes from javascript like $('selector').val('some value'). You can fire any event to your selector when you change the value from javascript.

$(selector).val('some value');
// fire event
$(selector).trigger('change');

you can see this example and choose which are the events that interest you:

<!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>

Well, best way is to cover those three bases you listed by yourself. A simple :onblur, :onkeyup, etc won't work for what you want, so just combine them.

KeyUp should cover the first two, and if Javascript is modifying the input box, well I sure hope it's your own javascript, so just add a callback in the function that modifies it.


Here's a working example that I'm using to implement an autocomplete variation the populates a jqueryui selector (list), but I don't want it to function exactly like the jqueryui autocomplete which does a drop-down menu.

$("#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>");
            }
        }); 
});

Unfortunately there is no event or set of events that matches your criteria. Keypresses and copy/paste can both be handled with the keyup event. Changes through JS are trickier. If you have control over the code that sets the textbox, your best bet is to modify it to either call your function directly or trigger a user event on the 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');
});

If you don't have control over that code, you could use setInterval() to 'watch' the textbox for changes:

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

This sort of active monitoring won't catch updates 'immediately', but it seems to be fast enough that there is no perceptible lag. As DrLouie pointed out in comments, this solution probably doesn't scale well if you need to watch lots of inputs. You can always adjust the 2nd parameter to setInterval() to check more or less frequently.


You can bind the 'input' event to <input type="text">. This will trigger every time the input changes such as copy, paste, keypress, and so on.

$("#input-id").on("input", function(){
    // Your action
})

Here is a slightly different solution if you didn't fancy any of the other answers:

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);

Consider that you cannot rely on click and keyup to capture context menu paste.


Binding to the oninput event seems to work fine in most sane browsers. IE9 supports it too, but the implementation is buggy (the event is not fired when deleting characters).

With jQuery version 1.7+ the on method is useful to bind to the event like this:

$(".inputElement").on("input", null, null, callbackFunction);

I have created a sample. May it will work for you.

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/


This jQuery code catches immediate changes to any element, and should work across all browsers:

 $('.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
       ....
     }
   });
 });

This is the fastest& clean way to do that :

I'm using Jquery-->

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

It is working pretty fine for me.


Add this code somewhere, this will do the trick.

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;
};

Found this solution at val() doesn't trigger change() in jQuery


We actually don't need to setup loops for detecting javaScript changes. We already setting up many event listeners to the element we want to detect. just triggering any un harmful event will make the job.

$("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");

and ofc this is only available if you have the full control on javascript changes on your project.


you can simply identify all changers in the form, like this

           //when form change, show aleart
            $("#FormId").change(function () {
                aleart('Done some change on form');
            }); 

I may be late to the party here but can you not just use the .change() event that jQuery provides.

You should be able to do something like ...

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

You could always bind it to a list of controls with something like ...

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

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

The live binder ensures that all elements that exist on the page now and in the future are handled.


A real-time fancy solution for jQuery >= 1.9

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

if you also want to detect "click" event, just:

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

if you're using jQuery <= 1.4, just use live instead of on.


2017 answer: the input event does exactly this for anything more recent than IE8.

$(el).on('input', callback)

NO JQUERY! (Its kindof obsolete these days anyways)

Heres an Non-ASCII detector using event listeners

Using the event "input" you can look for any kind of change:

Deleting, Backspacing, Pasting, Typing, anything that will change the inputs value.

The input event is directly related to the setter of the text input. ANY time the text is changed in ANY fashion, input is dispatched.

_x000D_
_x000D_
document.querySelector("#testInput").addEventListener("input", test);
document.querySelector("#testInputLocked").addEventListener("input", testLocked);

function test(e) {
 var a = document.getElementById('output');
 if (e.target.value == '' || /^[ -~]+$/.test(e.target.value)) {
  a.innerText = "ASCII: true";
 } else if (!/^[ -~]+$/.test(e.target.value)) {
  a.innerText = "ASCII: false";
 }
}

function testLocked(e) {
 e.target.value = e.target.value.replace(/[^ -~]+/g, '');
}
_x000D_
Try pressing Alt+NumPad2+NumPad3 in the input, it will instantly detect a change, whether you Paste, Type, or any other means, rather than waiting for you to unselect the textbox for changes to detect.
<br><br>
<input id="testInput">
<a id="output">ASCII: true</a>
<br><br>
Want to lock it to ASCII and replace all Non-ASCII?
<br>
<input id="testInputLocked" placeholder="ASCII Locked">
_x000D_
_x000D_
_x000D_


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment