How to identify buggy behavior in "input" event without browser detection?
Asked Answered
S

2

8

I'll start with the question. When a specific browser has a buggy implementation of a feature and your javascript needs to know whether the current browser has that buggy implementation or not so it can use an alternate strategy, how do you figure out if the implementation is buggy without doing browser type sniffing (which is generally considered bad)?

Here's the whole situation.

I was working on some code that wants to use the "input" event for getting notifications of user changes to an <input type="text"> field (works much more live than the "change" event), but when that event isn't supported, it uses a much more complicated scheme involving a bunch of other events.

Since the "input" event is only supported in some browsers, I went in search of a way to do feature detection for the event (rather than browser user agent sniffing) since feature detection is generally a more robust way of doing things. As such, I came across this great article for doing exactly that and this code seems to work:

var isEventSupported = (function(){
    var TAGNAMES = {
      'select':'input','change':'input',
      'submit':'form','reset':'form',
      'error':'img','load':'img','abort':'img'
    }
    function isEventSupported(eventName) {
      var el = document.createElement(TAGNAMES[eventName] || 'div');
      eventName = 'on' + eventName;
      var isSupported = (eventName in el);
      if (!isSupported) {
        el.setAttribute(eventName, 'return;');
        isSupported = typeof el[eventName] == 'function';
      }
      el = null;
      return isSupported;
    }
    return isEventSupported;
  })();

Then, I ran into problems with IE (surprise, surprise). While IE purports to support the "input" event and it passes the feature test above and it works most of the time, IE's support is buggy as hell. It doesn't even trigger the event when the user hits the backspace key (among other missing behaviors). As such, I can't rely on it in IE. So, I had built this nice clean code that did a feature test for the "input" event and uses it's very clean implementation when present and when not present used this much uglier work-around involving monitoring eight other events. Now, it's busted in IE because the feature test for the "input" event passes so the code attempts to use it, but it's buggy as hell so it doesn't work.

Since these IE bugs show up on user actions, I can't think of any way to devise a javascript feature test to identify the buggy behavior. As such, my only current path is to resort to browser sniffing and refuse to rely on the "input" tag if the browser is IE.

Are there any options here for identifying the buggy behavior in the "input" event besides browser sniffing? If one had to do browser sniffing, is there a way to identify IE by behavior rather than a user agent string that can be freely spoofed and isn't guaranteed to be accurate?

Scythia answered 29/8, 2012 at 6:53 Comment(6)
One good thing (maybe the only?) with IE is conditional comments where you can put IE-specific code to solve your problem.Bloodroot
Here's is a good oninput event article. Unfortunately there doesn't seem to be a good alternative in IE, so even if you can detect it, there's not a lot you can do. Web developers have been doing without oninput for a long time, so if you update your question to state what you are trying to do, alternatives can be suggested.Alcoholic
@Alcoholic - I'm trying to implement some dynamic behavior that responds no matter how an input field is changed. Web developers have been doing without a reliable input event by just accepting an imperfect implementation that doesn't trigger on drag/drop or when the field is changed via the context menu and so on. I'm trying to do better than has been done before.Scythia
Can you not just use keydown? Am I missing something?Impropriety
@Impropriety - keydown misses a bunch of ways the user can change an input field such as drag/drop, right-click cut/copy/paste. In fact to cover all forms of user change, I end up monitoring 6 other events besides keydown.Scythia
Have you considered bypassing the test altogether and applying your solution as a universal override or extension of the implementation, thereby having full control of the critical resource? Also, I'm not sure that browser detection is actually a bad thing. MS has made it manditory for proper end-user experiences, and if it were me I'd test for IE and where found force the functionality through the target's prototype.Purdah
A
1

jamie-pate suggest something like this:

   var broken = false,
        ta = angular.element('<textarea>').on('input', function(evt) {
            broken = true;
        });
    ta.attr('placeholder', 'IESUCKS');

So you can check for "supports input event and is not 'broken'" in your code.

See https://github.com/angular/angular.js/issues/2614?source=c

Aftermost answered 8/1, 2014 at 15:15 Comment(0)
L
0

If you are interested in a cross-browser "input change" event, here is my implementation:

function onInputChange(domInput, callback) {
    if (domInput.addEventListener) {
        domInput.addEventListener('input', callback, false); // Firefox, etc.
    } else if (domInput.attachEvent) {
        domInput.attachEvent('onpropertychange', callback); // IE
    }
}


Usage example:

var leInput = document.getElementById('myInput');
var leCallback = function () {
    // awesome stuff here
};

onInputChange(leInput, leCallback);


Works in all browsers, supports keyboard input and copy/paste.

However there is the exception of that cursed IE9, which didn't exist at the time I wrote the above code. Would Microsoft ever consider fixing their bug? :\

Lamb answered 31/8, 2012 at 15:4 Comment(1)
Thx, not exactly what I'm looking for and has the specific problem I asked this question about in IE9 which supports both addEventListener() and the input event, but the input event behavior is buggy as hell.Scythia

© 2022 - 2024 — McMap. All rights reserved.