`
Joson_Coney
  • 浏览: 54710 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Relying on DOM readiness to invoke a function (instead of window.onload)

 
阅读更多

( From: http://www.javascriptkit.com/dhtmltutors/domready.shtml)
( Crazy implementation with pure javascript. Just in order to take place of " $(document).ready(function(){...});".
......

)

Relying on DOM readiness to invoke a function (instead of window.onload)

One of the most common event web developers check for before running their JavaScript is whether the page has completely loaded. For example:

window.onload=function(){
  walkmydog()
}

This technique has become very popular as a way of defining our scripts in a central location without having to worry about the availability of the page content it seeks to manipulate. The bottom line is, when the page has fully loaded, whatever we want on the page has as well, ready to be molded. However, it's not without its flaws- waiting for the entire page to load literally means that, which can include slow loading images/iframes present on the page, and isn't always necessary. That's why Dean Edwards, JavaScript extraordinaire, came up with an alternate techniqueto detect page DOM readiness instead, which just means finding out when the document's DOM tree has fully initialized, versus the entire document and every object in it. A classic example is the insertion/ deletion of nodes via the DOM, which can in fact be done sooner rather than later, when the DOM has loaded versus the document itself (window.onload). In this tutorial, let me recap and perhaps refine a bit Dean Edward's technique for calling a function as soon as the document DOM is ready!

Relying <wbr>on <wbr>DOM <wbr>readiness <wbr>to <wbr>invoke <wbr>a <wbr>function <wbr>(instead <wbr>of <wbr>window.onload) Checking DOM readiness in Firefox and Opera 9+

In Firefox and Mozilla, checking for DOM readiness and executing a function when it's ready is simple, as a special "DOMContentLoaded" keyword is supported that can be used in place of an element when calling document.addEventListener():

if (document.addEventListener)
  document.addEventListener("DOMContentLoaded", walkmydog, false)

In this case the function walkmydog() will run as soon as the DOM for the document has fully initialized, which depending on the contents of your page can occur a lot sooner thanwindow.onload.

Relying <wbr>on <wbr>DOM <wbr>readiness <wbr>to <wbr>invoke <wbr>a <wbr>function <wbr>(instead <wbr>of <wbr>window.onload) Checking DOM readiness in Internet Explorer

In IE (includes IE7), there's no intrinsic way to detect DOM readiness. Dean Edwards came up with a roundabout solution instead, which relies on the behaviour of the defer attribute when added to an external JavaScript tag. In short this attribute causes IE to "defer" loading the referenced external JS file until the DOM has fully loaded, a behaviour that we can take advantage of here to accomplish what we want:

if (document.all && !window.opera){ //Crude test for IE //Define a "blank" external JavaScript tag
document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>')
var contentloadtag=document.getElementByIdx_x_x("contentloadtag") contentloadtag.onreadystatechange=function(){
if (this.readyState=="complete")
walkmydog() } }

As you can see, this technique centers around defining a "blank" external JavaScript tag with the "defer" attribute added. In IE, most elements support a "onreadystatechange" event that fires during each stage of the element's loading process, ending with "complete". So by probing theonreadystatechange event of our deferred blank JavaScript tag, we can in effect call the desired function when the DOM is ready.

Relying <wbr>on <wbr>DOM <wbr>readiness <wbr>to <wbr>invoke <wbr>a <wbr>function <wbr>(instead <wbr>of <wbr>window.onload) Putting it all together, plus a fall back plan

You just saw the two divergent techniques for detecting DOM readiness. It's time now to put the two halves together, but more importantly, implement a fall back mechanism for browsers that don't support any of the two "detect DOM readiness techniques" to default to using window.onloadinstead. With that said:

var alreadyrunflag=0 //flag to indicate whether target function has already been run
if (document.addEventListener) 
    document.addEventListener("DOMContentLoaded", function(){
        alreadyrunflag=1; 
        walkmydog()
    }, false) 
else if (document.all && !window.opera){ 
    document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>') ;
    var contentloadtag=document.getElementByIdx_x_x("contentloadtag");    
    contentloadtag.onreadystatechange=function(){ 
        if (this.readyState=="complete"){ 
            alreadyrunflag=1; 
            walkmydog() 
        } 
    } 
} 
window.onload=function(){ setTimeout("if (!alreadyrunflag) walkmydog()", 0) }

Note the code in red- this is our fallback mechanism that shall account for the scenario in which the target function wasn't run at the DOM ready stage for any reason, and run it via the traditional window.onload event instead. With it in place, no browser should fall through the cracks at the end of the day. Two things I should point out with this scheme that makes it work:

  • A global flag "alreadyrunflag" is defined to let the fallback code know whether it should run the target function via window.onload. If the flag evaluates to true, it means the target function has already been run at the DOM readiness stage (which proceeds window.onload).

  •  In IE and for very basic pages that contain just a few lines of text, there is the possibility that window.onload could fire at the same time the readyState property of the external JavaScript tag evaluates to "complete", instead of the former always following the later . In such a unique case, the flag alreadyrunflag won't evaluate to true in time for our fall back function to know that the target function has already been run in IE, and will run it again. This problem can easily be fixed by embedding a setTimeout() within window.onload, ensuring the code attached to this event will in fact always be the very last thing run on the page.

And there you have it- a way to launch functions as soon as the DOM is ready and not leave non capable browsers in the dust. Using the exact same technique, the below example shows launching two functions this time around, the later with a parameter:

var alreadyrunflag=0 //flag to indicate whether target function has already been run if (document.addEventListener) document.addEventListener("DOMContentLoaded", function(){alreadyrunflag=1; walkmydog(); feedcat('grapes')}, false) else if (document.all && !window.opera){ document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>') var contentloadtag=document.getElementByIdx_x_x("contentloadtag") contentloadtag.onreadystatechange=function(){ if (this.readyState=="complete"){ alreadyrunflag=1 walkmydog() feedcat('grapes') } } } window.onload=function(){ setTimeout("if (!alreadyrunflag){walkmydog(); feedcat('grapes')}", 0) }

Relying <wbr>on <wbr>DOM <wbr>readiness <wbr>to <wbr>invoke <wbr>a <wbr>function <wbr>(instead <wbr>of <wbr>window.onload) In conclusion, and checking for  DOM readiness in Safari

The advantage of running a function as soon as the DOM is ready versus window.onload materializes on pages that are heavy on mages or iframe tags. Ultimately you have the weigh the benefits versus the additional code and work needed to implement such a technique. Before I conclude this tutorial, there's an elephant in the room I've been ignoring until now. Apparently in Safari it's also possible to check for DOM readiness, and Dean Edward referred to John Resig in coming up with a way to do so in that browser:

if(/Safari/i.test(navigator.userAgent)){ //Test for Safari var _timer=setInterval(function(){ if(/loaded|complete/.test(document.readyState)){ clearInterval(_timer) walkmydog() // call target function }}, 10) }

It's the obsessive DOM readiness checker! In Safari, apparently, what you need to do is manually probe the document.readyState property at fast paced intervals to see when it returns either "loaded" or "completed" (usually the former proceeds the later, but to be safe, check both). That's when you know the DOM is ready and to fire your desired function. Personally I'm not keen on implementing it, as this is where the technique crosses the line and becomes a burden in my opinion considering the small group it benefits. And yes we're all entitled to our opinions!

 

分享到:
评论

相关推荐

    Probabilistic Robotics

    of relying on a single “best guess” as to what might be the case in the world, probabilistic algorithms represent information by probability distributions over a whole space of possible hypotheses. ...

    Programmers.Guide.to.Drupal.Principles.Practices.and.Pitfalls.2nd.Edition

    Drupal has its own set of programming principles that require a different approach, and many programmers make mistakes when relying on skills they’ve used for other projects. The guidelines in this ...

    Tracking Human Position and Lower Body Parts Using Kalman and Particle Filters Constrained by Human Biomechanics

    of relying on constraints that are linked to a specific activity or camera view. These characteristics make our approach suitable for real visual surveillance applications. Experiments on a set of ...

    Seamless R and C++ Integration

    Rcpp attributes provide a high-level syntax for declaring C++ functions as callable from R and automatically generating the code required to invoke them. Attributes are intended to facilitate both ...

    3D-LaneNet- End-to-End 3D Multiple Lane Detection.pdf

    We introduce a network that directly predicts the 3D layout of lanes in a road scene from a single image. This work marks a first attempt to address this task with onboard sensing without assuming a ...

    The Art of SQL

    A database administrator tries to get the most out of a systema given hardware, processors and storage subsystem, or a given version of the database. A database administrator may have some SQL skills...

    Beyond jQuery(Apress,2016)

    But relying solely on jQuery as your window to the web leaves large gaps in your knowledge. This in turn results in frustration when the abstraction that jQuery provides “leaks” and exposes you to ...

    beginning_portable_shell_scripting_from_novice_to_professional.pdf

    introduction to Shell Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 About This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....

    Beyond.jQuery.1484222342

    But relying solely on jQuery as your window to the web leaves large gaps in your knowledge. This in turn results in frustration when the abstraction that jQuery provides "leaks" and exposes you to ...

    Learning Haskell Data Analysis(PACKT,2015)

    As you progress in the book, you will be relying on code from previous chapters in order to help create new solutions quickly. By the end of the book, you will be able to manipulate, find, and ...

    programming-openresty

    OpenResty itself has been relying on automated testing to remain high quality over the years. As OpenResty core developers, we embrace the test driven development (TDD) process all the time. An ...

    An Introduction to Deep Learning for the Physical Layer

    we demonstrate the application of convolutional neural networks on raw IQ samples for mod- ulation classification which achieves competitive accuracy with respect to traditional schemes relying on ...

    Why (and How) Networks Should Run Themselves

    Instead of optimizations based on closed-form analysis of individual protocols, network operators need data- driven, machine-learning-based models of end-to-end and application performance based on ...

    Deep Learning Networks for Stock Market Analysis and Prediction

    Its ability to extract features from a large set of raw data without relying on prior knowledge of predictors makes deep learning potentially attractive for stock market prediction at high ...

    Syngress - Violent Python

    Instead of relying on another attacker's tools, this book will teach you to forge your own weapons using the Python programming language. This book demonstrates how to write Python scripts to ...

    An Introduction to Design Patterns in C++ with Qt Second Edition

    The authors introduce several new design patterns, add many quiz questions and labs, and present more efficient solutions relying on new Qt features and best practices. They also provide an up-to-...

    MS Press - Object Thinking

    But many developers have not mastered its underlying concepts and principles—relying on methodology and process instead of fully exploiting the power of object thinking in software design....

    LDB特征提取算法

    A multiple gridding strategy is applied to capture the distinct patterns of the patch at different spatial granularities, leading to a high distinctiveness of LDB. LDB is very suitable for vision ...

    scaling_mongodb

    On the plus side, MongoDB tries to take care of a lot of the issues listed above. Keep in mind that this isn’t as simple as setting up a single mongod (then again, what is?). This book shows you how...

    不完全信息下的多Agent评价.pdf

    Recently, a ranking method called α-Rank, relying on a new graph-based game-theoretic solution concept, was shown to tractably apply to general games. However, evaluations based on Elo or α-Rank ...

Global site tag (gtag.js) - Google Analytics