Deebster
Deebster

Reputation: 2839

Firing a handler once for each actual change in an HTML input element

I want to trigger an event handler once per each actual change in an input field. For example, to validate (per keypress) entry of a credit card number (the change must be on each change so debouncing/throttling is not the answer).

I cannot use input alone as IE9 will not trigger this event from backspaces or cut/delete.

I cannot use keyup alone as this does not handle changes from a mouse (eg. pasting).

I cannot use change because this only fires on blur.

I can do $('input').bind('input keyup', handler) but this will fire two separate events most of the time. Assume that the handler is expensive and running it twice is unacceptable.

I can wrap the handler so that it only runs if the current value is different to the last checked but is there a better way?

Upvotes: 1

Views: 256

Answers (5)

Vier
Vier

Reputation: 807

If you don't need the handler to return a value, you can make it return false so that it doesn't fire up a second time.

Upvotes: 0

epascarello
epascarello

Reputation: 207501

What you are doing with checking the last input is what you need to do.

This is one way you can do it to store the last value.

function handler(){ 
    var tb = jQuery(this);
    var currentValue = tb.val();
    if (tb.data("lastInput") !== currentValue) {
        tb.data("lastInput", currentValue);
        console.log("The current value is " + currentValue);
    } 
}
$('input').bind('input keyup', handler);

jsFiddle

You could always extend jQuery if you really do not want that logic in your function. It is a bunch more code, but one method.

(function(){
    $.fn.oneinput = function(callback) {        
        function testInput(){ 
            var tb = jQuery(this);
            var currentValue = tb.val();
            if (tb.data("lastInput") !== currentValue ) {
                tb.data("lastInput",currentValue );
                if(callback) { 
                    callback.call(this) 
                };
            }
            return this;
        }    
        jQuery(this).bind("keyup input", testInput);
    };
}(jQuery));

$('input').oneinput( function(){ console.log(this.value); });
​

jsfiddle

Upvotes: 5

Ehtesham
Ehtesham

Reputation: 2985

Try this

    $('input').bind('keyup cut paste', function (event) {
         console.log('value changed');
    });

Fiddle http://jsfiddle.net/sXvK2/1/

Upvotes: 0

GajendraSinghParihar
GajendraSinghParihar

Reputation: 9131

I think the you have to use setInterval to moniter the change in the text box

try this demo

objTextBox = document.getElementById("trackChange");
oldValue = objTextBox.value;

console.log(oldValue);

function track_change()
   {
     if(objTextBox.value != oldValue)
     {
       oldValue = objTextBox.value;
       console.log("changed")
     }

   }

setInterval(function() { track_change()}, 100);

Note: I don't personally think that this is the best solution.But I cant find a better and at leat it will work for sure in every case keyboard or mouse change ;)

Upvotes: 0

Phuong Vu
Phuong Vu

Reputation: 537

What about

$el.bind('input', handler);
$el.bind('keyup', handler);
...

Upvotes: -3

Related Questions