Detect DOMContentLoaded - possible?

262 views
Skip to first unread message

dhtmlk...@gmail.com

unread,
Oct 16, 2007, 2:59:23 PM10/16/07
to
How to feature detect DOMContentLoaded?

I investigated
document.implementation.hasFeature
document.isSupported

Didn't find anything that looks like it would imply support of
DOMContentLoaded.

The libraries are using Browser detection. It seems that browser
detection fell out of style around 2002, but is now back in style.

I want to detect support, not browser, so I'd want something like

typeof window.somefeature == "function"

dhtmlk...@gmail.com

unread,
Oct 16, 2007, 7:31:53 PM10/16/07
to
On Oct 16, 11:59 am, "dhtmlkitc...@gmail.com" <dhtmlkitc...@gmail.com>
wrote:

> How to feature detect DOMContentLoaded?

It is possible to know if DOMContentLoaded has fired, after the page
loads (onload). I am keeping a variable in closed scope. Clunky but it
works.

David Mark

unread,
Oct 16, 2007, 8:21:16 PM10/16/07
to
On Oct 16, 2:59 pm, "dhtmlkitc...@gmail.com" <dhtmlkitc...@gmail.com>
wrote:

> How to feature detect DOMContentLoaded?

I assume you mean in IE, Safari, etc. (browsers that do not support
that event.)

>
> I investigated
> document.implementation.hasFeature
> document.isSupported
>
> Didn't find anything that looks like it would imply support of
> DOMContentLoaded.
>
> The libraries are using Browser detection. It seems that browser
> detection fell out of style around 2002, but is now back in style.

It is less viable today than in 2002.

>
> I want to detect support, not browser, so I'd want something like
>
> typeof window.somefeature == "function"

What is it you want to do? If you just want your scripted interface
elements to respond before assets finish loading, that is easy (with
one IE-specific catch.)

Attach a handler to the DOMContentLoaded event (won't hurt browsers
that don't support it) and to the load event. Use a flag to make sure
it doesn't run more than once. Put a script just before the closing
body tag to call this function on a timeout.

This doesn't exactly match DOMContentLoaded as under some
circumstances (eg a page with no assets), your initialization may run
after the page is fully loaded. But if there are assets to download,
it will make your page interactive without waiting around for the load
event. You still need to take care to hide and/or disable interface
elements that will not be functional until after your initialization
runs. And if you have scripts that attach listeners to the load
event, you must take into account that the onload handlers may run
before your simulated DOMContentLoaded event fires. I've never run
into a situation where it is necessary to use the load event (other
than as a fallback for the DOMContentLoaded/timeout solution), but it
would be trivial to add a queue for onload handlers that are run only
after the DOMContentLoaded queue has been processed. You could even
poll document.readyState (if it is detected to be a string) to defer
the processing of the onload queue until the document has completed
loading.

The one caveat for IE is that if you need to append children directly
to the body element, you could get the dreaded "Operation Aborted"
error in IE6. I have never seen this happen using this method with a
10ms delay, but that doesn't mean it is impossible. If you can't
append to a container other than the body, you can poll the innerHTML
property of the body and watch for </body>, at which time it will be
safe to manipulate the body element directly.

Then there is the method used by most of the libraries, which involves
browser sniffing and document.write. They "detect" IE (sometimes with
conditional compilation, sometimes with userAgent parsing), write a
deferred script tag, attach a readystatechange handler to the newly
created element and wait for it to indicate that it has finished
loading. The userAgent parsing will fail for IE imitators,
document.write will fail for XHTML documents and any variation of
behavior in deferred script loading will throw the whole thing off.
And of course, this IE-only method leaves Safari (and others) out, so
an interval is used to poll document.readyState. Typically browser
sniffing is used to "detect" Safari and Konquerer (and nothing else)
before setting this interval, so anything with an unexpected userAgent
string is left waiting around for the load event. And like the other
solution, there is no guarantee that the psuedo-DOMContentReady event
will fire before the load event.

Thomas 'PointedEars' Lahn

unread,
Oct 17, 2007, 4:09:03 PM10/17/07
to
dhtmlk...@gmail.com wrote:
> How to feature detect DOMContentLoaded?

First Google hit:

,-<http://dean.edwards.name/weblog/2005/02/order-of-events/>
|
| Aaron Boodman (the author of Greasemonkey) said:
|
| I finally discovered DOMContentLoaded event. It’s an undocument,
| proprietary event that Mozilla throws and which is accessible from
| script when, um, the dom’s content is loaded (that is, before all
| the images and what not have loaded).

> I investigated
> document.implementation.hasFeature
> document.isSupported

document.implementation implements the DOMImplementation interface of
the W3C DOM, and it checks for features of the W3C DOM.

document.isSupported is an implemented method of the Node interface of
W3C DOM Level 2 Core, and it checks for features of the W3C DOM.

It is no surprise that support for the proprietary event cannot be detected
this way.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

dhtmlk...@gmail.com

unread,
Oct 17, 2007, 5:20:13 PM10/17/07
to
On Oct 17, 1:09 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> dhtmlkitc...@gmail.com wrote:
> > How to feature detect DOMContentLoaded?
>
> First Google hit:
>
> ,-<http://dean.edwards.name/weblog/2005/02/order-of-events/>
> |
> | Aaron Boodman (the author of Greasemonkey) said:
> |
> | I finally discovered DOMContentLoaded event. It's an undocument,
> | proprietary event that Mozilla throws and which is accessible from
> | script when, um, the dom's content is loaded (that is, before all
> | the images and what not have loaded).
>
> > I investigated
> > document.implementation.hasFeature
> > document.isSupported
>
> document.implementation implements the DOMImplementation interface of
> the W3C DOM, and it checks for features of the W3C DOM.
>
> document.isSupported is an implemented method of the Node interface of
> W3C DOM Level 2 Core, and it checks for features of the W3C DOM.
>
> It is no surprise that support for the proprietary event cannot be detected
> this way.
>

As-is, I've got something along the lines of:


fired = false

var fallBack = function() {
if(!fired)
alert('DOMContentLoaded did not fire.');
}

addEventListener("DOMContentLoaded" function(){fired=true;}, false);
addEventListener("load" function(){fired=true;}, false);


The real code is a little more involved, but that's the idea of it.

> PointedEars
> --


dhtmlk...@gmail.com

unread,
Nov 2, 2007, 11:09:17 PM11/2/07
to
Ok, so what I have now, is a simple interface along the lines of

EventPublisher.get(ContentLoadAdapter, "loaded").add(loadHandler);
function loadHandler(e) { alert(e.type); } // custom event, where
necessary.

It uses no browser detection.

So who's got an IE6 that wants to test it out?

You should see an alert box before the gorilla loads.

http://dhtmlkitchen.com/learn/js/load/index.jsp
http://dhtmlkitchen.com/learn/js/load/index.html

I tried the doScroll event, but then I thought I'd try readyState on
documentElement for IE. And surprise - It works! If I do have to use
the doScroll for IE6, I will try it on the document.scripts[0] and see
if that fires at the right time. document.scripts will exist in IE,
only in IE, and document.scripts[0] supports doScroll, while having no
visual effect. So if the current code doesn't have the desired result
in IE6, then I'll add the code for doScroll.


Randy Webb

unread,
Nov 2, 2007, 11:37:49 PM11/2/07
to
dhtmlk...@gmail.com said the following on 11/2/2007 11:09 PM:

<snip>


> document.scripts will exist in IE, only in IE, and document.scripts[0]

You may want to test that belief in Opera before believing it is "only
in IE".

alert(document.scripts)

[object HTMLCollection]

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

dhtmlk...@gmail.com

unread,
Nov 4, 2007, 12:55:38 AM11/4/07
to
On Nov 2, 8:37 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
> dhtmlkitc...@gmail.com said the following on 11/2/2007 11:09 PM:

>
> <snip>
>
> > document.scripts will exist in IE, only in IE, and document.scripts[0]
>
> You may want to test that belief in Opera before believing it is "only
> in IE".
>
Good point. Opera doesn't support doScroll on a script, though. IE
does.

javascript:alert(document.scripts[0].doScroll)

But even if it did, there wouldn't be a double fire because of the way
I wrote it. fireOnce only fires once.

I'd really like to know what happens in IE6. WHo wants to try & test?

Randy Webb

unread,
Nov 4, 2007, 2:35:14 AM11/4/07
to
dhtmlk...@gmail.com said the following on 11/4/2007 12:55 AM:

> On Nov 2, 8:37 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>> dhtmlkitc...@gmail.com said the following on 11/2/2007 11:09 PM:
>>
>> <snip>
>>
>>> document.scripts will exist in IE, only in IE, and document.scripts[0]
>> You may want to test that belief in Opera before believing it is "only
>> in IE".
>>
> Good point.

And that was my only point. Anybody that didn't know better might have
read your post and - incorrectly - assumed that document.scripts is IE
only when it isn't.

And no, I do not have IE6.

Diego Perini

unread,
Nov 6, 2007, 1:03:47 PM11/6/07
to
On Nov 3, 4:09 am, "dhtmlkitc...@gmail.com" <dhtmlkitc...@gmail.com>
wrote:

> Ok, so what I have now, is a simple interface along the lines of
>
> EventPublisher.get(ContentLoadAdapter, "loaded").add(loadHandler);
> function loadHandler(e) { alert(e.type); } // custom event, where
> necessary.
>
> It uses no browser detection.
>
> So who's got an IE6 that wants to test it out?
>
> You should see an alert box before the gorilla loads.
>
> http://dhtmlkitchen.com/learn/js/load/index.jsphttp://dhtmlkitchen.com/learn/js/load/index.html

>
> I tried the doScroll event, but then I thought I'd try readyState on
> documentElement for IE. And surprise - It works! If I do have to use
> the doScroll for IE6, I will try it on the document.scripts[0] and see
> if that fires at the right time. document.scripts will exist in IE,
> only in IE, and document.scripts[0] supports doScroll, while having no
> visual effect. So if the current code doesn't have the desired result
> in IE6, then I'll add the code for doScroll.

I have done some test with the above links in IE6 and IE7.
I get reproducible errors with both the HTML and the JSP
pages, and I got the following description messages:

a) from an about:blank page completely cleaned the cache
first load of the JSP page, click on the alert box then get

Line: 0
Error: 'contentScripts.style' is null or not an object

this continuously happens even with Reload/Refresh F5/CTRL-R,

b) after fiddling a bit with the Backward/Forward buttons
once every two/three landings in the HTML page, i get

Line: 56
Error: 'document.getElementById(...)' is null or not an object

this does not happens if the page is Reloaded/Refreshed itself,
it seem it happens more frequently with Backward/Forward, with
the GO button and typing the URL directly in the browser, after
the page is already cached.

Please give a try to the doScroll() method for IE, I don't like
browser branching either, if it where I had that choice !!!

I strongly believe we should split the problem in to pieces to
really benefit of a snippet that cover the cases that are not
well covered with the existing solutions.

In IE first choice should be the HTC method, the next option, if
we are not dealing with IFRAMEs, would be the doScroll(), in case
of IFRAMEs the doScroll() method is not usable, so we only have
two other choices for IE:

- when document.readyState is interactive (for WIDGETS to work)
- when document.readyState is complete (for SELECTORS to work)

These two states must be checked in combination because sometime
only the complete state will be reached, but will ensure that
one of them will always fire before the standard onload.

Finally an onload fall back will be good to catch other cases.

These events/timeout should all converge in a call to a single
init() function, where we should make sure to only fire once.


Diego


Reply all
Reply to author
Forward
0 new messages