jQuery bind to keyup only, not focus
Asked Answered
C

4

5

This seems like a simple thing but google hasn't turned up anything for me:

How can I bind to a text / value change event only, excluding an input gaining focus? Ie, given the following:

$(function(){
  $('input#target').on('keyup', function(){
    alert('Typed something in the input.');
  });
});

...the alert would be triggered when the user tabs in and out of an element, whether they actually input text or not. How can you allow a user to keyboard navigate through the form without triggering the event unless they input/change the text in the text field?

Note: I'm showing a simplified version of a script, the reason for not using the change event is that in my real code I have a delay timer so that the event happens after the user stops typing for a second, without them having to change focus to trigger the event.

Carillonneur answered 15/4, 2012 at 2:14 Comment(0)
H
6

Store the value, and on any key event check if it's changed, like so:

$(function(){
  $('input#target').on('keyup', function(){
      if ($(this).data('val')!=this.value) {
          alert('Typed something in the input.');
      }
      $(this).data('val', this.value);
  });
});​

FIDDLE

Horrify answered 15/4, 2012 at 2:30 Comment(1)
I like this, nice and simple and it works well with my delay timer. Thanks!Carillonneur
C
4

Simply use the .change event.

Update: If you want live change notifications then do you have to go through the keyup event, which means that you need to program your handler to ignore those keys that will not result in the value being modified.

You can implement this with a whitelist of key codes that are ignored, but it could get ugly: pressing Del results in the value being changed, unless the cursor is positioned at the end of the input in which case it does not, unless there happens to be a selected range in the input in which case it does.

Another way which I personally find more sane if not as "pure" is to program your handler to remember the old value of the element and only react if it has changed.

$(function() {
    // for each input element we are interested in
    $("input").each(function () {
        // set a property on the element to remember the old value,
        // which is initially unknown
        this.oldValue = null;
    }).focus(function() {
        // this condition is true just once, at the time we
        // initialize oldValue to start tracking changes
        if (this.oldValue === null) {
            this.oldValue = this.value;
        }
    }).keyup(function() {
        // if no change, nothing to do
        if (this.oldValue == this.value) {
            return;
        }

        // update the cached old value and do your stuff
        this.oldValue = this.value;
        alert("value changed on " + this.className);
    });
});​

If you do not want to set properties directly on the DOM element (really, there's nothing wrong with it) then you could substitute $(this).data("oldValue") for this.oldValue whenever it appears. This will technically have the drawback of making the code slower, but I don't believe anyone will notice.

See it in action.

Cathiecathleen answered 15/4, 2012 at 2:16 Comment(1)
Except I want this to catch values as the user types (or, after they stop typing), without them having to switch out of the text field. I'll add this note to the question.Carillonneur
R
1

This will do it, set a custom attribute and check against that:

$('input').focus(function(){ 
    $(this).attr('originalvalue',$(this).val()); 
});

$('input').on('keyup',function(){ 
    if($(this).val()===$(this).attr('originalvalue')) return; 
    alert('he must\'ve typed something.'); 
});

Be wary of events firing multiple times.

Ravel answered 15/4, 2012 at 2:28 Comment(0)
G
0

Here is another version that plainly tests if the input field is empty.

If the input is empty then the action is not performed.

$(function(){
    $(selector).on('keyup', function(){
        if ($(this).val()!='') {
            alert('char was entered');
        }
    })
});
Galcha answered 7/8, 2014 at 9:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.