Is it possible to determine if a page is loading any resources, at any time including after the HTML document loads or from new ajax requests?
The use case is I have a site where I need to take a screenshot, but want to wait until everything has rendered. So this means:
DOM has fully loaded (detecting this is easy even with plain JS)
All resources (css, js, etc) have loaded.
Any AJAX calls that may have occurred from actions have completed. (probably the hard part here)
Detecting animations and CSS transitions is difficult, and not necessary for this. If you have a solution that covers 1-3, I will accept it. If you also know how to detect CSS transitions and JS animations etc, then you're amazing and I'll accept that :)
I think that to answer this question we should move from different sides.
First of all you want to wrap all your javascript code with
$( window ).load(function() {
// Run code
});
This will force your function to fire just when the page is fully loaded, including graphics, load method.
Quoted from jquery website
The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element
associated with a URL: images, scripts, frames, iframes, and the
window object.
This approach will solve point 1 and 2, and its a little bit different from ready method that fires just when the DOM is loaded.
The point 3 is a little bit harder to approach, but you could solve it using
$( document ).ajaxStop(function() {
//run code here
});
As it register an handler to be called when all Ajax requests have completed - ajaxStop.
Quoted from jquery website
Whenever an Ajax request completes, jQuery checks whether there are any other outstanding Ajax requests. If none remain, jQuery triggers
the ajaxStop event. Any and all handlers that have been registered
with the .ajaxStop() method are executed at this time. The ajaxStop
event is also triggered if the last outstanding Ajax request is
cancelled by returning false within the beforeSend callback function.
So the final code will look like this:
$( window ).load(function() {
$( document ).ajaxStop(function() {
//run code here
});
});
Hope it helped!
Related
I'm trying to identify roughly when the DOM is finished updating after a page is loaded via AJAX on any arbitrary website.
My current method first listens for the chrome.webNavigation.onHistoryStateUpdated event in a background script, then executes a content script in which a MutationObserver detects changes to the website's body. From there, unfortunately, it seems like it's a bit more finicky. If I just wait for the first mutation where nodes are added to the DOM, I wind up in many cases (YouTube, to give one example) where the page is still blank. Other more hacky approaches I've considered include things like just using setTimeout or waiting for the page to reach a certain length, but those seem clearly wide open to exception cases.
Is there a more fool-proof way to detect that the DOM has roughly finished updating? It doesn't necessarily have to be perfectly precise, and erring on the side of triggering late in my use case is better than triggering early. Also it isn't important at all that resources like video and images be fully loaded, just that the text contents of the page are basically in place.
Thanks for your help!
I need to make a change to an old page as quickly as possible, and the effort to AJAX-ify it in order to obviate postbacks would take too long (making a more correct version of it will have to come later, this new functionality needs to be in place ASAP). The javscript changes required are too complicated to attempt entirely in the plain JS the page currently uses for everything (it's enough of a mess as is), so I decided to implement the new functionality quickly using jQuery.
Everything works fine until there's a postback, after which the document ready function still runs, but the selectors no longer find anything. I'm not using ASP.NET AJAX, so there's no UpdatePanels or partial postbacks.
What's happening and how can I fix it in the simplest, fastest possible way?
While $(document).ready() is ideal for one-time initialization routines, it leaves you hanging if you have code that needs to be re-run after every partial postback. Of course there are ways to get around this. But can you try using .NET franeworks pageLoad() and bind your events there and see if selectors still work after postback.
<script type="text/javascript">
function pageLoad() {
$("#Button1").on('click', function () {
...
});
}
</script>
If you have a a trigger attached to the DOM, and that element in the DOM gets replaced, the trigger will be lost. Such a trigger might look like $('#mydiv').on('click', function(){});.
Instead, you have the attach the trigger to a DOM element that wont be replaced. The easy way is to attach this to the document, but you'd be recommended to narrow the search.
Such a selector would look like
$('document').on('click', '#mydiv', function() {});
This means that if the element #mydiv gets recreated, then the trigger is not lost.
You can read more about delegated events at http://api.jquery.com/on/
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).
I've noticed lately that sometimes the domready and window.load does not work. It's like randomly working when entering the page, and or refreshing.
Say I have:
$(function(){
$('.hide').hide();
// disable html5 native validation to let jquery handle
$('form').attr('novalidate','novalidate');
});
$(window).load(function(){
$('.input').click(function(){
$(this).animate({opacity:0.8});
}).blur(function(){
$(this).animate({opacity:1});
});
});
Sometimes when I load the page, the element is not getting hidden, sometimes it is, the input fields will animate, sometimes not, and both don't necessary fail together. If I refresh the page a few times, it will work.
I always thought that domready will execute as soon as the doms are ready, and window.load will wait until everything on the page is rendered ready? Or is this more bugs from HTML5?
Question is: am I missing something or just misunderstanding something?
Edit: Notably Chromium. I am on Ubuntu, so I would not be surprised if it was a chromium bug.
Be aware that if you have a very complex html structure, it may delay the time for the dom to become ready. The browser probably tries to render the page as quickly as it possibly can, and with a really complex page, it's possible that the rendering will begin and the domready event will trigger, but the browser will quickly render stuff before the specific code that you set up gets triggered.
A block in jQuery domready happens as fast as it can, but if you put, say:
setTimeout(function(){ $().ready(function(){alert('finally');});}, 9000);
That "as fast as it can" is still going to be limited by where the code occurs, in this case after a 9 second timeout.
Scenario: Preloading images
Perform an ajax query
Show loading screen
Retrieve results from ajax query
Insert images into the dom
Wait for images to finish loading
Hide loading screen
I was thinking of doing the following:
function ajaxCallback(results) {
/* snip insert into dom code */
$(".waitForLoad").each(function() {
imageLoadingCount++;
$(this).load(imageLoaded);
});
}
var imageLoadingCount = 0;
function imageLoaded() {
imageLoadingCount--;
if (imageLoadingCount == 0)
HideLoadingScreen();
}
I'm not quite sure of the interaction between the browser DOM and javascript. Does the DOM wait for the javascript to finish executing before it starts loading the images? I'm worried about possible race conditions.
Javascript should run in parallel with the loading, unless you're using all the connections with AJAX requests. The browser still functions normally while javascript runs, which is the whole point behind it in the first place.
The load event observer is a little scary because it will work only if you set it before the element has completely loaded, if you set it after that nothing will happen. Therefore, it really depends on when you call ajaxCallback(). I would recommend using onSuccess rather than onComplete.
Also, I wonder if it's possible to use the load event observer on $(".waitForLoad") itself?
You can safely execute ajaxCallback within $.ready() and get rid of most problems. And note that DOM is not updated for newly created tags.
Also note that - The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel.
In many scenarios, users will get annoyed if you are showing them loading screens for more than a second or two. Waiting for images to get loaded is hardly a good idea.