Summary of implementation of DOMReady events in some mainstream JS frameworks

Source: Internet
Author: User

The onload event of window is commonly used, and the actual effect of this event is: when the page parsing/DOM tree is complete, it is triggered only after downloading all the resources in fragments, scripts, style sheets, and iframe. This is a little too late for many practical applications, which affects the user experience. To solve this problem, a DOMContentLoaded method is added to ff. Compared with onload, this method is triggered earlier. It is triggered after the DOM content of the page is loaded, instead of waiting for loading other resources. The Webkit engine has introduced this event since version 525 (Webkit nightly 1/2008: 525 +). Opera also includes this method. So far, mainstream IE still has no meaning to add. Although IE does not exist, there is always a solution. The following compares the compatibility version Implementation Solutions of several mainstream frameworks for this event. The frameworks involved include:
Prototype
JQeury
Moontools
Dojo
Yui
Ext
I. Prototype
Implementation Code
Copy codeThe Code is as follows:
(Function (){
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
Matthias Miller, Dean Edwards and John Resig .*/
Var timer;
Function fireContentLoadedEvent (){
If (document. loaded) return;
If (timer) window. clearInterval (timer );
Document. fire ("dom: loaded ");
Document. loaded = true;
}
If (document. addEventListener ){
If (Prototype. Browser. WebKit ){
Timer = window. setInterval (function (){
If (/loaded | complete/. test (document. readyState ))
FireContentLoadedEvent ();
}, 0 );
Event. observe (window, "load", fireContentLoadedEvent );
} Else {
Document. addEventListener ("DOMContentLoaded ",
FireContentLoadedEvent, false );
}
} Else {
Document. write ("<" + "script id = __ondomcontentloaded defer src = //:> <\/script> ");
$ ("_ OnDOMContentLoaded"). onreadystatechange = function (){
If (this. readyState = "complete "){
This. onreadystatechange = null;
FireContentLoadedEvent ();
}
};
}
})();

The implementation idea is as follows:
If it is webkit, The readyState attribute of the document will be poll. If the value of this attribute is loaded or complete, the DOMContentLoaded event will be triggered. To be safe, register the event to window. onload.
If it is FF, The DOMContentLoaded event is directly registered.
For IE, use document. write to add a script element to the page and set the defer attribute. Finally, the script is loaded as a DOMContentLoaded event.
There are two main problems with this implementation method: first, using document. when the page contains iframe, the method of writing scripts and setting defer will wait until the content in iframe is loaded, which is not much different from onload; 2. The DOMContentLoaded method is introduced in Webkit Versions later than 525. Therefore, in these versions, it can be optimized without polling.
Ii. jQuery
Copy codeThe Code is as follows:
Function bindReady (){
If (readyBound) return;
ReadyBound = true;
// Mozilla, Opera and webkit nightlies currently support this event
If (document. addEventListener ){
// Use the handy event callback
Document. addEventListener ("DOMContentLoaded", function (){
Document. removeEventListener ("DOMContentLoaded", arguments. callee, false );
JQuery. ready ();
}, False );
// If IE event model is used
} Else if (document. attachEvent ){
// Ensure firing before onload,
// Maybe late but safe also for iframes
Document. attachEvent ("onreadystatechange", function (){
If (document. readyState = "complete "){
Document. detachEvent ("onreadystatechange", arguments. callee );
JQuery. ready ();
}
});
// If IE and not an iframe
// Continually check to see if the document is ready
If (document.doc umentElement. doScroll & typeof window. frameElement = "undefined") (function (){
If (jQuery. isReady) return;
Try {
// If IE is used, use the trick by Diego Perini
// Http://javascript.nwbox.com/IEContentLoaded/
Document.doc umentElement. doScroll ("left ");
} Catch (error ){
SetTimeout (arguments. callee, 0 );
Return;
}
// And execute any waiting functions
JQuery. ready ();
})();
}
// A fallback to window. onload, that will always work
JQuery. event. add (window, "load", jQuery. ready );
}

The implementation idea is as follows:
Similarly, Webkit and Firefox are used to directly register the DOMContentLoaded event. However, because Webkit is introduced in Versions later than 525, there is a compatibility risk.
For IE, first register the onreadystatechange event of the document. After testing, this method is equivalent to window. onload and will still be triggered after all resources are downloaded.
After that, if it is IE and the page is not in iframe, The doScroll method of documentElement is continuously called through setTiemout until the call is successful, and DOMContentLoaded is triggered.
JQuery uses a new method for IE solutions, which is derived from http://javascript.nwbox.com/iecontentloaded /. In IE, some DOM methods can be called only after DOM Parsing is complete. doScroll is such a method, in turn, when doScroll can be called, that is, when DOM Parsing is completed, it is consistent with the document in prototype. compared with write, this solution can solve the problem that iframe is invalid on the page. In addition, jQuery seems worried that this method will fail when the page is in iframe, so the implementation code makes a judgment. If it is in iframe, it is implemented through onreadystatechange of document, otherwise, it is implemented through doScroll. However, after testing, even in iframe, doScroll is still valid.
3. Moontools
Copy codeThe Code is as follows:
(Function (){
Var domready = function (){
If (Browser. loaded) return;
Browser. loaded = true;
Window. fireEvent ('domainready ');
Document. fireEvent ('domainready ');
};
If (Browser. Engine. trident ){
Var temp = document. createElement ('div ');
(Function (){
($ Try (function (){
Temp. doScroll ('left ');
Return $ (temp). inject (document. body). set ('html ', 'temp'). dispose ();
}))? Domready (): arguments. callee. delay (50 );
})();
} Else if (Browser. Engine. webkit & Browser. Engine. version <525 ){
(Function (){
(['Loaded', 'complete']. contains (document. readyState ))? Domready (): arguments. callee. delay (50 );
})();
} Else {
Window. addEvent ('load', domready );
Document. addEvent ('domcontentloaded', domready );
}
})();

The implementation idea is as follows:
If it is IE, use the doScroll method.
If it is a Webkit earlier than version 525, it is implemented by polling document. readyState.
Others (FF/Webkit high edition/Opera) register the DOMContentLoaded event directly.
The Moontools Implementation Scheme prototype and jQeury are integrated, and the webkit version judgment makes the scheme more robust. In the implementation of doScroll, compared with jQuery, a new div element is created and destroyed after use, while jQuery directly uses the doScroll of documentElement for detection, it is simpler and more efficient.
4. Dojo
Copy codeThe Code is as follows:
// START DOMContentLoaded
// Mozilla and Opera 9 expose the event we cocould use
If (document. addEventListener ){
// NOTE:
// Due to a threading issue in Firefox 2.0, we can't enable
// DOMContentLoaded on that platform. For more information, see:
// Http://trac.dojotoolkit.org/ticket/1704
If (dojo. isOpera | dojo. isFF> = 3 | (dojo. isMoz & dojo. config. enabledomaindomcontentloaded = true )){
Document. addEventListener ("DOMContentLoaded", dojo. _ loadInit, null );
}
// Mainly for Opera 8.5, won't be fired if DOMContentLoaded fired already.
// Also used for Mozilla because of trac #1640
Window. addEventListener ("load", dojo. _ loadInit, null );
}
If (dojo. isAIR ){
Window. addEventListener ("load", dojo. _ loadInit, null );
} Else if (/(WebKit | khtml)/I. test (navigator. userAgent) {// sniff
Dojo. _ khtmlTimer = setInterval (function (){
If (/loaded | complete/. test (document. readyState )){
Dojo. _ loadInit (); // call the onload handler
}
}, 10 );
}
// END DOMContentLoaded
(Function (){
Var _ w = window;
Var _ handleNodeEvent = function (/* String */evtName,/* Function */fp ){
// Summary:
// Non-destructively adds the specified function to the node's
// EvtName handler.
// EvtName: shocould be in the form "onclick" for "onclick" handlers.
// Make sure you pass in the "on" part.
Var oldHandler = _ w [evtName] | function (){};
_ W [evtName] = function (){
Fp. apply (_ w, arguments );
OldHandler. apply (_ w, arguments );
};
};
If (dojo. isIE ){
// For Internet Explorer. readyState will not be achieved on init
// Call, but dojo doesn't need it however, we'll include it
// Because we don't know if there are other functions added that
// Might. Note that this has changed because the build process
// Strips all comments -- including conditional ones.
If (! Dojo. config. afterOnLoad ){
Document. write ('<scr' + 'ept defer = "" src = "//:" + = "" onreadystatechange = "if (this. readyState = \ 'complete \ ') {' + dojo. _ scopeName + '. _ loadInit ();} ">'
+ '</Scr' + 'ipt'>'
);
}
Try {
Document. namespaces. add ("v", "urn: schemas-microsoft-com: vml ");
Document. createStyleSheet (). addRule ("v \: *", "behavior: url (# default # VML )");
} Catch (e ){}
}
// FIXME: dojo. unloaded requires dojo scope, so using anon function wrapper.
_ HandleNodeEvent ("onbeforeunload", function (){
Dojo. unloaded ();
});
_ HandleNodeEvent ("onunload", function (){
Dojo. windowUnloaded ();
});
})();

The implementation idea is as follows:
If it is Opera or FF3 or later, the DOMContentLoaded event is directly registered. For the sake of security, the window. onload event is also registered.
Webkit is implemented by polling document. readyState.
If it is Air, only the widnow. onload event is registered.
For IE, the script with the defer attribute is written on the previous page and Its onreadystatechange event is registered.
The implementation scheme of Dojo in IE cannot solve the problem of iframe. Because there is a very strange Bug in FF2, The DOMContentLoaded event is used only in FF3 and later versions by default, at the same time, a configuration-dojo. config. enablejavasdomcontentloaded. If you set this configuration to true under FF, DOMContentLoaded will still be used for implementation, which fully considers the flexibility. The implementation of webkit is as optimized as prototype.
V. YUI
Copy codeThe Code is as follows:
(Function (){
/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller */
// Internet Explorer: use the readyState of a defered script.
// This isolates what appears to be a safe moment to manipulate
// The DOM prior to when the document's readyState suggests
// It is safe to do so.
If (EU. isIE ){
// Process onAvailable/onContentReady items when
// DOM is ready.
YAHOO. util. Event. onDOMReady (
YAHOO. util. Event. _ tryPreloadAttach,
YAHOO. util. Event, true );
Var n = document. createElement ('P ');
EU. _ dri = setInterval (function (){
Try {
// Throws an error if doc is not ready
N. doScroll ('left ');
ClearInterval (EU. _ dri );
EU. _ dri = null;
EU. _ ready ();
N = null;
} Catch (ex ){
}
}, EU. POLL_INTERVAL );
// The document's readyState in Safari currently will
// Change to loaded/complete before images are loaded.
} Else if (EU. webkit & EU. webkit <525 ){
EU. _ dri = setInterval (function (){
Var rs = document. readyState;
If ("loaded" = rs | "complete" = rs ){
ClearInterval (EU. _ dri );
EU. _ dri = null;
EU. _ ready ();
}
}, EU. POLL_INTERVAL );
// FireFox and Opera: These browsers provide a event for this
// Moment. The latest WebKit releases now support this event.
} Else {
EU. _ simpleAdd (document, "DOMContentLoaded", EU. _ ready );
}
//////////////////////////////////////// /////////////////////
EU. _ simpleAdd (window, "load", EU. _ load );
EU. _ simpleAdd (window, "unload", EU. _ unload );
EU. _ tryPreloadAttach ();
})();

Similar to Moontools
Vi. EXT
Copy codeThe Code is as follows:
Function initDocReady (){
Var COMPLETE = "complete ";
DocReadyEvent = new Ext. util. Event ();
If (Ext. isGecko | Ext. isOpera ){
DOC. addEventListener (DOMCONTENTLOADED, fireDocReady, false );
} Else if (Ext. isIE ){
DOC. write ("<script id =" + IEDEFERED + "defer = defer src = '/% 27 + % 27/:'> </script> ");
DOC. getElementById (IEDEFERED). onreadystatechange = function (){
If (this. readyState = COMPLETE ){
FireDocReady ();
}
};
} Else if (Ext. isWebKit ){
DocReadyProcId = setInterval (function (){
If (DOC. readyState = COMPLETE ){
FireDocReady ();
}
}, 10 );
}
// No matter what, make sure it fires on load
E. on (WINDOW, "load", fireDocReady );
}

The implementation idea is the same as that of Dojo.
Summary
Summarize the practices of major frameworks and write the following version. It is mainly to optimize as much as possible and take into account the Bug in FF2, and provide whether to use the DOMContentLoaded Switch configuration.
Copy codeThe Code is as follows:
/*
* Register the DOMContentLoaded event of the browser
* @ Param {Function} onready [required] Function to be executed when the DOMContentLoaded event is triggered
* @ Param {Object} config [Optional] configuration items
*/
Function onDOMContentLoaded (onready, config ){
// The browser detects related objects, which is not implemented to save code, but must be implemented in actual use.
// Var Browser = {};
// Set whether to use DOMContentLoaded in FF (A Bug exists in a specific scenario in FF2)
This. conf = {
Enabledomaindomready: true
};
If (config)
For (var p in config)
This. conf [p] = config [p];
Var isReady = false;
Function doReady (){
If (isReady) return;
// Ensure that onready is executed only once
IsReady = true;
Onready ();
}
/* IE */
If (Browser. ie ){
(Function (){
If (isReady) return;
Try {
Document.doc umentElement. doScroll ("left ");
} Catch (error ){
SetTimeout (arguments. callee, 0 );
Return;
}
DoReady ();
})();
Window. attachEvent ('onload', doReady );
}
/* Webkit */
Else if (Browser. webkit & Browser. version <525 ){
(Function (){
If (isReady) return;
If (/loaded | complete/. test (document. readyState ))
DoReady ();
Else
SetTimeout (arguments. callee, 0 );
})();
Window. addEventListener ('load', doReady, false );
}
/* FF Opera High Version webkit others */
Else {
If (! Browser. ff | Browser. version! = 2 | this. conf. enabledomaindomready)
Document. addEventListener ("DOMContentLoaded", function (){
Document. removeEventListener ("DOMContentLoaded", arguments. callee, false );
DoReady ();
}, False );
Window. addEventListener ('load', doReady, false );
}
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.