Execution of code in <script> [duplicate] - javascript

This question already has answers here:
When does the browser execute Javascript? How does the execution cursor move?
(2 answers)
Closed 9 years ago.
When does the execution of code on tags begin? Is it sequential?
<html>
<head>
<title>Canvas tutorial</title>
<script type="text/javascript">
function draw(){
var canvas = document.getElementById('tutorial');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
}
}
</script>
<style type="text/css">
canvas { border: 1px solid black; }
</style>
</head>
<body onload="draw();">
<canvas id="tutorial" width="150" height="150"></canvas>
</body>
</html>
Above is a working piece of code. Why is script above the canvas element?

There are multiple choices for where to put script functions that will be called later.
In the <head> section. Scripts here will be available immediately and can be used by any other scripts that are executed while the document is being loaded.
In the <body> section mixed in with the HTML. These scripts will be executed at the time that location in the document is parsed. Everything that comes before the script in the DOM will be in place and ready. Everything that comes after the script will not yet be available.
At the very end of the body, right before the </body> tag. At the time these scripts execute, the whole document before it will be ready.
In your particular case, a function is defined in the <head> section so that it is available for execution at some later time. Because of the way the code appears in the <head> section, that code is only a function definition. Nothing actually executes when that code is parsed. The function itself is then executed when the page and its images are done loading via the onload handler specified in this line:
<body onload="draw();">
Only then is the code actually called and run. The draw() function could have been defined in any of the above three locations for this particular issue because the onload handler comes after all three options. As to why the script is above the canvas element, that is just a choice the designer of the page made. They could have located the script after the canvas element if they wanted and the page would have still worked fine.
A good working practice is to place scripts as late in the <body> as possible because that allows the page content to load and display quicker. But, some scripts are needed during the creation of the page (for example scripts that choose to use document.write()) so they must be placed earlier so they are available when needed. Scripts may also be marked defer or async to further delay their loading to allow content to be displayed first.

The preferred method is to put your scripts right below the closing body tag.
However, if it's essential to use a script on a page right away, it's best to keep it in the header.

Because the script merely defines a function that does not get invoked until the page is completely loaded (via the onload body attribute).

Inline elements will execute sequentially, as is the case in your example. However, all your current code does is define a function. It does not execute that function.
In your case you utilized the body onload= event to actually execute the draw() function. This is why you do not have a problem with the code, which seems to be the point of your initial question.
For this reason, it is typically recommended that you not place javascript in the head section unless absolutely necessary, and instead place it as close to closing body tag as possible.
With that said, in this case you define a function, but defining it and executing it are 2 different things. It is not a problem for you to define a function that you do not execute until the DOM is ready, and the DOM element(s) you want to work with are already rendered.
With that said, when you load external javascript files in the head section, it can cause the rendering of the page to block, and depending on the size and number of scripts you're loading that way, it's again advisable to place these at the end of the page. This will avoid the concerns you have in terms of the existence of DOM elements prior to execution of a function that attempts to manipulate those elements.

Do no use an onload attribute on the body element...in fact don't use any attributes on the body element ever.
<head>
<script type="application/javascript">
//<![CDATA[
window.onload = function() {/*load multiple functions here*/}
//]]>
</script>
</head>

Related

Javascript adding <script> tag after page loads

Got a little problem here. Basically, I'm trying to add a script tag after the page loads.
This is what I am doing:
index.php:
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function getad()
{
$.post('assets/getad.php', "ad", function(response) {
response = response.replace('document.write','document.getElementById("ad").innerHTML = ');
eval(response);
console.log(response);
});
}
getad();
</script>
<div id="ad"></div>
</body>
</html>
getad.php:
<?php
echo file_get_contents("http://ads1.qadabra.com/t?id=a823aca3-9e3c-4ddd-a0cc-14b497cad85b&size=300x250");
?>
You can find a demo here: http://dev.cj.gy/game/
As you can see, the #ad div DOES get filled with the correct script tag, but it doesnt actually run, If I edit the page to include the script tag right at page load, it does run.
Yes, <script> tags cause execution when parsed as part of the main document; they don't execute from being written to innerHTML.
You can create an executing script element outside of that initial parse using the DOM method of calling createElement('script'), setting its src/content and adding it to the document. This is what jQuery's getScript does.
However it wouldn't do you much good because the next script, that ads1.qadabra.com is document.writeing to the page, also itself calls document.write.
You could work your way around both of these calls at the client side (ie without getad.php), by assigning your own custom function to document.write that, instead of writing to the loading page, attempts to extract the source of the script tag passed to it, and load that in a DOM-created script element.
But in general these are scripts designed to work synchronously at document load time; anything you do to try to force them to run in a way they weren't intended to is likely to be fragile and stop working when the ad network change anything.
If you want to load a third-party ad without pausing the loading of the parent document, I suggest putting it in an iframe.

How to execute code before window.load and after DOM has been loaded?

Here is the circumstance:
I have 2 pages:
1 x html page
1 x external Javascript
Now in the html page, there will be internal Javascript coding to allow the placement of the window.onload, and other page specific methods/functions.
But, in the external Javascript I want certain things to be done before the window.onload event is triggered. This is to allow customized components to be initialized first.
Is there a way to ensure initialization to occur in the external Javascript before the window.onload event is triggered?
The reason I have asked this, is to attempt to make reusable code (build once - use all over), to which the external script must check that it is in 'order/check' before the Javascript in the main html/jsp/asp/PHP page takes over. And also I am not looking for a solution in jQuery #_#
Here are some of the links on Stack Overflow I have browsed through for a solution:
Javascript - How to detect if document has loaded (IE 7/Firefox 3)
How to check if page has FULLY loaded(scripts and all)?
Execute Javascript When Page Has Fully Loaded
Can someone help or direct me to a solution, your help will be muchness of greatness appreciated.
[updated response - 19 November 2012]
Hi all, thanks for you advice and suggested solutions, they have all been useful in the search and testing for a viable solution.
Though I feel that I am not 100% satisfied with my own results, I know your advice and help has moved me closer to a solution, and may indeed aid others in a similar situation.
Here is what I have come up with:
test_page.html
<html>
<head>
<title></title>
<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript" src="test_script_1.js"></script>
<script type="text/javascript" src="test_script_2.js"></script>
<script type="text/javascript">
window.onload = function() {
document.getElementById("div_1").innerHTML = "window.onload complete!";
}
</script>
<style type="text/css">
div {
border:thin solid #000000;
width:500px;
}
</head>
<body>
<div id="div_1"></div>
<br/><br/>
<div id="div_2"></div>
<br/><br/>
<div id="div_3"></div>
</body>
</html>
loader.js
var Loader = {
methods_arr : [],
init_Loader : new function() {
document.onreadystatechange = function(e) {
if (document.readyState == "complete") {
for (var i = 0; i < Loader.methods_arr.length; i++) {
Loader.method_arr[i]();
}
}
}
},
load : function(method) {
Loader.methods_arr.push(method);
}
}
test_script_1.js
Loader.load(function(){initTestScript1();});
function initTestScript1() {
document.getElementById("div_1").innerHTML = "Test Script 1 Initialized!";
}
test_script_2.js
Loader.load(function(){initTestScript2();});
function initTestScript2() {
document.getElementById("div_2").innerHTML = "Test Script 2 Initialized!";
}
This will ensure that scripts are invoked before invocation of the window.onload event handler, but also ensuring that the document is rendered first.
What do you think of this possible solution?
Thanking you all again for the aid and help :D
Basically, you're looking for this:
document.onreadystatechange = function(e)
{
if (document.readyState === 'complete')
{
//dom is ready, window.onload fires later
}
};
window.onload = function(e)
{
//document.readyState will be complete, it's one of the requirements for the window.onload event to be fired
//do stuff for when everything is loaded
};
see MDN for more details.
Do keep in mind that the DOM might be loaded here, but that doesn't mean that the external js file has been loaded, so you might not have access to all the functions/objects that are defined in that script. If you want to check for that, you'll have to use window.onload, to ensure that all external resources have been loaded, too.
So, basically, in your external script, you'll be needing 2 event handlers: one for the readystatechange, which does what you need to be done on DOMready, and a window.onload, which will, by definition, be fired after the document is ready. (this checks if the page is fully loaded).
Just so you know, in IE<9 window.onload causes a memory leak (because the DOM and the JScript engine are two separate entities, the window object never gets unloaded fully, and the listener isn't GC'ed). There is a way to fix this, which I've posted here, it's quite verbose, though, but just so you know...
If you want something to be done right away without waiting for any event then you can just do it in the JavaScript - you don't have to do anything for your code to run right away, just don't do anything that would make your code wait. So it's actually easier than waiting for events.
For example if you have this HTML:
<div id=one></div>
<script src="your-script.js"></script>
<div id=two></div>
then whatever code is in your-script.js will be run after the div with id=one but before the div with id=two is parsed. Just don't register event callbacks but do what you need right away in your JavaScript.
javascript runs from top to bottom. this means.. if you include your external javascript before your internal javascript it would simply run before the internal javascript runs.
It is also possible to use the DOMContentLoaded event of the Window interface.
addEventListener("DOMContentLoaded", function() {
// Your code goes here
});
The above code is actually adding the event listener to the window object, though it's not qualified as window.addEventListener because the window object is also the global scope of JavaScript code in webpages.
DOMContentLoaded happens before load, when images and other parts of the webpage aren't still fully loaded. However, all the elements added to the DOM within the initial call stack are guaranteed to be already added to their parents prior to this event.
You can find the official documentation here.

How do I know when DOM “body” element is available?

As soon as body DOM node is available, I'd like to add a class to it with JavaScript.
I want this to happen as soon as possible, before any of body's children are loaded.
Right now, I'm using an inline script right after opening body tag. Is there a less obtrusive way?
Might be a bit late to the party but...
You can just tap into the browser rendering cycle. Thus you don't have to deal with timeouts which leak memory (if improperly used).
var script = document.createElement('script');
script.src = '//localhost:4000/app.js';
(function appendScript() {
if (document.body) return document.body.appendChild(script);
window.requestAnimationFrame(appendScript);
})();
I would imagine this will differ between browsers.
One solution may be to test for it by placing a script immediately inside the opening <body> tag, then running your code at an interval to add the class.
<body>
<script>
function add_class() {
if(document.body)
document.body.className = 'some_class';
else
setTimeout(add_class, 10); // keep trying until body is available
}
add_class();
</script>
<!-- rest of your elements-->
</body>
jQuery does something similar internally to deal with a particular IE bug.
There isn't a guarantee that the descendant elements won't be loaded though, since again it will depend on when the particular implementation makes the body available.
Here's the source where jQuery takes a similar approach, testing for the existence of the body in its main jQuery.ready handler, and repeatedly invoking jQuery.ready via setTimeout if the body isn't available.
And here's an example to see if your browser can see the <body> element in a script at the top of the element, before the other elements. (Open your console)
Here's the same example without needing the console.

when and where to put javascript in html

I am new to Java script. I am practicing code.When i put my code in the head section, then i get element null, and when i put it inside body, but before element, then i also get null, but if i put it inside body, but after element then i get the element. I want to ask why i am getting null in case of the first two cases. Here is my code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/attributes.js"></script> // null
</head>
<body>
<script type="text/javascript" src="js/attributes.js"></script> // null
<a id="braingialink"
onclick="return showAttributes();"
href="http://www.braingia.org" >Steve Suehring's Web Site
</a>
<script type="text/javascript" src="js/attributes.js"></script> // ok
</body>
Here is my javascript
var a1 = document.getElementById("braingialink"); //get null in first two cases
window.alert(a1.getAttribute("href"));
a1.setAttribute("href", "www.google.com");
window.alert(a1.getAttribute("href"));
function showAttributes() {
var e = document.getElementById("braingialink");
var elementList = "";
for (var element in e) {
/**
* Sometimes, especially when first programming with JavaScript, you might not know what
* attributes are available for a given element. But you don’t have to worry about that, because
* of a loop that calls the getAttribute() method.
*/
var attrib = e.getAttribute(element);
elementList = elementList + element + ": " + attrib + "\n";
} //end of for()
alert(elementList);
} //end of function showAttributes
And also tell me, placing <script type="text/javascript" src="js/attributes.js"></script>
after the a element, is the same as i write script in the script tag , like
Steve Suehring's Web Site
<script type="text/javascript">
var a1 = document.getElementById("braingialink");
alert(a1.getAttribute("href"));
a1.setAttribute("href","http://www.microsoft.com");
alert(a1.getAttribute("href"));
</script>
Are both things mean to same?
Thanks
The browser parses the document from top to bottom, and if it encounters a <script> block (whether inline script or inclusion of an external JS file) it runs that JavaScript before parsing any more of the document. If that particular code block tries to refer to any elements it can only access the ones above it in the source, i.e., the ones already parsed.
The document.getElementById() method returns null if no element is found for the id you supply, so if you try to use it to access elements below it in the source they've not yet been parsed and can't be found.
The two most common practices to deal with this are:
Put all of your script at the bottom of the <body> such that when it runs all of the elements will have been parsed.
Create an "onload" handler, that is, define a function that will be run as soon as the document finishes loading. You can do this from a script block in the <head> - the JavaScript that defines the onload function is run immediately, but then the function is executed later after everything has loaded.
Following is the simplest way to do option 2:
window.onload = function() {
var x = document.getElementById("x");
// other element manipulation here
};
There is nothing stopping you doing 1 and 2 in the same document, along with throwing some <script> blocks in the middle of the document, but most people find it neater to keep all their code in the one spot.
You're getting null in the head because the DOM has not loaded - your objects are nonexistent at that time. Use this:
window.onload = function () {
// Your code
}
Oh and also take a look at the .ready() function of jQuery here. It would certainly help the headache later on.
Normally you should put script blocks inside the head tag. You can put them in the body tag if you have a special reason, for example to make the script load later because it comes from a slow server.
The reason that you can't access the element, is that the code runs before the browser has parsed the code for the element, so the element simply doesn't exist yet.
You use the load event to run the code after the document is loaded:
window.onload = function() {
// here you put the code that needs to access the elements
}
see http://www.w3schools.com/js/ and http://www.w3schools.com/js/js_whereto.asp
You can place an unlimited number of scripts in your document, and you can have scripts in both the body and the head section at the same time.
It is a common practice to put all functions in the head section, or at the bottom of the page. This way they are all in one place and do not interfere with page content.
You need to understand how web browsers load resources into a page. Firefox -> Firebug add-on Net tab shows the timeline of how resources are loaded. If you are using jQuery or something like it (and you aught to) - then stick your code inside $(document).ready(function() { .. } - that will ensure the page has fully loaded.
Also, it's a good practise to to include your custom js last thing before </body> tag - that way page DOM would have loaded.
Have a read if you want to understand this deeper:
http://www.goodreads.com/book/show/6438581-even-faster-web-sites
and
http://www.goodreads.com/book/show/1681559.High_Performance_Web_Sites
Best would be right before the closing body tag, to not disturb the page loading and rendering at all! It's also recommended by google, for example for analytics snippet and also by facebook!
you get nulls because your script executes while the browser is still loading the page. Since the page might not yet have all elements rendered, you get nulls. you need to run the script when the page has finished loading.
put your script in to the HEAD element, and invoke it on body's onload event.

How can we get an initial piece of JavaScript to run without referencing a function in your XHTML page?

Can we you get our JavaScript to run in the first place to
assign an event handler?
How can we get an initial piece of JavaScript to run without referencing a function in your XHTML page?
Just put a script tag in the body of your page and it will run as the page is rendered.
<script type="text/javascript">
// code goes here
</script>
Any code you put in a <script type="text/javascript"> tag will be executed immediately. Put it in your <head> and it will run before anything else. Put at the end of the <body> and it will run last.
Do keep in mind that the DOM may not be fully initialized in either of those cases. If you need the DOM use window.onload or jQuery's $(document).ready()
Also 'XHTML' and 'HTML' are not the same. XHTML is a very strict subset of HTML that in my opinion does nothing to improve upon regular HTML but it does allow for some fanciness. It has no effect whatsoever on JavaScript.
As you've tagged jQuery the way to do this is simply by including a ready function, e.g.
$(document).ready(function () {
// Assign your event handlers
});
Just put this code within a <script type="text/javascript"> block within your page.

Categories