Javascript change event on input element fires on only losing focus
Asked Answered
S

7

96

I have an input element and I want to keep checking the length of the contents and whenever the length becomes equal to a particular size, I want to enable the submit button, but I am facing a problem with the onchange event of Javascript as the event fires only when the input element goes out of scope and not when the contents change.

<input type="text" id="name" onchange="checkLength(this.value)" />

----onchange does not fire on changing contents of name, but only fires when name goes out of focus.

Is there something I can do to make this event work on content change? or some other event I can use for this? I found a workaround by using the onkeyup function, but that does not fire when we select some content from the auto completer of the browser.

I want something which can work when the content of the field change whether by keyboard or by mouse... any ideas?

Slumberous answered 18/8, 2011 at 10:31 Comment(6)
You could use onkeyup and onchange?Dullish
The only issue I have is that browser's autocompleter selection would not cause any of these events to occur.Slumberous
What kind of input field is this?Salicin
oh...I forgot to add it into the sample code, its a text field.Slumberous
I thought this would have been a very common issue & lots of people would have faced it, but now it seems the other way round...:)Slumberous
Possibly see also https://mcmap.net/q/219357/-catching-all-changes-to-the-contents-of-an-input-box-using-javascript-jqueryDeconsecrate
S
131
(function () {
    var oldVal;

    $('#name').on('change textInput input', function () {
        var val = this.value;
        if (val !== oldVal) {
            oldVal = val;
            checkLength(val);
        }
    });
}());

This will catch change, keystrokes, paste, textInput, input (when available). And not fire more than necessary.

http://jsfiddle.net/katspaugh/xqeDj/


References:

textInput — a W3C DOM Level 3 event type. http://www.w3.org/TR/DOM-Level-3-Events/#events-textevents

A user agent must dispatch this event when one or more characters have been entered. These characters may originate from a variety of sources, e.g., characters resulting from a key being pressed or released on a keyboard device, from the processing of an input method editor, or resulting from a voice command. Where a “paste” operation generates a simple sequence of characters, i.e., a text passage without any structure or style information, this event type should be generated as well.

input — an HTML5 event type.

Fired at controls when the user changes the value

Firefox, Chrome, IE9 and other modern browsers support it.

This event occurs immediately after modification, unlike the onchange event, which occurs when the element loses focus.

Sharrisharron answered 18/8, 2011 at 11:5 Comment(9)
its no working...did you check your code at your end?? was it working on selection from an autocompleter...?Slumberous
I checked textInput in Chrome 15 and it works. I checked input event in IE9 and it works too. Firefox should support DOMAttrModified, but I don't have it installed. These two events are the best you can hope for, since they fire on any kind of text input.Sharrisharron
Awesome solution....input worked for me like a blessing...nothing else except input is needed, that itself works enough. it works on ff4, but does not on 3.x, & I had 3.6 on my desktop & it never worked...Slumberous
Can you provide some more information about this input event with which you are binding the element here, I couldn't find it on api.jquery.comSlumberous
@Sharrisharron nope, it only updates the other TBs when leaving the first one, I want the sync to happen immediately.Laroche
For the sake of keeping things updated, currently this solution fired multiple times on a single input change in FF22, you don't need to use the keypress or textinput events, input and propertychange should sufficeDescribe
I found that change, keyup, and input was the best combination to cover IE9 and Firefox (36.0.4). The keypress event did not seem to work in IE9 because it didn't capture things like Delete and Backspace, and the input event covers pasting with the keyboard and with the context menu.Insnare
input dominatesCryptanalysis
This works not so well with characters that require input method. For example, to input Chinese character “長”, I'd press "c","h","a","n",“g” and then "space", all these keystrokes are recorded and fire the events unwantedly. Is there any workaround for this? #70041218Mohur
M
12

It took me 30 minutes to find it, but this is working in June 2019.

<input type="text" id="myInput" oninput="myFunction()">

and if you want to add an event listener programmatically in js

inputElement.addEventListener("input", event => {})
Medlock answered 8/6, 2019 at 14:41 Comment(4)
the "input" event is what also React is using for the onChange property :)Boudoir
@sekmo, then why they decided to call it onChange? It's confusingHydrometer
can you share the link where react says that they use onInput when we call onChange?Hydrometer
"The onChange event behaves as you would expect it to: whenever a form field is changed, this event is fired. We intentionally do not use the existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to handle user input in real time." reactjs.org/docs/dom-elements.html#onchange - "For <input> and <textarea>, onChange supersedes — and should generally be used instead of — the DOM's built-in oninput event handler." reactjs-bot.github.io/react/docs-old/…Boudoir
D
10

As an extention to katspaugh's answer, here's a way to do it for multiple elements using a css class.

   $('.myclass').each(function(){
        $(this).attr('oldval',$(this).val());
   });

   $('.myclass').on('change keypress paste focus textInput input',function(){
       var val = $(this).val();
       if(val != $(this).attr('oldval') ){
           $(this).attr('oldval',val); 
           checkLength($(this).val());
        }
    });
Dar answered 2/1, 2013 at 14:45 Comment(0)
S
4

Do it the jQuery way:

<input type="text" id="name" name="name"/>


$('#name').keyup(function() {
  alert('Content length has changed to: '+$(this).val().length);
});
Salicin answered 18/8, 2011 at 10:33 Comment(3)
This will also only be fired when the field looses focues.Portulaca
@Felix Kling, true, changed it to keyup() ;)Salicin
again the same problem with keyup...I have used it & i had a problem with that. read my complete question.Slumberous
B
1

You can use onkeyup

<input id="name" onkeyup="checkLength(this.value)" />
Bladdernut answered 18/8, 2011 at 10:33 Comment(1)
I have used onkeyup...but my problem is when the user selects from the autocompleter of the browser, then this event is not triggered...I have already written this in my question in the workaround i used...Slumberous
W
0

You would have to use a combination of onkeyup and onclick (or onmouseup) if you want to catch every possibility.

<input id="name" onkeyup="checkLength(this.value)" onmouseup="checkLength(this.value)" />
Webber answered 18/8, 2011 at 10:36 Comment(3)
nice try, but the issue here is that I am not pressing mouse on the input element but on the auto-completer, which will not trigger this event...Slumberous
The only other thing I can think of, and it is nasty nasty, is to setTimeout and periodically check the value of the field... What exactly are you wanting to do?Webber
Thats very nasty...:D it is something similar to what a password strength indicator does, it tells you the strength of the password as you keep entering into it. I want to enable a button only when the entered string is of length 10 else keep it disabled. I hope you got it...Slumberous
M
0

Here is another solution I develop for the same problem. However I use many input boxes so I keep old value as an user-defined attribute of the elements itself: "data-value". Using jQuery it is so easy to manage.

        $(document).delegate('.filterBox', 'keyup', { self: this }, function (e) {
            var self = e.data.self;

            if (e.keyCode == 13) {
                e.preventDefault();
                $(this).attr('data-value', $(this).val());
                self.filterBy(this, true)
            }
            else if (e.keyCode == 27) {
                $(this).val('');
                $(this).attr('data-value', '');
                self.filterBy(this, true)
            }
            else {
                if ($(this).attr('data-value') != $(this).val()) {
                    $(this).attr('data-value', $(this).val());
                    self.filterBy(this);
                }
            }
        });

here is, I used 5-6 input boxes have class 'filterBox', I make filterBy method run only if data-value is different than its own value.

Mella answered 17/5, 2012 at 12:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.