[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 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.
If documentElementsByTagName may be undefined then the above ternary
conditional will error in browsers where it is undefined. I think it
should be
(typeof documentElementsByTagName != 'undefined')?
documentElementsByTagName('html', docNode)
If you mean that documentElementsByTagName has never been declared,
that is impossible in the context this code came from (it is a
declared variable.) It may have an undefined value, but that won't
throw an error.
[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? 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.
Of the browsers I checked that can set opacity, only IE4 and Opera 6-
don't have document.documentElement. I don't mind degrading those
browsers to not use opacity setting. This would make the setOpacity
and all other functions requiring an element for feature testing not
dependent on an htmlElement function like you've outlined. In my eyes,
Opacity yes, but all other style-related functions? That seems
extreme. 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?
that is a nice reduction in code size. Code always might contain bugs
and needs testing as we have seen even here (not meant as criticism
but as an argument to reduce code size where reasonable). I think that
Well, it turned out that it wasn't a bug, but I get your point.
only checking for document.documentElement is a reasonable place to
draw the line in browser history given the approximate distribution of
browser version in use today. Any non-trivial CSS that may need the
fallbacks in the htmlElement function for a feature tests likely won't
work in IE4 anyway. Sound reasonable?
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. 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]?) If not, can it get
any element during page load?
As a reference for this threshold, I don't wrap document.all and
document.getElementById together in a function. I just check for
document.getElementById.
I still allow for the use of document.all when gEBI isn't present, but
I did remove support for document.layers a few years back.