You are not logged in.

  • Login

Dear visitor, welcome to Coder Forum. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

Saturday, September 12th 2009, 11:29am

Tags

Browser, crossbrowser, DOMContentLoaded, Firefox, internet explorer, onload, onreadystatechange, ready

Abstract

Wir wollen ein JavaScript ausführen, nachdem die Seite fertig geladen wurde.
Doch das herkömmliche "Seite geladen" ist zu langsam - da dies erst geschieht, wenn auch alle externen Quellen wie Bilder fertig sind.
Um den Event auszuführen nachdem die Hauptseite fertig ist, gibt es für jeden Browser einen eigenen Weg - hier wird eine Plattformunabhängige Lösung vorgestellt.

Article

1. Hinweis


Dieser Artikel ist noch nicht fertiggestellt

2. Einführung


Will man JavaScript Code ausführen, nachdem die Seite fertig geladen wurde benutzt man im Normalfall das onload Event im Body.

HTML Code

1
<body onload="alert('hello world')">


Leider führen unterschiedliche Browser diese Funktion zu unterschiedlichen Zeitpunkten aus.
Hat man nun umfangreiche, externe Quellen eingebunden (z.B. Kartenmaterial von Google Maps) dann wird die Funktion erst sehr spät ausgeführt.

3. Beispiel


Das folgende Beispiel ist so bearbeitet, dass ein Bild für 5 Sekunden lädt. Das eigentliche Script wird also (mit den meisten Browsern) erst nach 5 Sekunden ausgeführt.
http://demo.easy-coding.de/javascript/on…ser/regular.php

4. Firefox Lösung


Der Firefox kennt das Event "DOMContentLoaded" (Mozilla Dokumentation), das ausgeführt wird wenn der HTML Code fertig interpretiert wurde. Damit hängt man sich vor nachgelagerte Scripte oder eingebundene Bilder.

JavaScript Code

1
2
3
document.addEventListener("DOMContentLoaded", function(){
	alert('firefox sagt: fertig');
}, false);


5. Internet Explorer Workaround


Wofür der Firefox Lösungen bietet, hat der Internet Explorer leider nur Workarounds.
Diese reichen über das mittels "defer" verzögerte Einhängen von externen <script> Elementen bis hin zu einem "Linksscrollen" das erst funktioniert, wenn die Seite fertig geladen wurde. Da das einhängen externer Scripte mehr Ressourcen verbraucht hat sich das JavaScript Framework jquery (in Version 1.3.2) für letzten Workaround entschieden.

Daher wird er auch hier behandelt.

JavaScript Code

1
2
3
4
5
6
7
8
9
10
11
(function () {
	try {
		// throws errors until after ondocumentready
		d.documentElement.doScroll('left');
	} catch (e) {
		setTimeout(arguments.callee, 50);
		return;
	}
	// no errors, fire
	alert('internet explorer sagt: fertig');
})();


Microsoft dokumentiert diesen Weg für alle bisher verfügbaren IE Versionen: http://msdn2.microsoft.com/en-us/library/ms531426.aspx.
Durch die Closure um den eigentlichen Event und die Verwendung von arguments.callee, das die Closure referenziert sind wir übrigens in einer Endlosschleife, dir wir im 50 Millisekunden Takt aufrufen.

6. Event Syntax


Wenn das Leben nicht schon schwierig genug wäre, so bieten die verschiedenen Browser noch unterschiedliche Methoden um Events hinzuzufügen.
Diese Problematik wird im Script behandelt, auch wenn in diesem Wiki Artikel nicht darauf eingegangen wird.

7. Event Queue


Die Anforderung an unser Script ist nun einerseits, dass man beliebig viele Events hinzufügen kann - andererseits sollen die Events auch noch gefeuert werden, wenn der Event versucht wird hinzuzufügen nachdem die Seite schon fertig ist.

Dafür gibt es eine Abfrage beim hinzufügen der Events:

JavaScript Code

1
2
3
4
5
6
7
8
9
// If the DOM is already ready
if ( this.isReady )
	// Execute the function immediately
	fn.call( window, this );
 
// Otherwise, remember the function for later
else
	// Add the function to the wait list
	this.readyList.push( fn );


8. Lösung


Das Script ist als ready.js unter MIT/GPL Lizenzierung frei zur Verfügung. Für die produktive Verwendung empfiehlt sich die Verwendung der minimierten Version: ready.min.js (0,4 KB gzipped)
Für Tests könnt ihr außerdem den vollen Quelltext herunterladen: ready.js (3,2 KB)

Nach Einbindung fügt man Funktionen über folgende Syntax hinzu:

HTML Code

1
2
3
4
5
6
<script type="text/javascript" src="ready.min.js"></script>
<script type="text/javascript">
ready.push(function() {
	alert('ready event geladen');
});
</script>


Eine Live Demo findet ihr unter http://demo.easy-coding.de/javascript/on…-cross-browser/.

9. Quelltext


JavaScript Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
 * ready.js
 *
 * Author: Torben Brodt <[email]t.brodt@gmail.com[/email]>
 * Summary: Cross-browser wrapper for DOMContentLoaded
 * Updated: 07/09/2009
 * License: MIT / GPL
 * Version: 1.1
 *
 * URL:
 * [url]http://www.easy-coding.de[/url]
 * [url]http://jquery.com/dev/svn/trunk/jquery/MIT-LICENSE.txt[/url]
 * [url]http://jquery.com/dev/svn/trunk/jquery/GPL-LICENSE.txt[/url]
 *
 * Full Description:
 * A page has loaded after all external resources like images have been loaded.
 * Should all scripts wait for that? a better bevaviour is to wait for the dom content being ready.
 *
 * This script has workarounds for all the big browsers meaning the major versions of firefox, internet explorer, opera, safari and chrome.
 * You can use it without risk, since the normal "onload" behavior is the fallback solution.
 *
 * Most of the source is lended from jquery
 */
var ready = new (function () {
	var readyBound = 0, d = document, w = window, t = this, x;
	t.isReady = 0;
	t.readyList = [];
 
	function bindReady() {
		if ( readyBound ) return;
		readyBound = 1;
 
		// Mozilla, Opera and webkit nightlies currently support this event
		if ( d.addEventListener ) {
			// Use the handy event callback
			x = "DOMContentLoaded";
			d.addEventListener( x, function(){
				d.removeEventListener( x, arguments.callee, false );
				ready.ready();
			}, false );
 
		// If IE event model is used
		} else if ( d.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			x = "onreadystatechange";
			d.attachEvent(x, function(){
				if ( d.readyState === "complete" ) {
					d.detachEvent( x, arguments.callee );
					ready.ready();
				}
			});
 
			// If IE and not an iframe
			// continually check to see if the document is ready
			if ( d.documentElement.doScroll && w == w.top ) (function(){
				if ( t.isReady ) return;
 
				try {
					// If IE is used, use the trick by Diego Perini
					// [url]http://javascript.nwbox.com/IEContentLoaded/[/url]
					d.documentElement.doScroll("left");
				} catch( error ) {
					setTimeout( arguments.callee, 0 );
					return;
				}
 
				// and execute any waiting functions
				ready.ready();
			})();
		}
 
		// A fallback to window.onload, that will always work
		w.onload = ready.ready; // TODO: compliant? t.event.add( window, "load", t.ready );
	};
 
	// Handle when the DOM is ready
	t.ready = function() {
		// Make sure that the DOM is not already loaded
		if ( !t.isReady ) {
			// Remember that the DOM is ready
			t.isReady = 1;
 
			// If there are functions bound, to execute
			if ( t.readyList ) {
				// Execute all of them
				for(var i=0; i<t.readyList.length; i++) {
					t.readyList[i].call( w, t );
				};
 
				// Reset the list of functions
				t.readyList = null;
			}
 
			// Trigger any bound ready events
			d.loaded = true; // TODO: compliant? this(document).triggerHandler("ready");
		}
	};
 
	// adds funtion to readyList if not ready yet, otherwise call immediately
	t.push = function(fn) {
		// Attach the listeners
		bindReady();
 
		// If the DOM is already ready
		if ( t.isReady )
			// Execute the function immediately
			fn.call( w, t );
 
		// Otherwise, remember the function for later
		else
			// Add the function to the wait list
			t.readyList.push( fn );
 
		return t;
	};
})();

Lexikon 4.1.5, developed by www.viecode.com
Besuchen Sie uns auf Google+