How does Jquery domready work? - javascript

I'm looking at jQuery source code for tracking the domready event and there's one thing I don't understand completely. What if the script is included dynamically and is loaded asynchronously? That way the document might already be loaded when the script loads. The only place jQuery checks for this is the document.readyState.
Correct me if I'm wrong, but hasn't this property been introduced to Firefox just very recently? If so - the DomContentLoaded event might have already been fired (even window's onLoad might) and there is no way to actually call the code on domready in such situation.

In the current version of jQuery, it's all handled with the "Deferred" mechanism. The readiness of the page is encapsulated in a Deferred object, and functions are simply added to the "done()" queue. The Deferred API simply remembers whether the page is ready or not, so passing in a function as a "ready" handler after the page is ready will simply call the function immediately.
The code to keep track of when "ready" actually happens is pretty tortured, however.

Related

Notification when function is registered on e.g. $(document).ready()

is there a way to be notified when a function is registered via the jQuery $(document)ready() functionality and get a reference to that?
The background:
Im using a parent theme on a wordpress site, which uses ajax page transitions and document ready is only called on the first load. Now i want a reference to each function previously registered to call them again if my page changes.
The goal: is to restore the functionality of $(document).ready() as not only me, but many other plugins out there are using it and i obviously dont want to rewrite them all.
Yes, i could call MY registered function with no efford but this feels kind of lackluster while destroying the underlying functionality. By the way: it is the parent themes transitions, so overriding this wouldn't be the best solution either.
What i want is to provide an addition, that intercepts every registration and calls the registered functions again manually after the transition. Is that a good idea?
(notice calling ready() manually doesn't work if it was called already automatically on the initial page load)
why dont you wrap them all in a onPageChanged function and call that on document ready, and in the success handler from ajax calls

Event fired when browser comes out of "loading" state?

Whenever we go to a website, the browser enters a "loading" state (spinner in place of favicon) till the site is loaded.
Which jquery event is fired when browser comes out of the "loading state"?
$(document).ready(function() {
// put all your jQuery goodness in here.
});
you can try anyone of :
window.onload or document.ready
It would definitely help if you explained what you were trying to do. But since you asked for an jQuery event that fires when the browser has loaded the page, I would suggest you use the jQuery ready handler.
All three of the following syntaxes are equivalent:
$(document).ready(handler)
$().ready(handler) (this is not recommended)
$(handler)
The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code.
EDIT: Since we need an event when the browser has completed loading the page and all its resources, the jQuery .load() method would be more suitable.
The load event is sent to an element when it and all sub-elements have been completely loaded. It is a shortcut for .bind('load', handler).

Does this code need to be in a document.ready?

The document.ready is used to execute code after the DOM is fully loaded. This can be used to attach event handlers to elements on the page e.g
$(function(){
$('#somediv').click(function(){
});
})
<div id="somediv"> </div>
Internally, jQuery hooks up to DOMContentLoaded and window.onload as a fallback. In IE's case an attempt is made to scroll the viewport over and over until successful.
I have a few questions, my first one being, when binding event handlers to the document itself, is it necessary to put that code in a document.ready ? I have always been writing the code below without wrapping it in a document.ready
$(document).keydown(function(e){
if (e.which == 39) {
alert( "right arrow pressed" );
return false;
}
});
And as you can see, it works. My understanding is, since this code doesn't hook up to any elements within the document, but the document itself, there's no need to wrap it in a document.ready handler. Another reason i don't wrap it is because i used to do the same in vanilla javascript the equivalent would be the code below, which also works.
document.onkeydown = function(){
var keyCode = event.keyCode || event.which;
if (keyCode == 39) {
alert( "right arrow pressed" );
return false;
}
}
I've seen numerous posts where people wrap it in a document.ready, is there any downside of not wrapping this code in document.ready ?
Also i think this question stems from my lack of clarity of what happens during this time when the DOM is being constructed, so if someone can explain what happens during the period right before the DOM is ready. To me the document is ready when the html has been parsed and converted into a DOM tree, or is there more to it ?
In summary, here are my questions
When binding event handlers to the document itself, is it
necessary to put that code in a document.ready.
Are there any downsides to not wrapping the code in the document.ready ?
What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
If you are binding to the document itself, you don't need to wait until it is ready. There shouldn't be any downsides to not wrapping it in document.ready in this case.
document.ready gets fired when the DOMReady event is triggered by the browser, or when a specific test is successful for versions of browsers that don't support the DOMReady event.
Additional information. (5/22/12)
Most modern browsers implement the DOMContentLoaded event which fires when all elements defined on the document are ready to be manipulated by javascript. Other browsers either rely on a setTimeout loop that continuously checks the readystate of the document or binds directly to the onreadystatechanged method of the document (taken from jquery core). The document itself is ready to be manipulated before javascript is ever executed, therefore you never need to wait when binding directly to the document.
The only gotcha here is that if the code interacts with elements other than the document, there is a chance that the event could be triggered on the document before those elements exist. It is very unlikely for that to happen, but it can happen. If that is something that can happen with your code, then it makes sense to place it inside of $(document).ready() to prevent that scenario. Your sample doesn't warrant being placed inside of $(document).ready().
The point of $(document).ready is to execute code after the entire document has been parsed.
You only need to use it if you want to use elements that don't exist yet.
(eg, if your script is in the <head>)
If the elements you're using already exist (either because they're global or because your <script> is below them), you don't need it.
The only drawback of not binding an event to the document in a document.ready block would be that it will be possible to fire the event before all the page content has been loaded, which may not be what you want.
This event gets triggered when the DOM hierarchy has been fully
constructed i.e. all assets such as images have been completely
received.
You asked:
When binding event handlers to the document itself, is it necessary to put that code in a document.ready?
Answer: Nope. When using code that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the script in which your code resides or just before document.ready() block.
Are there any downsides to not wrapping the code in the document.ready ?
Answer: No. But when you've to create elements inside your documents by using JavaScript, then should wait for sake until your DOM gets ready. For this, you should put your code inside document.ready() block.
What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
Answer: Before document.ready gets fired, DOMContentLoaded is already triggered by browser.
When using actions to elements or calling them (that will be generated in DOM or don't exist yet) you need to use $(document).ready
In addition to the answers: you can mere use jquery live function (instead of keydown, etc.) to be free of the situation 'DOM elements must be finished'.
So the next must work properly:
$( "#somediv" ).live( 'keydown', function(){ ... } );
In this case jQuery binds the event when it is possible. You don't have a pain to place all bindings in one (ready) function, your bindings can be placed in independent parts of your HTML page or Javascript files.
So, the result answer is: no, you don't need to place your code in document.ready when you use the mentioned function.
Update
In the last versions of jQuery (>= 1.7) use on() function instead of live() because the last one is depricated. So, it's not necessary to place event bindings into ready().
1. When binding event handlers to the document itself, is it necessary to put that code in a document.ready?
No. In fact, the 'on' methods for binding in JQ can delegate at the document so you could use those at any time on any element safely as long as there wasn't a lot of bubbling being stopped at container elements with stopPropagation.
2. Are there any downsides to not wrapping the code in the document.ready?
Only that scripts in the head might try to hit HTML that isn't there yet. The converse is that HTML might be ready and getting events from the user before the doc is. See 'on' methods or google 'event delegation' for having your cake and eating it too where events are concerned (the caveat is libraries that use stopPropagation stupidly). document.ready is mostly just a way to be certain your code is firing when the HTML is ready to be hit. It's not necessary for code that falls at the bottom of the body tag unless (maybe) you're hitting body itself with something.
3. What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
At the point that document ready is fired, all tags have been parsed and the layout dimensions have been established. Images do not need to have fully loaded, and I'm only guessing, but I suspect non-layout impacting CSS may not be in effect yet in some browsers. An element is considered 'ready' when its closing tag has been read and executed on by the HTML parser. JS in script tags must be handled by an interpreter before HTML parsing can continue, which is why we tend to put our code at the bottom of the doc nowadays anyway, for faster perceived loading time.

Call a function on DOM ready from outside <head>?

In jQuery you can wrap all your code in $(function() { ... }); and have it fire when the DOM is ready, but what if you want to put that in the middle of the page somewhere? Isn't it possible that the DOM ready event will fire before it processes that chunk of code and it'll get missed? Is there a way to guarantee it'll get fired?
You can place a <script>..</script> block anywhere in your code:
if you use .ready() (or equivalent syntax) to execute code when the dom is loaded, it will be executed when the whole page is loaded, no matter where you placed the ready() handler.
if you simply put code within the <script> tags, then it will be executed whenever the parser reaches that point of the code.
No, it is not possible for the DOM ready event to fire when the DOM is not ready. It will be fired, regardless of where you place your script.
DOM ready doesn't fire until the whole DOM tree has been loaded, so it will work.
Also, if you happen to do $(function() { ... }) after DOM ready has already fired, jQuery is smart and will just execute your callback right away.
No, the DOM ready event should not get fired until the DOM is ready, meaning until it processes the last closing tag and constructs the DOM fully.
You should be fine placing your <script> tags with the jQuery ready anywhere in the page.
DOM ready event will fire before it processes that chunk of code
only if connection to web-server will fails before the browser download the whole html page.
In such a strange case dom ready event will fires, but your inline scripts fails.

Load external script dynamic, and access it, so I can trigger its domready function

I am trying to load the Zopim chat client. Normally it is included with a document write action. This causes it to be loaded before the domReady function is triggered, as it needs this to start itself.
I want to load it later, and this works by using prototype (framework determined by Magento) to create a new script element and attaching it to the head. The script is loaded perfectly, but the domReady doesn't fire, so the script is never started.
The script is a nameless class, by this I mean that all its functions are encapsulated in {}
UPDATE: Sorry, I got it wrong, it is as self invoking function, the same syntax as the first answer suggest.
(function C(){
})();
This function call when run sets up listening events for the domReady event under various browsers and then waits. When the domready event fires, it calls a function (that is within the self-invoked function) that starts everything. What I need, is a way to access this function somehow.
END UPDATE
Within that is a function named C.
How can I call this function directly?
Or put another way, how can I start an external javascript file that depends on domready going off, when that event doesn't happen?
Can I load an external javascript file into a variable, so I can name the class?
Can I access the nameless class {} somehow maybe via the script tag?
Is there a way to alter the external file/javascript so I can have it look for another event, one that I can trigger?
About the only solution I can think of at the moment is to create a iframe and load the script in that.
If you want to fire it after loading it asynchronously after the domready is already fired, you can do this:
Make your function C a self invoking function by:
(function C(){
})();
With this approach you would be changing the external script though.
You may trigger the event programmatically, for example:
window.dispatchEvent(new Event('DOMContentLoaded'));
See Creating and triggering events.
But note that this solution can be tricky to make it work correctly, cause when you trigger the event, some event handlers that have registered to the event will trigger a second time. And this causes problems like page not working as expected or an infinite loop (event registering, handler call, event registering, handler call indefinitely).
So you would need a solution to make sure that the different scripts that registered to the DOMContentLoaded event have their handlers only called 1 time exactly.

Categories

Resources