Defer attribute and onload event - javascript

Having the code below:
<html>
<head>
<script>
function elem_onload() {
console.log("elem_onload");
};
</script>
</head>
<body onload="elem_onload()">
<script type="text/javascript" src="script.js" defer></script>
</body>
</html>
script.js:
console.log("external script");
the defer attribute doesn't seems to work. The output is:
external script
elem_onload
whether with or without defer attribute. Shoudn't it be
elem_onload
external script
with defer defined?
Duplicated answer!?
I'd like to state that my answer isn't duplicate of
How exactly does <script defer=“defer”> work?
The referenced recommended answer is about inline script where the browser behavior is clear for me - it simply ignores defer. My question is about external script in which case the browser should execute the external deferred script
after the document has been parsed
as documentation states hence after onload event.
So I'm waiting for an appropriate answer...

The external script deferred by the defer attribute is executed before the (DOMContentLoaded) is fired, i.e. when the initial HTML document has been completely loaded and parsed. The onLoad attribute on a <body> tag, on the other hand, fires only when a web page is fully loaded.
Therefore, the defer attribute is indeed working. You may test it by trying the two cases below. In both cases the content of script.js file should be this:
console.log(document.getElementById('sample').innerHTML);
CASE 1 HTML - with defer --> logs "Sample text"
<body onLoad="elem_onload()">
<script type="text/javascript" src="script.js" defer></script>
<div id="sample">Sample text</div>
</body>
CASE 2 HTML - without defer --> logs an error
<body onLoad="elem_onload()">
<script type="text/javascript" src="script.js"></script>
<div id="sample">Sample text</div>
</body>

Thx. all for help.
So the statement "...after the document has been parsed" from original doc. (MDN <script> tag)
refers say step #0 from 12.2.6 The end
when document is completely parsed and now there are several tasks to be done on that occasion. Those tasks includes running external deferred scripts which
is prior (#3) to onload event.
Am I right?

Related

Script tags - not linking (JS platform game)

I'm working through the 'create a platform game' project from Eloquent JavaScript and have an issue with script tags.
In the book we're told to display our level using:
<link rel="stylesheet" href="css/game.css">
<script>
var simpleLevel = new Level(simpleLevelPlan);
var display = new DOMDisplay(document.body, simpleLevel);
</script>
I've tried adding this (together with an additional script tag for my platform.js file) into index.html but the browser is giving nothing back, not sure what I'm doing wrong?
Ensure you are inserting your scripts in the right order:
<!DOCTYPE html>
<html>
<head>
Here you should put your "included" scripts with <script src=...>
</head>
<body>
...
</body>
<script>
Here you should put your first execution, if it needs the html page been completely loaded (as to use document.body).
</script>
</html>
The scripts are being executed as they appear into the page. If you use document, you have to delay the execution until the whole page has been loaded: Either by putting your script at the end of the HTML, either by putting an initialization function within the HEAD, and call it from body onload:
<head>
<script>
function myFunction(){...}
</script>
</head>
<body onload="return myFunction()">
...
</body>
Make sure to include the external JavaScript file you need in a separate <script> tag before your inline script!

Difference between onload and script at end of body?

I'm new to JS and I'm not sure when exactly the functions are executed.
Example A:
<html>
<head>
<title>A</title>
<script src="myScript.js"></script>
</head>
<body onload="myFunction()">
[Content here...]
</body>
</html>
Example B:
<html>
<head>
<title>B</title>
<script src="myScript.js"></script>
</head>
<body>
[Content here...]
<script>
myFunction();
</script>
</body>
</html>
From what I've read so far the function is executed when the parser reaches it. Wouldn't that make example A and B the same? Is all the content (e.g. a table with text) of the page visible on the screen when myFunction() is called in B?
Adding the <script> at the end of the body essentially runs it once the items before that <script> are processed (you can think of it like running when the DOM of the body is done). Although onload waits not only for the DOM, but for all the contents inside to be completely done loading, such as images.
onLoad will wait untill the whole document has finished loading with images and such. The good thing about putting your scripts before the closing body tag, is that the user would see the page rendered sooner, if you have a heavy script in your head that takes a couple of seconds to download, the user would see a blank page until it loads the scripts and continues downloading the rest of the document. I would use both, onLoad to make sure the scripts gets executed when everything has loaded, and scripts at bottom so that users has the feeling that the page is loading fast :)

Why is $(document).ready needed after the <script> tag?

Why is $(document).ready needed after the <script> tag?
What would happen if we don't use $(document).ready?
$(document).ready is javascript code, so it has to be written in <script> element and after jQuery is loaded.
If you don't write $(document).ready, your code will not wait for DOM to load completely and execute the javascript code immediately.
If you're using script in <head> that is using/manipulating some elements from DOM, you'll need ready, otherwise you'll get null/undefined.
If you're using script at the end of <body>, then you'll be safe as all the elements are loaded.
Quoting as it is from jQuery Docs
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.
In cases where code relies on loaded assets (for example, if the dimensions of an image are required), the code should be placed in a handler for the load event instead.
Example? Sure!
In Head no ready
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script>
alert($('#myname').val());
</script>
</head>
<body>
<input type="text" value="Tushar" id="myname" />
</body>
</html>
At the end of body
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" value="Tushar" id="myname" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script>
alert($('#myname').val());
</script>
</body>
</html>
In head with ready
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
alert($('#myname').val());
});
</script>
</head>
<body>
<input type="text" value="Tushar" id="myname" />
</body>
</html>
For the <script> at the end of <body>, you can omit ready.
Why is $(document).ready really need after <script> tag when we use javascript.
It isn't.
What else if we don't use $(document).ready
First, understand why people use ready: It's used to delay the code within the function you pass into it until jQuery calls that function, which jQuery does when it thinks the document is fully loaded.
JavaScript code within script tags runs immediately. If the script tag is above an element it refers to, the element won't exist when the script runs:
<script>
$("#foo").show();
</script>
<div id="foo" style="display: none">...</div>
That div will not be shown, because it doesn't exist when the code runs. So people use ready to delay their code.
There's a better way if you control where your script tags go: Just put your script tag at the end of the document, just before the closing </body> tag:
<div id="foo" style="display: none">...</div>
<!-- ... -->
<script>
$("#foo").show();
</script>
</body>
All of the elements defined above the script tag will exist when the code runs. No need for ready.
The ready event occurs when the DOM (document object model) has been loaded.
Because this event occurs after the document is ready, it is a good place to have all other jQuery events and functions.
//Use ready() to make a function available after the document is loaded:
$(document).ready(function(){
$("button").click(function(){
$("p").slideToggle();
});
});
Like in the example above.
The ready() method specifies what happens when a ready event occurs.
Direct quote from Learn jQuery
A page can't be manipulated safely until the document is "ready."
jQuery detects this state of readiness for you. Code included inside
$( document ).ready() will only run once the page Document Object
Model (DOM) is ready for JavaScript code to execute. Code included
inside $( window ).load(function() { ... }) will run once the entire
page (images or iframes), not just the DOM, is ready.

Javascript `defer` doesn't seem to work

I have this code:
<!DOCTYPE html>
<html lang="en">
<head>
<script defer src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script defer>
// This function is supposed to run when the DOM is ready.
$(function() {
});
</script>
</head>
It works if I remove the defer's, but if I leave them in, or just the jquery one I get an error about how $ is undefined. Maybe I'm being an idiot but everything I've read about defer says it should load all the scripts and then run them when the document has been parsed.
This is with a recent Firefox.
From the HTML5 spec:
The async and defer attributes are boolean attributes that indicate
how the script should be executed. The defer and async attributes must
not be specified if the src attribute is not present.
Then, only jQuery is deferred, but not the inline script. Therefore, it attempts to use $ before it is defined, so it throws.

Window.onload vs procedural execution

When using procedural style the code seemed to be executing with the wrong width dimensions of an element (i suspect the code was executing before the element was finished being created), when i refreshed the page all was fine.
Issue:
<html>
<head></head>
<body>
<div id="parent">
</div>
<script language="javascript" type="text/javascript">
create_object(); // Creates an element and puts it inside div parent
</script>
</body>
</html>
Solution:
<html>
<head>
<script language="javascript" type="text/javascript">
window.onload = function(){
create_object(); // Creates an element and puts it inside div parent
}
</script>
</head>
<body>
<div id="parent">
</div>
</body>
</html>
What is the difference?
The window.onload waits for the page to load of course but since the is after the element.. shouldn't that be just fine?
No other java script is being executed on the page.
window.onload waits for all page resources (such as images and style sheets) to be loaded before calling its callback. In your first example, the DOM elements will all exist (because your code is executing at the end of the body after things before it have been parsed), but external resources like images may not yet be loaded and thus final layout may not yet be achieved so everything may not yet have its final size/layout.
window.onload is executed when DOM tree is ready and all resources are loaded (image, script, stylesheet ...). If you load your script in body without this callback, your div width can be wrong if you load image or stylesheet into this bloc ...

Categories

Resources