Execution order of html - javascript

I want to know HTML parser's parsing sequence.
Given two html files:
page1.html
<html>
<body>
<iframe id="x" src="page2.html"></iframe>
<div id="z"></div>
<--! something that need to be parsed -->
</body>
</html>
page2.html
<html>
<body>
<div id="y">
<body>
</html>
I know iframe tag downloads src in parallel (i.e., HTML parser parses subsequent lines of iframe tag although iframe src (in the example, page2.html) is not yet downloaded).
So, the question is, when the page2.html is parsed?
In other words, when the div element (id=y) is added to DOM tree?
Is it done after parsing codes in page1.html or done immediately after complete downloading of page2.html by blockinig page1.html parsing? Or, do HTML parser parses page1.html and page2.html in parallel (at the same time)?
Any comments and links would be appreciated.
Thanks!
(If there are wrong questions, please let me know. Actually, I am new to JavaScript and HTML)

Exact timing depends on the browser. page1 should be downloaded and ready first, before page2 is ready. However, page1 is not ready prior to the start of downloading and parsing page2.

The actual order things are done in is browser dependent, but in a typical browser, it first builds a tree of the HTML in the page you are visiting and then processes it. When it gets to processing the iframe, it will then go and request that page.
Now, this is complicated by the fact that the HTML is downloaded in chunks from the server, so from the partial tree, it might start downloading the content from the iframe before it's even seen half of page 1.
The take-away though is that you shouldn't be relying on this behaviour.

Related

How can my content script access element from an HTML web accessible resource page? [duplicate]

When embedding JavaScript in an HTML document, where is the proper place to put the <script> tags and included JavaScript? I seem to recall that you are not supposed to place these in the <head> section, but placing at the beginning of the <body> section is bad, too, since the JavaScript will have to be parsed before the page is rendered completely (or something like that). This seems to leave the end of the <body> section as a logical place for <script> tags.
So, where is the right place to put the <script> tags?
(This question references this question, in which it was suggested that JavaScript function calls should be moved from <a> tags to <script> tags. I'm specifically using jQuery, but more general answers are also appropriate.)
Here's what happens when a browser loads a website with a <script> tag on it:
Fetch the HTML page (e.g. index.html)
Begin parsing the HTML
The parser encounters a <script> tag referencing an external script file.
The browser requests the script file. Meanwhile, the parser blocks and stops parsing the other HTML on your page.
After some time the script is downloaded and subsequently executed.
The parser continues parsing the rest of the HTML document.
Step #4 causes a bad user experience. Your website basically stops loading until you've downloaded all scripts. If there's one thing that users hate it's waiting for a website to load.
Why does this even happen?
Any script can insert its own HTML via document.write() or other DOM manipulations. This implies that the parser has to wait until the script has been downloaded and executed before it can safely parse the rest of the document. After all, the script could have inserted its own HTML in the document.
However, most JavaScript developers no longer manipulate the DOM while the document is loading. Instead, they wait until the document has been loaded before modifying it. For example:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>
JavaScript:
// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});
Because your browser does not know my-script.js isn't going to modify the document until it has been downloaded and executed, the parser stops parsing.
Antiquated recommendation
The old approach to solving this problem was to put <script> tags at the bottom of your <body>, because this ensures the parser isn't blocked until the very end.
This approach has its own problem: the browser cannot start downloading the scripts until the entire document is parsed. For larger websites with large scripts and stylesheets, being able to download the script as soon as possible is very important for performance. If your website doesn't load within 2 seconds, people will go to another website.
In an optimal solution, the browser would start downloading your scripts as soon as possible, while at the same time parsing the rest of your document.
The modern approach
Today, browsers support the async and defer attributes on scripts. These attributes tell the browser it's safe to continue parsing while the scripts are being downloaded.
async
<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
Scripts with the async attribute are executed asynchronously. This means the script is executed as soon as it's downloaded, without blocking the browser in the meantime.
This implies that it's possible that script 2 is downloaded and executed before script 1.
According to http://caniuse.com/#feat=script-async, 97.78% of all browsers support this.
defer
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
Scripts with the defer attribute are executed in order (i.e. first script 1, then script 2). This also does not block the browser.
Unlike async scripts, defer scripts are only executed after the entire document has been loaded.
(To learn more and see some really helpful visual representations of the differences between async, defer and normal scripts check the first two links at the references section of this answer)
Conclusion
The current state-of-the-art is to put scripts in the <head> tag and use the async or defer attributes. This allows your scripts to be downloaded ASAP without blocking your browser.
The good thing is that your website should still load correctly on the 2% of browsers that do not support these attributes while speeding up the other 98%.
References
async vs defer attributes
Efficiently load JavaScript with defer and async
Remove Render-Blocking JavaScript
Async, Defer, Modules: A Visual Cheatsheet
Just before the closing body tag, as stated on Put Scripts at the Bottom:
Put Scripts at the Bottom
The problem caused by scripts is that they block parallel downloads. 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. While a script is downloading, however, the browser won't start any other downloads, even on different hostnames.
Non-blocking script tags can be placed just about anywhere:
<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
async script will be executed asynchronously as soon as it is available
defer script is executed when the document has finished parsing
async defer script falls back to the defer behavior if async is not supported
Such scripts will be executed asynchronously/after document ready, which means you cannot do this:
<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
* might throw "jQuery is not defined" error
* defer will not work either
-->
Or this:
<script src="document.write(something).js" async></script>
<!--
* might issue "cannot write into document from an asynchronous script" warning
* defer will not work either
-->
Or this:
<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
* might throw "jQuery is not defined" error (no guarantee which script runs first)
* defer will work in sane browsers
-->
Or this:
<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
* might not locate #header (script could fire before parser looks at the next line)
* defer will work in sane browsers
-->
Having said that, asynchronous scripts offer these advantages:
Parallel download of resources:
Browser can download stylesheets, images and other scripts in parallel without waiting for a script to download and execute.
Source order independence:
You can place the scripts inside head or body without worrying about blocking (useful if you are using a CMS). Execution order still matters though.
It is possible to circumvent the execution order issues by using external scripts that support callbacks. Many third party JavaScript APIs now support non-blocking execution. Here is an example of loading the Google Maps API asynchronously.
The standard advice, promoted by the Yahoo! Exceptional Performance team, is to put the <script> tags at the end of the document's <body> element so they don't block rendering of the page.
But there are some newer approaches that offer better performance, as described in this other answer of mine about the load time of the Google Analytics JavaScript file:
There are some great slides by Steve Souders (client-side performance expert) about:
Different techniques to load external JavaScript files in parallel
their effect on loading time and page rendering
what kind of "in progress" indicators the browser displays (e.g. 'loading' in the status bar, hourglass mouse cursor).
The modern approach is using ES6 'module' type scripts.
<script type="module" src="..."></script>
By default, modules are loaded asynchronously and deferred. i.e. you can place them anywhere and they will load in parallel and execute when the page finishes loading.
Further reading:
The differences between a script and a module
The execution of a module being deferred compared to a script(Modules are deferred by default)
Browser Support for ES6 Modules
If you are using jQuery then put the JavaScript code wherever you find it best and use $(document).ready() to ensure that things are loaded properly before executing any functions.
On a side note: I like all my script tags in the <head> section as that seems to be the cleanest place.
<script src="myjs.js"></script>
</body>
The script tag should always be used before the body close or at the bottom in HTML file.
The Page will load with HTML and CSS and later JavaScript will load.
Check this if required:
http://stevesouders.com/hpws/rule-js-bottom.php
The best place to put <script> tag is before closing </body> tag, so the downloading and executing it doesn't block the browser to parse the HTML in document,
Also loading the JavaScript files externally has its own advantages like it will be cached by browsers and can speed up page load times, it separates the HTML and JavaScript code and help to manage the code base better.
But modern browsers also support some other optimal ways, like async and defer to load external JavaScript files.
Async and Defer
Normally HTML page execution starts line by line. When an external JavaScript <script> element is encountered, HTML parsing is stopped until a JavaScript is download and ready for execution. This normal page execution can be changed using the defer and async attribute.
Defer
When a defer attribute is used, JavaScript is downloaded parallelly with HTML parsing, but it will be execute only after full HTML parsing is done.
<script src="/local-js-path/myScript.js" defer></script>
Async
When the async attribute is used, JavaScript is downloaded as soon as the script is encountered and after the download, it will be executed asynchronously (parallelly) along with HTML parsing.
<script src="/local-js-path/myScript.js" async></script>
When to use which attributes
If your script is independent of other scripts and is modular, use async.
If you are loading script1 and script2 with async, both will run
parallelly along with HTML parsing, as soon as they are downloaded
and available.
If your script depends on another script then use defer for both:
When script1 and script2 are loaded in that order with defer, then script1 is guaranteed to execute first,
Then script2 will execute after script1 is fully executed.
Must do this if script2 depends on script1.
If your script is small enough and is depended by another script
of type async then use your script with no attributes and place it above all the async scripts.
Reference: External JavaScript JS File – Advantages, Disadvantages, Syntax, Attributes
It turns out it can be everywhere.
You can defer the execution with something like jQuery so it doesn't matter where it's placed (except for a small performance hit during parsing).
The most conservative (and widely accepted) answer is "at the bottom just before the ending tag", because then the entire DOM will have been loaded before anything can start executing.
There are dissenters, for various reasons, starting with the available practice to intentionally begin execution with a page onload event.
It depends. If you are loading a script that's necessary to style your page / using actions in your page (like click of a button) then you better place it at the top. If your styling is 100% CSS and you have all fallback options for the button actions then you can place it at the bottom.
Or the best thing (if that's not a concern) is you can make a modal loading box, place your JavaScript code at the bottom of your page and make it disappear when the last line of your script gets loaded. This way you can avoid users using actions in your page before the scripts are loaded. And also avoid the improper styling.
Including scripts at the end is mainly used where the content/ styles of the web page is to be shown first.
Including the scripts in the head loads the scripts early and can be used before the loading of the whole web page.
If the scripts are entered at last the validation will happen only after the loading of the entire styles and design which is not appreciated for fast responsive websites.
You can add JavaScript code in an HTML document by employing the dedicated HTML tag <script> that wraps around JavaScript code.
The <script> tag can be placed in the <head> section of your HTML, in the <body> section, or after the </body> close tag, depending on when you want the JavaScript to load.
Generally, JavaScript code can go inside of the document <head> section in order to keep them contained and out of the main content of your HTML document.
However, if your script needs to run at a certain point within a page’s layout — like when using document.write to generate content — you should put it at the point where it should be called, usually within the <body> section.
Depending on the script and its usage the best possible (in terms of page load and rendering time) may be to not use a conventional <script>-tag per se, but to dynamically trigger the loading of the script asynchronously.
There are some different techniques, but the most straightforward is to use document.createElement("script") when the window.onload event is triggered. Then the script is loaded first when the page itself has rendered, thus not impacting the time the user has to wait for the page to appear.
This naturally requires that the script itself is not needed for the rendering of the page.
For more information, see the post Coupling async scripts by Steve Souders (creator of YSlow, but now at Google).
Script blocks DOM load until it's loaded and executed.
If you place scripts at the end of <body>, all of the DOM has a chance to load and render (the page will "display" faster). <script> will have access to all of those DOM elements.
On the other hand, placing it after the <body> start or above will execute the script (where there still aren't any DOM elements).
You are including jQuery which means you can place it wherever you wish and use .ready().
You can place most of <script> references at the end of <body>.
But if there are active components on your page which are using external scripts, then their dependency (.js files) should come before that (ideally in the head tag).
The best place to write your JavaScript code is at the end of the document after or right before the </body> tag to load the document first and then execute the JavaScript code.
<script> ... your code here ... </script>
</body>
And if you write in jQuery, the following can be in the head document and it will execute after the document loads:
<script>
$(document).ready(function(){
// Your code here...
});
</script>
If you still care a lot about support and performance in Internet Explorer before version 10, it's best to always make your script tags the last tags of your HTML body. That way, you're certain that the rest of the DOM has been loaded and you won't block and rendering.
If you don't care too much any more about in Internet Explorer before version 10, you might want to put your scripts in the head of your document and use defer to ensure they only run after your DOM has been loaded (<script type="text/javascript" src="path/to/script1.js" defer></script>). If you still want your code to work in Internet Explorer before version 10, don't forget to wrap your code in a window.onload even, though!
I think it depends on the webpage execution.
If the page that you want to display can not displayed properly without loading JavaScript first then you should include the JavaScript file first.
But if you can display/render a webpage without initially download JavaScript file, then you should put JavaScript code at the bottom of the page. Because it will emulate a speedy page load, and from a user's point of view, it would seems like that the page is loading faster.
Always, we have to put scripts before the closing body tag expect some specific scenario.
For Example :
`<html> <body> <script> document.getElementById("demo").innerHTML = "Hello JavaScript!"; </script> </body> </html>`
Prefer to put it before the </body> closing tag.
Why?
As per the official doc: https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics#a_hello_world!_example
Note: The reason the instructions (above) place the element
near the bottom of the HTML file is that the browser reads code in the
order it appears in the file.
If the JavaScript loads first and it is supposed to affect the HTML
that hasn't loaded yet, there could be problems. Placing JavaScript
near the bottom of an HTML page is one way to accommodate this
dependency. To learn more about alternative approaches, see Script
loading strategies.

Can an HTML / JavaScript pair reference another HTML file?

Given a completed page a.html, is it possible to build b.html which includes JavaScript such that b pulls data from a.html and outputs the data into b.html's window? That is, is there any such thing like src=whatever.js where one can declare a variable of the other HTML page, so that something like this line like this would work (obviously doesn't as it is)?
<html>
<head>
<title>b.html</title>
</head>
<body>
<script>
var images = a.document.body.getElementsByTagName ("img");
etc.
Thanks again for any help! I see the 'may have your answer' above, but that uses JQuery, which I'm not looking for.
The simple answer is 'no, javascript is explicitly forbidden from accessing local filesystem, so there's no way a.html can read the contents of b.html even if they reside in the same folder locally'.
That being said, however, if the are both being served by a web server, you could always ask it to fetch a.html for you and then use javascript to parse it, invisbile to the user, and extract the info you need from it.
Take a look at a rather clumsy example below, using invisible iframe HTML element - basically a container you can put on page and load a different page into, and then have access to its DOM tree. (There are limitations to prevent XSS attacks, but since both a.html and b.html are from one and the same domain, these do not apply in your case.)
a.html
<!doctype html>
<html>
<head>
......
</head>
<body>
...
<div id=aa>
Some interesting stuff...
</div>
...
</body>
</html>
b.html
<!doctype html>
<html>
<head>
......
</head>
<body>
...
<iframe src="a.html" onLoad="alert('The contents of div with id=aa from a.html is: ['+this.contentDocument.getElementById('aa').innerHTML+']');"></iframe>
...
</body>
</html>
Here, it loads the entire document a.html into element on page b.html (which you can make invisible through, say CSS) and, once it's loaded, it extracts the necessary div from the DOM tree of page a.html (which is accessible now through the iframe object in DOM of the current, b.html page) and makes use of its innerHTML property to prove that it can access it.
Here, the contentDocument property of the iframe object on page b.html points to the normal 'document' object of the page we have loaded into the iframe, giving us all the options we have when dealing with any page when we have its document root.
This example is clumsy by many counts of course, not least being the fact that you load TWO pages (b.html and a.html) into the browser (albeit a.html is invisible) instead of one and that is hardly efficient.
But it's a start and for realy simple scenarios it might be an adequate if unsophisticated solution )

Is there a specification of script execution order when using iframes?

It's fairly well known and understood that browsers will execute <script> elements in the order presented within the source of a page (barring defer and async etc). What I've not been able to establish is if there is a specification that guarantees an order across <iframe> elements also.
If my main page contains:
<html>
<head>
<script src="a.js"></script>
</head>
<body>
<iframe src="inner.html" />
<!-- ... -->
</body>
</html>
With inner.html being:
<html>
<head>
<script src="b.js"></script>
</head>
<body>
<!-- ... -->
</body>
</html>
Is it defined in a specification that a.js will execute before b.js?
What if the main page looks like this:
<html>
<head>
<script src="a.js"></script>
</head>
<body>
<iframe src="inner.html" />
<!-- ... -->
<script src="c.js"></script>
</body>
</html>
What is the guaranteed order of execution here, if there is one? Say a.js takes a long time to load - it's guaranteed to still run before c.js. But what if inner.html and all it's resources (including b.js) have loaded before a.js - is there anything in the HTML spec that says b.js will not run before a.js? If it all loads normally in a timely manner, is it defined in a spec somewhere as to whether b.js should execute before or after c.js?
The best I've managed to find so far from the <iframe> spec is:
When a Document in an iframe is marked as completely loaded, the user agent must run the iframe load event steps in parallel.
However that seems to just say (when you dig into the "iframe load event steps") that the load event will be dispatched in and amongst other things running on the main page, but doesn't say when the inner page will be parsed and content loaded and (critically) when scripts are to be run within it.
The specification of the script element seems clear to me:
There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed as soon as it is available, but without blocking further parsing of the page. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.
(Emphasis added.)
You ask:
Say a.js takes a long time to load - it's guaranteed to still run before c.js. But what if inner.html and all it's resources (including b.js) have loaded before a.js - is there anything in the HTML spec that says b.js will not run before a.js?
Yes, the section I quoted above implies that b.js won't run before a.js. Per the specification, parsing will stop while a.js is fetched and executed. Processing of the iframe is not going to happen until after parsing resume, which means that b.js cannot run before a.js.
c.js could execute before b.js. There is no single neat paragraph that I can point at to justify this though. The explanation for this is spread throughout the specification. What happens is that the iframe triggers a navigation to the URL passed in the src. (In the spec this is expressed as "Navigate the element's child browsing context to url." Navigation is described here.) This navigation event will cause a fetch to happen. (Fetch is described here.) And fetches are executed in parallel by default. A script element with src also fetches some data but (without async or defer) it also stops the parsing while the fetching happens.
Talking specific to chrome, each of the frames loaded inside the browser use the same render process but they have different contexts. (please check CEF3 underlying framework).Considering this fact only single process is responsible for both iframe and mainframe execution and following code, I think i can safely say that main frame loads first and then subframes are loaded. (can check callbacks we get from CEF3 on CEF test apps to confirm this again).
i.e. a.js and c.js are executed first and then b.js.
Parent HTML code:
<head>
<script type="text/javascript">
window.abc = "ramesh";
</script>
</head>
<body>
<iframe id="iframeId" src="testiframe.html">
</iframe>
<script type = "text/javascript">
for (i=0;i<10000;i++)
{
console.log("something");
}
var p = document.getElementById("iframeId");
console.log(p.contentWindow.testValue);
</script>
</body>
iframe code:
<script type="text/javascript">
window.testValue = "pqrs";
console.log("xyz");
</script>
<body>
</body>
iframe code should take far less time than the for loop I am printing. But this code always prints consoles from main frame first and if i try to access testValue from iframe's contentWindow, it says undefined (this is done to check its not about console log printing order and actual javascript execution order).
Hope this helps. Let me know if I missed any detail while coming to this conclusion.

Detect the completion of js script files present at bottom

The following link http://developer.yahoo.com/performance/rules.html#js_bottom says
"Put Scripts at the Bottom" for Speeding Up Your Web Site. Lets say I have added them at bottom
<html>
<head></head>
<body>
...
...
...
html
....
<script src="script1"/>
<script src="script2"/>
<script src="script3"/>
</body>
</html>
Now if I have the requirement to access some function of those js files somewhere in the middle of html, how would I do that? Let's say the code is like this
<html>
<head></head>
<body>
...
...
...
html
.....
<script>
$('a.test').modal('show);
</script>
....
<script src="script1"/>
<script src="script2"/>
<script src="script3"/>
</body>
</html>
Above "$", "modal" etc are the part of js libraries attached at the bottom of the page. How will I detect the completion of bottom scripts and fire the code written in script tag (
$('a.test').modal('show);
)
To execute a script you have to make sure you have to provided all the necessary dependencies for that script. Hence, you have two options:
Put necessary script references before the particular script
Put the script at the bottom of the page.
Nothing is set in stone and the real solution depends on your particular problem.
Its a general good coding practice to keep all scripts at one portion of html.
Having said that, i would suggest the same thing, to have maximum of script loading at the bottom, this helps in quick loading.
As far as dependencies go, if you script is dependent on something, try including it before it is called. Its basically iterative :)
You'll have to consider your design and what you want to do with your page.
Start with your hypothesis: Putting tags at the bottom speeds up your website.
Does it speed up your website? not really. So what does it do? The advantage of loading a script at the bottom of the DOM means that the DOM always gets loaded first.
The page is parsed from top to bottom, as soon as a script tag is encountered it gets executed. If the script tag has a link on it that script gets loaded synchronously, holding off rendering of the DOM.
If you absolutely need jQuery to do stuff in the middle of the page, load it on top. Is your webpage now slower? Yeah, it took a second to load jQuery. Were your audience impacted? By how much? a second?
Takeaways: Loading a script at the top is fine. Loading 10 scripts that end up being about 1 mbyte combined is not because it impacts UX.
As other people have mentioned, you can always selectors to manipulate that part of the code, no need to run a script in the middle of the page. It's a better practice to separate your UI from your code anyways.
You can defer execution of $ so that your code doesn't run until after your scripts have loaded.
http://www.mrclay.org/2010/11/14/using-jquery-before-its-loaded/

JQM: How to break while debugging in a JS file loaded through $.mobile.changePage()

I am developing a mobile app using jQuery, jQuery mobile (and PhoneGap, but that is not relevant). Let's say I have two html pages: page1.html and page2.html. I am loading page2.html using $.mobile.changePage() from page1.html. The page div in page2.html (i.e., the div having data-role="page") contains javascript code that is specific to page2, which also gets loaded with page2.html. The code in page2.html looks something like this:
<!DOCTYPE HTML>
<html>
<head>
<title>Title</title>
</head>
<body>
<div id="conf-page" data-role="page">
<script type="text/javascript" charset="utf-8">
<!-- MY SCRIPT HERE ----->
</script>
<div data-role="header" style="height: 45px">
Now I want to break somewhere in the javascript code in page2.html. For the time being, I am using Firefox (16.0.2) and Firebug to develop and debug. When page2.html is loaded, I see the JS code of page2.html at two places in firebug Scripts list:
At jQuery.min.js/eval/MD5/
At jQuery.min.js/eval/seq/<#>
If I put a breakpoint somewhere in one of the codes, it get applied to the code in (1) above, but it is never hit when page2.html is loaded.
How to go about setting a breakpoint and breaking somewhere in the JS code in page2.html? I couldn't find anything relevant on the web, which makes me think that I must be missing something, as this must be a pretty common requirement.
Looks like I was searching for different terms. There has been some discussions on this problem in this site. Here are a few references:
dynamically loaded js function does not appear in Firebug js debugger
Scripts added via jQuery not visible in FireBug
Debugging scripts added via jQuery getScript function
A few other ones.
There are two solutions suggested in the above threads:
Most of these threads suggest the same solution: use the "debugger;" statement (w/o the quotes) twice in the code for the FireBug debugger to stop. I did that, and it was a partial solution: the firebug did break, but the variable stack was empty. So this wasn't very useful.
Put the script in a file, use an AJAX Get call to load the script with crossdomain set to true, and that gets the script file, loads it and the script file shows in debugger. That can be used now to set breakpoints etc. More useful than above.
Keeping open to see if there are other solutions.

Categories

Resources