I have a project that needs to get the logo's dimension and adjust its position accordingly. From what I understand, all the elements on the page should be ready for use right after $(document).ready or onload event. I also tried to put the script before the closing body tag to make sure I can get everything. I use jQuery $(element).width and $(element).height to measure the logo image.
However, I am not getting these value every time: I console log these two values. Sometimes, it shows me zero which I guess the image tag is loaded, but the actual image is still loading. I am so confused because I search online, they all say all the elements should be ready if I use DOM ready or put the script tag in the end.
try this
$('#img').load(function() {
// Handler for .load() called.
});
all the elements on the page should be ready for use right after $(document).ready or onload event. I also tried to put the script before the closing body tag to make sure I can get everything.
No, the $(document).ready event resp. embedding the script as last element in body only guarantee that the DOM structure is build up already. That does not mean that external resources referenced by any elements have already finished loading – the only event that guarantees that is the load event.
The jQuery docs explicitly warn about combining $(document).ready and “old school” load event handling (meaning onload attribute on body or window.onload) – so you should use .on('load', handler) instead. But be aware of the cave-ats of that regarding images that the docs also mention.
Related
I have a website with a background and a main container. I wanted to hide the container until the whole page has been loaded. so i added
#cover{opacity:0}
at the start of the page and
$(window).load(function() {
$('#cover').css('opacity','1');
});
at the end, just before </body> tag. It works perfectly when page is loaded for the first time.
PROBLEM : If I load the same page once more, it shows all the images and text scattered throughout the page. It works fine once completely loaded. certainly this type of behavior is caused by cached images. but all the images are inside the main container which has opacity:0, This has completely confused me.
UPDATE 1:
I am using turn.js to convert the whole container into a book, i want the book become visible when the book is ready i.e. both loading of images and javascript initialization has completed.
UPDATE 2:
This is how i am checking for "images loaded" and "javascript initialized". it worked as i wanted it to. is this a good way to handle the situation?
$(window).load(function(){
$(window).ready(function() {
$('#cover').css('opacity','1');
});
});
$(window).ready(function(){
$(window).load(function() {
$('#cover').css('opacity','1');
});
});
The problem may be related to your $('window').onload();
Take some time and read this SO post.
what-is-the-difference-between-window-load-and-document-ready
load is called when all assets are done loading, including images.
ready is fired when the DOM is ready for interaction.
From the MDC, window.onload:
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.
From the jQuery API
documentation, .ready( handler ):
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.
Let me know if this change works.
You do not call the same block in your CSS (#container) and in your JS (#cover).
I need to fire some javascript after the DOM and CSS is loaded, but not images. I believe that's after document.ready but before window.onload. Anyone know how to achieve this?
I was thinking of loading CSS after document.ready by iterating through document.styleSheets but it feels like a bad idea.
Update: The reason for this unusual requirement is that I need to predict the size which images will be rendered, which is determined by css. Moving the javascript to the bottom of the page solves the issue, but I'd like my script to work when that's not the case too.
You want the DOMContentLoaded event, together with an external script linked after all of the stylesheets.
From the linked page:
if you have a <script> after a <link rel="stylesheet" ...>, the page will not finish parsing - and DOMContentLoaded will not fire - until the stylesheet is loaded.
You could try to use a small image and add the handler to its onload event, see image.onload event and browser cache
Add your code with this small image to document.ready.
Please could you elaborate what is your use case, and why putting the code on document.ready event handler would not do the job for you?
Another option would be to attach handlers to onload of each of the style tags, and each of this handlers to increment some counter, which you would check at the same time if the counter = style tags count. (You could determine the count of style tags, the same time you add the event handlers).
When the counter has reached the number of style tags, you could fire your custom event, that could be used to have your code run. This however would fail if some of the stylesheets fail to load for some reason, so I would suggest adding a fallback to execute the code on window.onload if the above logic fails.
DOMContentLoaded is the first thing that is executed.
BUT
if i place an image like this in the html. and this image is cached then the image onload executes before DOMContentLoaded.
html
<img onload="console.log('imgLoaded');" src="http://placekitten.com/16/16">
js
window.addEventListener('DOMContentLoaded',function(){
console.log('DOMContentLoaded')
},false);
DEMO
http://jsfiddle.net/yE9qU/
output:
DOMContentLoaded
imgLoaded
imgLoaded <----- wrong
DOMContentLoaded
also putting the onload event directly on the image does not work.
http://jsfiddle.net/yE9qU/1/
output:
10 10
10 10
16 16 <----- wrong
10 10
This means that there is no way to get the right css assigned size before everything loads... so after window.onload
Solutions...
depends on what you need.
if there are not to many images i would add them after executing load or DOMContentLoaded.
like you say putting the script at the bottom of the page. but not so sure if image is already cached.
a. do the math after everything has loaded (it's just some milliseconds)
b. hide the images until math is done.
If you explain exactly why you need the size of the images in that exact moment it's easier for us to find you a proper alternative solution.
So I'm using jquery along with some plugins I wrote.
I do all the initialization in a $(document).ready(function(){}) block however this is executed when the whole DOM has been loaded and is ready to be used.
However that would take long eg. when there is a server load. Or maybe the user clicks a button that has been loaded while the rest of the page hasn't loaded yet (and thus document.ready() hasn't been executed yet) in which case it would do nothing.
So, what if I want a code to be executed right after the related part of the page has been loaded instead of waiting for the WHOLE page to be loaded?
I know placing inline code right after the html that this js operates on would do the trick but what if that code uses a library like jQuery that hasn't been loaded yet?
I know placing inline code right after the html that this js operates on would do the trick but what if that code uses a library like jQuery that hasn't been loaded yet?
That would be the only way. The HTML is parsed from top to bottom. So you can expect every script you included to be accesible after you included it.
Your page should still work without JavaScript anyway, so a user clicking a button extremely fast will just temporarily have a somewhat degraded experience.
That being said, the DOM is basically ready when the HTML document all scripts are loaded. Since you cannot execute meaningful JavaScript before the JavaScript code is loaded (duh), I'd have a close look at page performance. Sending an HTML document and 2,3 JavaScript files should not be slow.
You could also use the old-style inline event handlers, like <button onclick="registerButtonClickEvent()">. However, this would introduce a complex, potentially buggy and hardly testable layer of temporary event holding.
If your <script src="jquery-whatever.js> line precedes the first clickable element in your HTML, it is guaranteed that the jquery library will be loaded and run before the user has anything useful to click on.
Just don't add async or defer attributes to the script element.
The onload event isn't triggered from all html elements, so you're forced to wait for window load. It doesn't matter where you load jQuery since it will have to wait for document to be ready. That total time required to load jQuery plus the rest of the document will be thet same.
We have a JQuery $(function() statement as:
<script type="text/javascript">
$(function(){
//Code..
})
</script>
Dumb question - when exactly is this function executed? Is it when the entire HTML page has been downloaded by the client?
What is benefit of using the wrapping your code within $(function() as opposed to just doing:
<script type="text/javascript">
//Code..
</script>
It fires when the document has been parsed and is ready, and is the equivalent of $(document).ready(function () { }).
The obvious benefit is that having your script tag before other elements on the page means that your script can interact with them even though they're not available at parse time. If you run your script before elements have been parsed and the document is not ready, they will not be available for interaction.
It is executed as soon as the DOM is parsed and is invoked in order of appearance if there are multiple appearances. At this point the document is however not displayed, its just parsed.
When the document completes loading. It is the same as writing this:
$(document).ready(function(){});
EDIT: To answer your second question:
If you don't wrap your code in the block above then it would fire as soon as it is encountered instead of after all the controls on the page have loaded. So if a block was at the top of a page and it referred to elements in the page those references would not work as the elements have not loaded yet.
But if you wrap in the block then you know that the page has loaded and all elements are available to now reference.
It fires after the the document has fully loaded, the DOM tree has been initialized, all CSS styles have been applied and all Javascript has been executed. It differs from the load event in that elements (other than CSS/JS) that load their content from other URLs, such as images or flash files, have not necessarily finished loading at this point. This is usually called the "domready" or "domloaded" event, and some modern browsers support it directly (e.g. Firefox has a DomContentLoaded event), and on others it can be simulated with various tricks, like using the defer attribute or placing a script at the very end of the body.
The advantage is that you can reliably interact with the document at this time; for example you can set an event handler on an element with a certain ID and be sure that it already exists in the DOM tree. On the other hand, it can run considerably earlier than the load event, if some external resource is slow to load. If your script is at the end of your HTML code, then there might be little difference in using or not using the domready event, but usually scripts are called from the head tag, and at that point no elements of the body are available yet.
I have a few dynamic pages and I want to alter certain elements before the page has fully rendered.
My snippet is something like:
document.body.getElementById("change").innerHTML = "<img src...";
I do not have access to change the content server side.
Where is the best place to put the snippet to have the code run before the page it has rendered?
Rather, is putting the Javascript in either the HEAD (inside the window.onload event?) or before the closing BODY (not inside an event listener) optimal?
I'm afraid you are highly unlikely to be able to execute your script before the page renders. Sure you can place an inline script and have it use document.write(...) at the place you'd like it to display your content, but this is a horrible solution. Orherwise the best you can do is at the 'DOM Ready' event, although it's difficult to do on all browsers consistently, you really need a library to abstract the details. jQuery provides it's ready method to fire an event when the DOM is ready, rather than when the page and all resources are finished loading.
Since the browser usually renders elements immediately after they have been parsed the best way would be do place the code in a script element directly after the referenced element:
<div id="change"></div>
<script type="text/javascript">
document.body.getElementById("change").innerHTML = "<img src...";
</script>
Not sure I understand your problem correctly, but if you use an event listener inside the head (such as jQuery's $(document).ready()), you will be able to alter the element once the dom structure has been loaded by passing your snippet to the function (handler) being called when the event fires.
<HEAD>
//...
<SCRIPT type="text/javascript">
$(document).ready(function() {
$("#change").append(
$("<img src=\"...\">")
) ;
}) ;
<SCRIPT>
</HEAD>
Using core javascript you will have to fork your event listeners for mozilla (W3C) and internet explorer event specifications. There's loads of documentation on how to do that on the internet.
Either way the best thing to do in this case obviously would be to create the content yourself, not altering it post rendering.
AFAIK you cannot do this. Because before a page is rendered there won't be any element and you can't access elements that haven't been loaded to the DOM tree.
If you do not want to render any elements before you make the DOM changes, you could set CSS display: none on the body element and then change it to display: block once you're done.