I am doing maintenance work for a website. The logo on the home page is supposed to bounce in from left after page has loaded but the animation begins even when the page is still loading.
The code is
$(document).ready(function(){
$('#logo-large').addClass('animated bounceInLeft');
});
The site is using animate.css library
The ready method do not wait for resources to load.
While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. 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. When using scripts that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the scripts.
Reference: https://api.jquery.com/ready/
Use window.load method:
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.
$(window).on('load', function() {
$('#logo-large').addClass('animated bounceInLeft');
});
Reference: https://api.jquery.com/load-event/
The problem here is that you say "page loaded" but you haven't defined what that means. The animation is, indeed, playing after the DOM has loaded. That's what the $(document).ready method insures. However, any images or asynchronous calls can still trigger after the DOM is ready. So... the REAL question is, do you want to wait til after the images have loaded AND do you have any asynchronous calls that need to be accounted for.
I just wrote this so I'm not 100% sure if it doesn't have any bugs, but this should work for both cases.
jQuery.prototype.pageComplete = function(promises, callback){
if(!callback){
callback = promises;
promises = [];
}
var images = jQuery.Deferred();
var DOMReady = jQuery.Deferred();
var count = this.length;
promises.push(images);
promises.push(DOMReady);
jQuery(document).ready(function(){
DOMReady.resolve();
});
function counter(){
if(--count == 0) images.resolve();
}
this.each(function(image){
var img = new Image();
img.onload = counter;
img.src = image.src;
});
jQuery.when.apply(jQuery, promises).then(callback);
};
You use it like so:
// for just images
$('img').pageComplete(function(){
// code to transition image here
});
// for images and ajax
$('img').pageComplete([
ajax1, // these are all promises created by jQuery.ajax
ajax2,
ajax3
],
function(){
// code to transition image here
});
Try this one, solution should work without jquery
window.onload = function() {
document.getElementById('logo-large').classList.add('animated', 'bounceInLeft');
};
Use The Window Load Function
This will wait until the whole page has loaded before running the animation
jQuery(window).load(function() {
$('#logo-large').addClass('animated bounceInLeft');
});)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
Is the DOM always ready when my external scripts have finished loading?
<head>
<script type="text/javascript" src="base.js"></script>
</head>
Inside base.js, I have an object that loads external scripts. It uses the following method to do so:
var head = document.getElementsByTagName("head")[0],
scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.onreadystatechange = function () {
if (this.readyState === "complete") onModuleLoaded();
};
scriptElement.onload = onModuleLoaded;
scriptElement.src = "externalScript.js";
head.appendChild(scriptElement);
Now, when all external scripts have been loaded, a callback function is called. My question is: Is this callback function suitable to place the
rest of my javascript code in? This code needs the DOM to be ready.
My scripts also use jQuery. But I don't think I can use
$(document).ready(function () { ... });
because in my tests that fires before my scripts have been loaded. However, I do not know if this will always be the case. If it will, my callback function is suitable for my DOM-manupilating javascript code.
But if it is possible that my scripts can be loaded before the DOM is ready to be manipulated, I need to find another way.
Thank you for reading!
Check jQuery.holdReady(). If you will try to load external js via getScript then you can easily do that.
Delay the ready event until a custom plugin has loaded:
$.holdReady( true );
$.getScript( "externalScript.js", function() {
$.holdReady( false );
});
Is the DOM always ready when my external scripts have finished loading?
Probably, yes. No.
Dynamically-added script elements load their scripts asynchronously. You're quite correct that you can't use jQuery's ready callback because it looks at when the DOM defined by the main HTML is fully loaded, which may well be before your additional scripts have loaded.
I'd be really, really surprised if the main DOM weren't loaded before your onModuleLoaded callback was called. So probably, yes, it'll be ready. Color me surprised. I ran the experiment, and guess what? It's possible for the script load and callback to happen before the rest of the page has been processed. (This is why I test my assumptions.)
But if you're worried there may be edge cases around it, you could always use ready within your callback. If jQuery has already fired the ready callbacks and you hook another one, jQuery calls it right away.
I know there are many ways to detect if images have been loaded the traditional way (i.e. <img src="bar.jpg"/>, but is there a way to detect when images are completely loaded inline (as in, <div class="foo" style="background-image: url(bar.jpg)">)?
I am uploading images via FilePicker and the image is then set as the background image to the parent div.
The window load event signifies that all images in the page have been loaded.
From MDN:
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images and sub-frames have finished loading.
This occurs during the initial load of the page for the resources specified in the HTML of the page.
If you are dynamically setting an image to be a background image, there is no event for when that background image has been loaded. If you wanted to know when that image was loaded, you could load it yourself in an image object and watch the onload handler for that image object and then when loaded, you could set it as the background image. It would be cached at that point so the background would show immediately.
function setBackgroundNotify(imgURL, targetObj, callback) {
var img = new Image();
img.onload = function() {
targetObj.style.backgroundImage = "url(" + imgURL + ")";
callback();
};
img.src = imgURL;
}
#jfriend00 is correct. That answer has the advantage of having no dependence on other libraries.
However, if you are already using jQuery (as the tag on your question suggests), you can achieve the same thing with .on("load",...).
http://api.jquery.com/load-event/
Note, the .load(...) shortcut has been deprecated, so use .on("load", ...) instead. This has at least one advantage over window.onload. It allows queueing of multiple event handlers, whereas an inadvertent reassignment of window.onload will blow your handler away. Furthermore, in the off chance there are any browser incompatibilities with window.onload, the jQuery solution will likely automagically handle them.
You can (more or less) prove to yourself it is working with a little profiling:
$(document).ready(function() {
console.log("Document ready at " + Date.now());
});
$(window).on("load", function() {
console.log("First window on load at " + Date.now());
});
$(window).on("load", function() {
console.log("Second window on load at " + Date.now());
});
Assuming you've got some div's doing some really expensive background image loading, you should see a noticeable lag in time between document ready and the first window on load.
Why does ajax load() triggers callback before all images are fully loaded.
$(element).load("url #id", function()
{
$(this).fadeIn();
})
When I load data, element fades in and I see how images are drawn slowly on my screen... is it that image is loaded but computer is slow?
What should I do to show content after it's fully loaded?
$(element).load will load content into your element, but then you can find all images and attach a load callback on them to determine when all images have been loaded. However, this is not very reliable since the load event on images might never fire for various reasons. In some browsers, the load event will be synchronous when the image is cached, so it will fire before we even attached an event handler on the image. For that reason, if images are not loaded after 5 seconds, we show the element anyway.
$(element).load("url #id", function () {
var $self = $(this),
$images = $self.find('img'),
imgCount = $images.length,
loadedCount = 0;
$images.on('load', function () {
if (++loadedCount === imgCount) {
$self.fadeIn();
$(this).off('load');
}
});
setTimeout(function () {
if (loadedCount !== imgCount) {
$self.fadeIn();
$images.off('load');
}
}, 5000);
});
From the jQuery documentation:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the
same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's
cache
In the same documentation they offer a soultion to display graphics when they are loaded.
You can chech for the height property to be what it needs to be before displaying the image, since it will change size only when it has really been loaded (only if you did not specify it in the css though).
I have a javascript code like this
<script type="text/javascript">
window.onload=myFunction;
</script>
Is there any difference in using the above snippet in the <head></head> tag and just before
</body> tag, as I would like to call my function after the page loads.
basically there's no pratical difference, but I recommend
to place that code at the bottom, since you need to use a script (blocking-rendering tag) it's better put it at the end of the document.
to avoid a destructive assignments like that: writing window.onload=myFunction you destroy other previous assignments to window.onload event (if any) so it's better something like
(function() {
var previousOnLoadIfAny = window.onload;
window.onload = function() {
if (typeof previousOnLoadIfAny === 'function') {
previousOnLoadIfAny();
}
yourfunction();
}
}());
Binding to window.onload will always run your function when the load event fires. This only fires after everything in the page has finished loading, including images etc. If you want to run your function when the DOM has finished loading but before everything else then you can bind to the DOMContentLoaded event or use a library like jQuery (e.g. $(function(){ myFunction() });).
The benefit about putting your function at the end of your <body> is that theoretically this means that the rest of your content has already loaded and you don’t need to bind your function to a load event. This sometimes works, but depends on the situation.
No, where you place that will not matter - anywhere in the document and it will trigger when the document and all external resources (images, scripts etc) has loaded.
Because onload triggers after all external resources one often want to use DOMContentLoaded instead which triggers when the HTML DOM is ready. Which will make for a page that is more responsive.
I have a photo gallery page hosted on a CMS (Squarespace) which has some of it's own scripts which load the thumbnails asynchronously.
The actual large images however are not preloaded, so I decided to add my own script into the mix to just make the browser load those larger images into the cache in the background, like this:
(function($) {
var cache = [];
// Arguments are image paths relative to the current page.
$.preLoadImages = function() {
var args_len = arguments.length;
for (var i = args_len; i--;) {
var cacheImage = document.createElement('img');
cacheImage.src = arguments[i];
cache.push(cacheImage);
}
}
})(jQuery)
$(window).load(function(){
$.preLoadImages(
"/picture/1.jpg",
"/picture/2.jpg", //etc.
);
});
I placed my code in a $(window).load() because this is a background script and it's not essential it even runs at all, it's just to improve performance.
However, I think this script is somehow blocking the CMS's own thumbnail preloading script.
Am I right? And most importantly, is there a way to dictate that my script only run after all other scripts on the page have run?
cheers
JavaScript is always running, the hover event for example is firing constantly, mousemove, etc...there's no "end" to the script run.
However in your case, this shouldn't block any other preloading...also you can use document.ready here, since you don't actually need images loaded before your code executes.
In fact, you're actually slowing down the page by using window.load instead...since the preloading starts later, when it could be parallelized with other downloads earlier by the browser. Instead use document.ready, like this:
$(function(){
$.preLoadImages(
"/picture/1.jpg",
"/picture/2.jpg", //etc.
);
});
Scripts are loaded top down, and body onloads are normally appended to existing onloads - so as long as that $(function().. is at the end of the page, it'll be ran last. (last (as per nick's comment) meaning the initial parse/run of the document)