D
David Mark
[snip]
A couple other notes.
The original stand-alone version tested for the existence of the style
object. The recently posted version comes from a module that checks
that elsewhere. So that check should be added.
And seeing that Opera 5/6 refuse to find the html element using gEBTN
or the all object, I updated my code to use the previously posted
check of all[0] and all[1] if the html variable cannot be set any
other way. That branch will only run for Opera 5/6 or antiquated
mobile browsers and is only a couple of extra lines. It is a moot
point for this example if Opera 5/6 do not support opacity, but the
function that finds the html element is crucial for lots of other
feature tests (at least if they are to be run in the head of the
document.)
If this is to be added to your repository, it would be a good
foundation for it and other style-related code to have functions that
find the html element for a given document and determine if the host
is capable of CSS manipulation by testing for the presence of the
element's style object.
Would you mind posting your function that finds the html element?
Okay. I just updated it this morning and haven't had time to test it
thoroughly.
var doc = this.document;
var isRealObject = function(o) {
return !!(o && typeof(o) == 'object');
};
var htmlElement = function(docNode) {
var html;
docNode = docNode || doc;
html = isRealObject(docNode.documentElement)
If docNode.documentElement is defined, will it ever be any type other
than 'object'? It seems like checking this is unnecessary if there has
never been a known problem.There is the possibility, however remote, that it could be a null
object.
I asked about this sort of testing on c.l.js a when I was first
venturing into feature testing. I thought I'd have to test everything.
If document.getElementsById is present then I'd have to check if it
was callable before calling it. There is a chance it may not be
callable; however, since this situation has never been observed, the
For that host object methods I use:
isFeature = function(o) {
return !!(o && (typeof(o) == 'object' || typeof(o) == 'function'));
};
This is because there is no reliable way to determine if host object
methods are callable.
general feeling was to trust is it callable until it is observed to be
not callable in at least one browser. Feature testing even when no
problems has ever been observed could balloon the feature tests to
hugely paranoid proportions.
I agree.
That said, I understand you may have had the isRealObject function
around for another situation and it was just handy to use in this
case.
Yes, it is used by lots of functions.
[snip]
[0]:null);
if (!html && docNode.all && docNode.all[0]) {
html = docNode.all[(docNode.all[0].tagName == '!')?1:0] || null;
if (html && html.tagName.toLowerCase() != 'html') { html = null; }
}
return html;
};
The missing documentElementsByTagName function is a wrapper for gEBTN
that only exists if the document object features such a method. It
exists to smooth out problems with the "*" parameter, as well as using
the all object for agents that don't feature gEBTN. It isn't really
needed now that the additional clause has been added to handle Opera
5/6, so you should just change it to doc.getElementsByTagName.
When I looked at document.documentElement, document.all.tags and
document.getElementsByTagName, I stated that in IE4
document.all.tags('html').length is 1. That is only true after
window.onload fires. Before window.onload the length is 0. Since
feature testing is preferably done in the head right when the script
loads, the document.all.tags check isn't really enabling any
particular browsers, as far as I know. This goes along with your "It
isn't really needed now...."Were all of those results determined after onload?
Yes
If so, I would
like to see what they look like when run in the head. Regardless, I
assume that document.all[0] is defined before the onload event fires,
so the added test should be sufficient.
The added test seems to be fine in IE4 at least with the HTML page I
tested.
That's good to know.
Can you think of an example of a browser without
document.documentElement where style-related functions would work if
the document.all fallback is used for testing? Do the entire scripts
associated with these style-related functions work in these browsers?
For example, a function that shows and/or hides elements. The
requirements are that CSS is supported (style object exists) and
visibility can be adjusted by script (the visibility property of the
style object is a string.) I don't think it would make sense to
exclude IE4, Opera 5/6, etc. from using such a function. Another
example is a function that adds and/or removes elements from the
layout, which requires a working display property. Also, a function
that attaches a listener for drag and drop operations requires a
working position property (assuming it needs to work with statically
positioned elements.) All three of these examples can be written to
work with IE4, and two of the three can work with Opera 5/6 (IIRC,
those browsers cannot update the display property.)
Also, there is no reason why such functions can't run after
the body has been parsed (e.g. in a real or simulated DOMContentLoaded
listener.) I do that for several functions that have to create
elements and append them to the body to detect quirks like Opera's
botched offsetLeft/Top reporting. It seems like setOpacity is
something that wouldn't be needed until the document is ready, else
how would you reliably find the element you want to fade?
Since document.all[0] or document.all[1] seems to work in the head
this point may be moot.
For these examples yes. Other functionality (e.g. calculating an
element's offset position) require feature detection to occur after
the closing body tag has been parsed (thanks to IE's ridiculous
"Operation Aborted" bug.) I haven't found this to be a hindrance as I
never reference DOM nodes before the document is ready anyway (let
alone try to compute their position.)
[snip]
Sort of. How would a script determine if CSS is even available when
running in IE4, Opera 6, etc.? One of the first flags I set is based
on the presence of a style object. If it doesn't exist then lots of
unneeded feature testing is skipped and style-related functions are
not created. Next I check the types of the display, visibility and
position properties of the object (typically strings, but not always)
and those three results determine which style-related modules should
be initialized.
This is exactly the direction in which I'd like to go with this code
repository.
Seeing as you are like-minded and are willing to handle the
documentation and administration of the project, I am willing to help
you fill it up one function at a time. I've got a module for
virtually everything and they all use similar feature detection. It
will take a while, but eventually the result will be a competent
alternative to dreck like jQuery. I for one am tired of seeing
constant script errors in IE every time I browse the Web. I can't
imagine what the Web is like in less-supported agents. It must be
hell for mobile users, people who never upgrade their browsers, Mac
users, etc.
They are also referenced by applications to determine
if it is possible to hide dynamically replaced content during the page
load (i.e. if a style rule is added before the body is parsed, will it
be possible to overrule it with an inline style once the content is
replaced after parsing.) Can you confirm if IE4 can get the HTML
element via document.all[0] (or document.all[1]?)
It can.
That's good to know.
How many of your pages have enabled JavaScript functionality because
of these archaic checks and how many actual visitors benefit? If there
I can't get IE4 to load in XP for some reason and AFAIK, nobody uses
anything I write with IE4 (or Opera 5/6.) I figure a couple of extra
lines doesn't hurt and allows very simple enhancements (e.g. hiding
and showing elements) to work with older mobile devices.
are pages that do become enabled with these checks that would not
become enabled with the modern checks only, it still may be better
overall (faster download times, less code to maintain) to just slide
these down the degradation path given how few users benefit. They
still do get a perfectly working HTML page, after all.
Yes, I agree with that, especially since most widgets I build with my
API have requirements that are beyond the ancient browsers (e.g.
Function.prototype.call.) So despite the fact that basic style-
related functions are available to browsers like IE4, they typically
don't get the chance to use them (the test for call short circuits the
widgets' initialization.)
I think setting the feature threshold at document.getElementById and
document.documentElement is ok today. If there is outrage over this
then the code repository could allow for the the document.all
fallbacks. I cringe a little when I type that thought. I strongly vote
we go "modern" (NN6 November 2000, IE5.5 July 2000).
I'd say that makes sense. I can't remember when Opera 7 was released
though. It seems like it was a two or three years into the century.
I've heard that some older mobile devices use an Opera 6 image, but
those will probably all be in landfills soon (if not already.)