HTML5 standardizes the oninput event handler, which should be used to detect user input in JavaScript. Sure, you could use onkeydown or onkeyup instead, but those were never really designed for this particular use case, and it shows.
Luckily, all modern browsers support oninput, IE9 included. For older browsers it’s a good idea to fall back to the keydown event, for example. Unfortunately, detecting oninput support isn’t as straight-forward as you’d think. I assumed this JavaScript snippet would return true or false, depending on whether oninput is supported or not:
'oninput' in document.createElement('input'); This works correctly in most browsers, but not in Firefox (see bug #414853 (now fixed)). While it’s still possible to write a working feature test for oninput, it’s really cumbersome.
Besides, there’s no need to feature test — just bind handlers to both the input and keydown events, and then remove the onkeydown handler as soon as the oninput handler fires. Here’s a simple example, DOM0-style:
someElement.oninput = function() {
this.onkeydown = null;
// Your code goes here
};
someElement.onkeydown = function() {
// Your code goes here
}; The keydown event will only fire once (since it fires before oninput) – after that, only oninput will be used. That’s not ideal, but it sure beats adding lines and lines of code just to properly detect oninput support in all browsers.
A simple demo is available. Note that the same pattern can be applied for any event handler that has a lesser alternative in older browsers.
Comments
Mathias wrote on :
Of course, since you’re probably re-using the same code in both handlers, you could use a separate
function:If you’re using jQuery events, you could use
jQuery#unbind:Here’s a quick jQuery plugin (GitHub repository):
Use it as follows:
Note that namespaced events are used to prevent unbinding other jQuery-bound
keydownevent handlers. Also, in addition tokeydown, you could bind to thecut,pasteanddropevents as well.Zoltan Hawryluk wrote on :
Great idea doing the double
oninput/onkeydowntrick! Coincidentally, I was also doing some research ononinputas well. IE9 has a really annoying bug where backspace and delete (as well as cutting parts out of theinputelement) were not firing theoninputevent. :-( I hope you forgive the shameless self-promotion, but I wrote an article about how to fix this problem, and how I updated my HTML5 forms polyfill, html5Widgets to fix these issues as well as add support in older IEs.Note that this only fixes it in the
<form>element, which I find the most useful since it will fire theoninputevent when any value in any input of the form is modified. I am going to do more research before I fix it for all the others, since I want to research other issues before I support more tags (the Firefox bug you state above may be one of them).Andy Earnshaw wrote on :
I’ve found that
onpropertychangewill give results similar tooninput, so when not using jQuery (which I have a plugin for), I use the following code:Since Firefox and other browsers have supported
oninputfor a while, I decided that detection isn’t really necessary. I would say that I get more IE 6 users on my sites than Firefox 1 or Opera 8 :-) For the ultra paranoid, it would be easy to combine your code with mine and have IE 5.5+ working just as good as Chrome 11, with the fallback in place just in case a visitor happens to be using Opera 8.Tim Down wrote on :
One annoyance is that Safari prior to version 5 doesn’t support the
inputevent fortextareas. It does however support atextinputevent instead.Irfan wrote on :
Hello Mathias,
Considering that mouse related events should — whether they do or not, I do not know — essentially constitute input, as well, hence for those interested in only capturing the keyboard events, would it not unnecessarily increase the workload?
Irfan.