Feature detection vs browser detection



In a recent thread in this group, I said that in some cases object
detection and feature tests weren't sufficient in the development of
cross-browser applications, and that there were situations where you
could improve the application by detecting the browser vendor/version.
Some of the posters here disagreed. Since then, I've had to deal with a
few of these cases; some of them could be rewritten to use object
detection, and some couldn't. I'd like to present a selection of these
cases here, and ask your opinion about how to accomplish the required
features without browser detection.

To avoid unnecessary side-tracking in the discussion, let me state in
advance that

- I fully understand that object detection and feature tests are to be
used whenever possible. I've never said otherwise (check the archives).

- I completely agree that many popular libraries and scripts rely far
too heavily on browser sniffing. I agree that this is in most cases
unnecessary and invites problems in the future.

- I'm not necessarily talking about parsing the user agent string. There
are often more reliable ways to detect the UA, especially for the most
problematic one (MSIE).

- When I'm proposing the use of browser detection, I'm doing it to
improve the user experience on older browsers. These old versions have
bugs and quirks that are well known and can be avoided or worked around.
I am *not* trying to predict how a future version of a browser is going
to behave.

- Usually I am not in a position to decide what is or isn't a reasonable
feature request. The client wants a feature; I say that it could break
in older browsers unless I do something that might become a problem with
future releases; they say go ahead - the competition is doing it too,
we'll deal with the problem when it's there.

- In my opinion, a UA that pretends to be something else, and goes as
far as to implement and mimick another UA's proprietary objects and
behaviors, wants to be treated as that UA. If it can't handle it, that's
not my problem anymore, and outside of my control (classic user error).
Again, I'm not talking about sniffing the UA string.


That said, here are the cases where I'm having trouble with the "pure"
object detection methods:


Case #1: Too much data in memory
--------------------------------

In one application, we're using a custom grid control with features
similar to a spreadsheet, that is used to view and edit data in tables
with several 100k of rows, sometimes more than 1M, without paging. Of
course, we can't display all that data at once, so we fetch the relevant
area via XHR. The server-side action to retrieve that data is very
processor intensive, and the performance is best when there are as few
requests as possible. Fewer requests means fetching a larger chunk of
data at once. Experience with this application has shown that the
overall responsivity of the browser deteriorates when too many elements
are displayed or kept in memory at once. MSIE6 is by far the worst
performer here, IE7 is better but still far behind the competition. So
what we're doing in this case is *determine the user agent* and then
decide how much data to fetch to get an optimal trade-off between server
delay and browser sluggishness. How could I do that without browser
sniffing?


Case #2: Designer relies on :hover
----------------------------------

Different application, still intranet. This one was designed for use
with IE7, and the designer used the :hover pseudo-class to show or hide
additional information (the dev team uses different browsers, but they
all handle :hover on any element correctly). Unfortunately, after a
corporate merger there are now users who are still using IE6, which
doesn't support :hover anywhere. Now we could either change the whole UI
design (pretty huge task in this case), or add a few event handlers to
support IE6 as well. We went with the event handlers, which took about
one day for the whole application. How could we handle this without
checking the browser version?


Case #3: Alpha support
----------------------

I'll keep this short, because I've already mentioned it here before.
Same application as #2, design relies on the PNG alpha channel for
flashy things like drop shadows and composite images. Transparent GIFs
are not good enough. IE6 can be made to understand alpha transparency
with a little ugly hack, but we wouldn't want to do that for all UAs.
Why not check for IE6 and apply the hack only when necessary?


Case #4: Memory leaks
---------------------

IE still, after all this time, has horrible memory leaks (circular
references between JScript objects and COM objects). If the application
provides a common way to register event handlers, they can be purged on
unload. I admit, I haven't timed this exactly, but on a JS-driven page
with a lot of event handlers that's going to take a while. How do I find
out if it's necessary to clear all existing event handlers if I can't
check for IE?


Case #5: How to recognize that the DOM is safe for scripting?
-------------------------------------------------------------

There are many different strategies for detecting the point in time when
the DOM can be modified (before window.onload), and most of them try to
use the most efficient strategy for the current UA. I've tried to make
this process UA-agnostic, but I don't think it can be done reliably
without unreasonable assumptions. Here's a short example (attach_ is a
generic wrapper for addEventListener/attachEvent):

// this shouldn't hurt if the UA doesn't know the event:
attach_(document, "DOMContentLoaded", handleReady);

// use polling for UA's who don't
// [but we shouldn't have to, if only we could use browser detection]
initReadyPolling();

/*
what initReadyPolling could do:
- in Safari, we can trust the document.readyState values of "loaded"
and "complete" (as far as the released versions are concerned)
- in MSIE, we can't trust "loaded". We could trust "complete", but that
won't help much, since it fires about the same time as window:load.
- Mozilla (AFAIK, I might be wrong here) doesn't have useful values in
document.readyState at all.
- In YUI, they attempt to apply the proprietary doScroll() on a dummy
element on each poll for IE, and when it doesn't throw an exception,
the DOM is ready
*/

// if all else fails, try to get the window's load event
attach_(window, "load", handleLoad); // handleLoad calls handleReady

I realize this is sub-optimal (and yes, I've read Peter Michaux's
excellent articles on this subject). There are so many browser
dependencies in initReadyPolling that any attempt to avoid UA sniffing
would rely on current circumstantial evidence (for example, if
attachEventListener is available, don't go the IE route). What if MS
decided to support the W3C event model?


Case #6: Various browser bugs
-----------------------------

Specific versions of browsers are known to have bugs and quirks that
could be addressed if we knew which browser/version we're dealing with.
There's a lot of different bugs in this category; let me use two of them
as examples:

1) Older Safari versions returned Mac-specific key codes for
keydown/up/press events (63232 instead of 38 for ArrowUp, 63234 instead
of 37 for ArrowLeft, etc). There are also cases where different (normal)
key codes are returned if a modifier key is pressed.

2) With XHR requests, IE sometimes returns the HTTP status code as 1223
instead of 204. That wouldn't could as a "success" code (2xx), and has
to be dealt with specially.

In the case of those two exemplary bugs it won't hurt much to just
accept the different numeric values and translate them, but you can see
where I'm going. These are bugs that can't be feature tested.


Those are just the situations I encountered since the last discussion. I
decided not to post in that thread again, because I'm not interested in
flame wars. Still, I think it's worthwhile to discuss this topic on its own.


- Conrad


PS: Before I forget it, Garrett was absolutely correct in mentioning
that the outerHTML test in my previous posted example needed to be case
insensitive. Unfortunately, the other suggestions, while interesting,
couldn't be applied to radio buttons, so that would be my Case #7, if
the workaround with outerHTML is deemed unacceptable.
.



Relevant Pages

  • Re: Feature detection vs browser detection
    ... could improve the application by detecting the browser vendor/version. ... detection, and some couldn't. ... Some things can be feature detected and/or tested, ... A better question is how you think browser sniffing would help in this ...
    (comp.lang.javascript)
  • Re: Help Jquery: unable to register a ready function
    ... A separate registry can be used for custom events or legacy DOM events e.g. "onclick". ... That doesn't make a case that object detection is sometimes not possible. ... Concluding that there is no remaining option but to check the browser ... Feature detection doesn't get interesting until a browser supports a ...
    (comp.lang.javascript)
  • Re: browsers & standards
    ... > Richard Cornford wrote: ... > Would that not more accurately be called "Feature verification"? ... The name has its roots in 'object detection' which was the preferred ... It is certainly superior to browser ...
    (comp.lang.javascript)
  • Re: FAQ Topic - How do I detect Opera/Netscape/IE?
    ... you wish to use is supported by the browser before using it. ... That's Object detection. ... Isn't the object a feature of the browser's object model? ... So feature detection does encompass both. ...
    (comp.lang.javascript)
  • [kde] Re: KDEPIM 4.6 prob^Wimpressions
    ... Did you file a feature request? ... X or the akonadi processes (right at this very moment: ... browser engine is not that good, ... I don't miss filters at all. ...
    (KDE)