Why document.onreadystatechange runs twice? - javascript

I have the following example below. I am curious why the console log writes the line 'document is ready' twice (both in FF as well as Chrome). How can I make sure it only runs once?
Additional question: since I am also using window.onload that already has an event attached, is it possible to add a window event without removing previously assigned ones?
<!doctype html>
<html>
<head>
<script>
window.onload=function(){console.log('window is ready');}
document.onreadystatechange = function(){console.log('document is ready');}
</script>
</head>
<body>
Hello
</body>
</html>

It runs multiple times because it have multiple states
https://developer.mozilla.org/en/docs/Web/API/Document/readyState
loading, interactive, complete
If you want to catch only one of them, just filter it using code similar to the one you see by the link

Related

How to rewrite an iframe multiple times with a script that declares a constant

I'm writing an in-browser HTML editor where users write HTML code that is sent (on every keystroke) to an iframe for preview purposes. This is the code I have now:
onCodeChange(html) {
iframe.contentDocument.open();
iframe.contentDocument.write(html);
iframe.contentDocument.close();
}
The problem appears when users try to add <script> tags with a const in them:
<!doctype html>
<html>
<body>
<script>
const a = 42;
</script>
</body>
</html>
When a user types in ... const a = 4 ... everything is fine (initial declaration of a as 4), but when they finish typing ... const a = 42 ... (redeclaration of a as 42), then an error is thrown:
Uncaught SyntaxError: Identifier 'a' has already been declared
I think that this happens because the JavaScript context remains the same even if the document is rewritten.
I have tried using srcdoc:
onCodeChange(html) {
iframe.srcdoc = html;
}
It works, but causes the iframe to flicker (I imagine that it unloads and loads the iframe) and I don't want users to have seizures...
I'm currently thinking about having two iframes (one on top of the other), using srcdoc, and swapping their z-index on load. It's very weird, but could fix the flickering.
Is there anything else I can do?
Just wrap your script with an IIFE every time you want to change the code.
<!doctype html>
<html>
<body>
<script>
(function(){const a = 42;})();
</script>
</body>
</html>

Chrome: JS loads before HTML

I'm learning Javascript and I'm very confused as to why I'm having issues with my javascript loading before the html when using Chrome. When I use Firefox and Edge, the page loads with the html first and then I get an alert. When I use Chrome though, I get the alert first and the background is just blank. Everything I'v learned so far seems to say that the js script should run after the html because it's at the bottom of the body tag.
Thanks!
home.html page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>Hi, testing chrome.</h1>
<h2>Is this working?</h2>
<ul>
<li>list1</li>
<li>list 2</li>
<li>list 3</li>
</ul>
<script type="text/javascript" src="myjs.js"></script>
</body>
</html>
myjs.js page
alert("Am I working right?");
If you want to make your html load first before js make sure to wrap it with
document.addEventListener("DOMContentLoaded", function(event) {
// your code here
});
Since the JavaScript is single threaded, so when you call alert() function, it blocks other execution because it is an UI blocking function.
The web uses an event driven model to sequence actions. You are correct in assuming that if the script appears at the end of a document, it will be parsed later than if it appeared at the beginning. But the HTML spec does not specify explicitly that HTML has to be rendered before your script is executed. So parsing and rendering are different operations, and chrome may choose to execute the script as soon as it finishes parsing it.
So how can you sequence your actions correctly? The web in general and javascript in particular are event driven. Your code can listen to a variety of events and respond to them as you please. In this case, you want to execute your script after your document has loaded. Take a look at the DOMContentLoaded event.
Here's your code modified to run when the DOMContentLoaded event is fired.
document.addEventListener("DOMContentLoaded", function() {
alert("Am I working right?");
});
I have simply enclosed your alert function call in my event handler function.
An event handler function (or callback) must be registered on the element that emits the event, in our case, the document object. This is done by calling addEventListener() on that object with two arguments. The first is the event name that we want to listen to as a string, and the second is a function that must be executed when the event is fired.
There are many events defined for many different elements, and you can even define your own custom events and respond to them.
Place the code in Jquery document ready method
The function DOMContentLoaded let the browser execute a javascript code after the HTML content has loaded
document.addEventListener("DOMContentLoaded", function(event) {
/*it is verry easy now, you can write code here which will be executed when the
html content will end loading*/
});
Something you should always do in your JS files is put every direct code and DOM-related functions in a function to wait for the page to load.
In plain JavaScript :
window.onload = function() {
//Your JS here
};
Note that according to this post, you can use document.onload(function() {...});
With JQuery :
$(function() {
//Your JS here
});
In plain JavaScript, try this in myjs.js
$(window).on("load", function(){
var ss = document.createElement("script");
ss.src = "myjs.js";
ss.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(ss);
});
ELSE
Try this if jQuery is loaded.
$(function() {
alert("Am I wrong?");
});
You will need to add
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js">
in the tag to include jQuery
This should make sure that the page is loaded. But please be informed that tag is also a part of the DOM
If the requirement is to execute the external JS after loading HTML, then you can try this.
$(function() {
var ss = document.createElement("script");
ss.src = "myjs.js";
ss.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(ss);
});

call function after complete page load

I'm using a javascript in my html page.. I have been recording the time taken using the navigation API .. When I try to findout the total load time (navigationStart - loadEventEnd) I find that the loadEventEnd is 0 . But also found that the loadEventStart value is recorded .. I print these values on console inside window.onload = function() {} . . From the above stats I assume that my function is called after the load event has fired and before it has completed .. However using onunload function gives me the result , the result cannot be viewed as it is printed in the console and unload event is triggered when moving away from the page .. Please help me find a solution .
Most likely you're getting a value of 0 because you're printing the information before the page has completed loading, try the following snippet:
window.onload = function(){
setTimeout(function(){
var t = performance.timing;
console.log(t.loadEventEnd - t.responseEnd);
}, 0);
}
That will make sure the numbers are printed after the page is actually ready. Got that snippet from here. Other information from that page you might find interesting:
Data from the API really comes to life when events are used in combination:
Network latency (): responseEnd-fetchStart.
The time taken for page load once the page is received from the server: loadEventEnd-responseEnd.
The whole process of navigation and page load: loadEventEnd-navigationStart.
Use the onload attribute in the tag as follows:-
<body onload="methodName();">
Try the following example for better understanding:-
<html>
<head>
<script type="text/javascript">
function test(){
alert("hello");
}
</script>
</head>
<body onload="test();">
<h5>Simple javascript test for page load</h5>
</body>
</html>
Try the following. i hope it will also work...
Use the window.onload object as follows:-
window.onload=function(){
//set of javascript statments...
}
or if you have any functions then use the window.onload as follows:-
window.onload=function_name
Have a look at the following example for better understanding of window.location
<html>
<head>
<script type="text/javascript">
window.onload = test;
function test(){
alert("hello");
}
</script>
</head>
<body>
<h5>Simple javascript test for page load</h5>
</body>
</html>

Chrome Javascript security?

So i have this empty page,
<html>
<head>
<title>JS</title>
<script type="text/javascript">
var container = document.getElementById("container");
console.log(container);
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
and for some reason console.log returns "null" instead of div object. But when i put code onto some website like jsfiddle, it works.
How do i fix this, is it a common problem?
JSFiddle may not mimic DOM loading correctly. The problem with your example is your JavaScript is executed before the DOM is completely loaded. The DOM is loaded top-down, so when your JavaScript is executed, the container div doesn't exist in the DOM yet.
You can move your script block after your div, that's a quick way to resolve the issue. Alternatively, you can listen for an event for when the DOM is loaded, then execute your code. This StackOverflow question demonstrates how to do that.

Why is document.GetElementById returning null [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 8 years ago.
I've been using document.GetElementById() successfully but from some time on I can't make it work again.
look at the following Code:
<html>
<head>
<title>no title</title>
<script type="text/javascript">
document.getElementById("ThisWillBeNull").innerHTML = "Why is this null?";
</script>
</head>
<body>
<div id="ThisWillBeNull"></div>
</body>
</html>
I am getting document.getElementById("parsedOutput") is null all the time now.
It doesn't matter if I use Firefox or Chrome, or which extensions I have enabled, or what headers I use for the HTML, it's always null and I can't find what could be wrong.
You can use the script tag like this:
<script defer>
// your JavaScript code goes here
</script>
The JavaScript will apply to all elements after everything is loaded.
Try this:
<script type="text/javascript">
window.onload = function() {
document.getElementById("ThisWillBeNull").innerHTML = "Why is this null?";
}
</script>
Without window.onload your script is never invoked. Javascript is an event based language so without an explicit event like onload, onclick, onmouseover, the scripts are not run.
<script type="text/javascript">
window.onload = function(){
document.getElementById("ThisWillBeNull").innerHTML = "Why is this null?";
}
</script>
Onload event:
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.
https://developer.mozilla.org/en/DOM/window.onload
Timing.
The document isn't ready, when you're getting the element.
You have to wait until the document is ready, before retrieving the element.
The browser is going to execute that script as soon as it finds it. At that point, the rest of the document hasn't loaded yet — there isn't any element with that id yet. If you run that code after that part of the document is loaded, it will work fine.
<script type="text/javascript">
window.onload += function() {
document.getElementById("ThisWillBeNull").innerHTML = "Why is this null?";
}
</script>
Use += to assign more eventHandlers to onload event of document.

Categories

Resources