Chrome loads js events before DOM loads - javascript

I was doing some javascript testing on chrome v71.0.3578.98, with the window.onload and I'm experiencing the js happening before the DOM loads
Ref gif: https://imgur.com/nxHYjRr
here is the code just wrapped in a simple html tag.
<h1>Title...</h1>
<p>lorem500...</p>
<script>
function pageLoad() {
alert('I\'m alive');
}
window.onload = pageLoad;
</script>
So in this basic page I tried running it in chrome v71 and the javascript ran first, but in firefox, opera it loaded after page loaded, as expected. Any thoughts?

The problem is that alert blocks - while an alert popup is visible, further page rendering is prevented, and when window.onload runs, the page may well not have rendered at all yet, especially if there isn't much HTML at all before it. All elements do exist in the document when the onload runs, they just may not be visible. (It depends on the browser)
alert is very user-unfriendly, as well as being difficult to work with (as you're encountering). Use console.log or a proper modal instead:
<h1>Title...</h1>
<p>lorem500...</p>
<script>
function pageLoad() {
console.log('I\'m alive');
}
window.onload = pageLoad;
</script>
If you had to use alert, only alert after an instant setTimeout, thus giving the browser a chance to paint the page before the alert gets called, just in case the browser hasn't rendered the page yet:
<h1>Title...</h1>
<p>lorem500...</p>
<script>
function pageLoad() {
setTimeout(() => {
alert('I\'m alive');
});
}
window.onload = pageLoad;
</script>

Related

Firefox not firing onload for dynamic nested iframe

I have the following code that works on Chrome and MS Edge but not on Firefox.
Parent.html has this script.
<html>
<body>
<script>
var ifr1 = document.createElement('iframe');
ifr1.onload = function() {
alert("iframe 1 loaded") //fires on all browsers
script = ifr1.contentWindow.document.createElement('script');
script.src = 'PATH/TO/script.js';
script.onload = function() {
alert("script 1 onload") //fires on all browsers
};
ifr1.contentWindow.document.body.appendChild(script);
};
document.body.appendChild(ifr1);
</script>
</body>
</html>
It creates an iframe and loads script.js within that iframe.
Here is script.js which does the same thing like above -
var ifr2 = document.createElement('iframe');
ifr2.onload = function() {
alert("iframe 2 loaded") //doesn't fire on Firefox
script = ifr2.contentWindow.document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js';
script.onload = function() {
alert("script 2 onload")
};
ifr2.contentWindow.document.body.appendChild(script);
};
document.body.appendChild(ifr2);
It creates another iframe ifr2 within the iframe ifr1 created by Parent.html.
Now, Chrome and Edge show all the alerts properly but Firefox doesn't fire the onload event for ifr2 loaded within ifr1 (even IE fires the onload for ifr2). Any idea why?
A workaround is to create a simple html page - even just <html><head></head><body></body></html> (maybe even less) .. lets call it empty.html
if you now change Parent.html to
<html>
<body>
<script>
var ifr1 = document.createElement('iframe');
ifr1.onload = function() {
alert("iframe 1 loaded") //fires on all browsers
script = ifr1.contentWindow.document.createElement('script');
script.src = 'PATH/TO/script.js';
script.onload = function() {
alert("script 1 onload") //fires on all browsers
};
ifr1.contentWindow.document.body.appendChild(script);
};
ifr1.src = 'empty.html'; // add this code *******
document.body.appendChild(ifr1);
</script>
</body>
</html>
Then it works as expected
Not sure why firefox does what it does - it could be because without the src attribute, the iframe's location is about:blank - but why the first one works and not the second is a mystery to me
edit: well, it did once then stopped again!!
OK, really strange - if you add ifr1.src = 'empty.html' it works ... if you duplicate that in script.js it breaks again
Not sure I've answered you well, but at least I've given you a working kludge :p
IMO this is a bug in Firefox because Firefox doesn't execute the load event inside iframes the way you would expect. The developers over at Mozilla may disagree. It all comes down to your definition of what "load" should mean, and it's more complicated than you think.
In any case the real issue is when to know it's safe to access ifr2.contentWindow, and the whole point of using ifr2.onload the way you did is so that you can figure out when ifr2.contentWindow exists.
Note, however, that the contentWindow and document are created immediately when document.body.appendChild(ifr2) executes, so if you move the appendChild() call to above your current code and remove the onload function, it will work as expected.
Alternatively you can change the onload function to something else and execute it directly after appendChild(), as such:
var ifr2 = document.createElement('iframe');
function loadit() {
console.log("iframe 2 loaded")
script = ifr2.contentWindow.document.createElement('script');
script.src = '...';
script.onload = function() {
console.log("script 2 onload")
};
ifr2.contentWindow.document.body.appendChild(script);
};
// add the iframe to the document
document.body.appendChild(ifr2);
// now execute your script stuff:
loadit()
This should work across all (modern) browsers.
While this is a bad practice and deprecated in chrome (it will show a warning in console.
adding this line before apending script tag fix the issue for me:
iframe.contentWindow.document.write('<html><head></head><body></body></html>');
It appears firefox needs it to init iframe and run javascript...

Plain JavaScript on-page-load event not working

The question is pretty simple: why is nither of those are working when they should? Tried in latest chrome and FF
document.addEventListener("DOMContentLoaded", function() {
alert("window on domcontentready");
}, false);
window.onload = function() {
alert("window on load");
}
http://jsfiddle.net/FHHgA/4/
The JavaScript is loaded on onload (inside jsfiddle), so onload won't fire, because it already fired.
Switch onload to no wrap - in <head>.
Create a blank html file and paste in your js, opening the html file will show the alerts. However it doesnt seem to display the alerts in in JSFiddler.

Attaching events to window.onload

I would like attach a function to window.onload so that it executes after everything is load. I have tried to do:
window.addEventListener('load', myFunction ,false);
window.onload = myFunction;
window.attachEvent('onload', myFunction); (this way does not work on Chrome)
What happens to me is that this function, looking at the Chrome's console (Network tab) is executed before window.onload (before the red line). I know this, because myFunction tries to load a remote javascript file and this file is loaded before red line.
I have also tried something more simple:
$(function() {
console.log("1111111");
});
window.onload=console.log("222222);
The output of that is:
22222222222
11111111111
Why ??? The first part should execute after DomContentLoaded and the second one after window.load isnt it? So why is this happening?
// This way does not work in Chrome
That's because you're using onload instead of load.

How to insert a javascript file into an iframe then call a function in the inserted javascript?

Edit: Just found out this is a chrome problem, the code works fine in firefox
I have an iframe on a webpage that shows a book formatted as html. I would like to insert some javascript within this iframe to make the book more dynamic (e.g. click on sentences, show animations etc). The iframe content is in the same domain as the parent page.
I can insert the javascript into the iframe but get an error calling a function in the inserted javascript. I've described the different bits of code below:
My parent page javascript is:
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
iFrameID.contentWindow.initialiseApi()
}
and the html containing the iframe is:
<iframe id="preview-iframe" width="640" height="240" frameborder="0" src="./testpage.htm" onload="iframeLoaded()" scrolling="no"></iframe>
The contents of iframeAPI.js is:
window.initialiseApi = function() { alert("Hello world") }
Looking at the iFrame's html in the browser shows that the iFrameAPI.js tag is inserted ok into the iframe head, but I don't get the alert popup when the page is loaded. The error appears on the following line:
iFrameID.contentWindow.initialiseApi()
Uncaught TypeError: Object [object Window] has no method 'initialiseApi'
However I can run this line in the browser's javascript console and the alert popup works fine.
Any help would be much appreciated.
Thanks,
Brian
Edit: I've just tried with an onload event to make sure the page is loaded and I still have the problem:
My parent page javascript is now :
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
jsLink.onLoad= iFrameLoaded();
}
function iFrameLoaded()
{
alert("Iframe loaded"); // Alert works ok
var iFrameID = document.getElementById('preview-iframe');
iFrameID.contentWindow.initialiseApi(); // Same error message on this line
}
It sounds like you are trying to use the function before the content has loaded.
try this instead:
var t = setTimeout(iFrameID.contentWindow.initialiseApi(),500);
This will wait half a second before trying the function which should give the page tiem to load. Delay times are given in milliseconds.
An even better approach is to try using Jquery and its ready() method but this requires the jquery library to be loaded as well. Its well worth it though in my opinion, see http://api.jquery.com/ready/.
You would try something like:
$("body",iFrameID.contentWindow.document).ready(iFrameID.contentWindow.initialiseApi())
You're executing it right away without giving the script a chance to load. Hook up an onload event to your script block and run your main function then.
Try, in the page included in the iFrame, accessing the main page by doing something like:
window.parent.xyz = something;
Where something is what you want exposed to the main page. Could be a function or an object of functions. Now in the main page you can just do:
something(); // or something.somefunction();
You could also send window references, I think, but I have not tried that.
The easiest way is to call the initialiseApi function in the iframeAPI.js itself as it will be called as soon as it's loaded. The iframeAPI.js could look like that:
function initialiseApi() {
alert("Hello world");
}
initialiseApi();
There is no callback or timeout needed.

Why does IE8 hangs on jquery window.resize event?

I discovered a problem that seems to reproduce always when opening a piece of html and javascript in IE8.
<html>
<body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(window).resize(function() {
console.log('Handler for .resize() called');
});
});
</script>
<div id="log">
</div>
</body>
</html>
Loading this file in IE8 and opening Developer Tools will show that the log message is printed continuously after one resize of the browser window.
Does anyone has an idea why? This is not happening in IE7 or IE9, nor in other browsers (or at least their latest versions).
UPDATE
One solution to prevent the continuos trigger of resize() is to add handler on document.body.onresize if the browser is IE8.
var ieVersion = getInternetExplorerVersion();
if (ieVersion == 8) {
document.body.onresize = function () {
};
}
else {
$(window).resize(function () {
});
}
But this does not answer my question: is the continuous firing of resize() a bug in IE8?
If "show window contents while dragging" is switched on, you will be inundated with resize events. I guess you're testing IE8 on a separate Windows machine which has this effect enabled (Display Properties -> Appearance -> Effects...).
To counteract this, you can wrap & trap the resize events to tame them: http://paulirish.com/demo/resize
This article says Chrome, Safari & Opera suffer from this too.
I only see the issue you are describing if an element on the page is resized (as described in this question). Your example doesn't work for me, but I assume for you it is appending the console message in the log div that you have there, which means that it is resizing the div and triggering the window resize event.
The answer that Lee gave is correct, but the method in the link didn't work for me. Here's what I did:
var handleResize = function(){
$(window).one("resize", function() {
console.log('Handler for .resize() called');
setTimeout("handleResize()",100);
});
}
handleResize();
This way, the handler is unbound as soon as it fires, and is only re-bound after you've finished all your actions that might re-trigger a page resize. I threw in a setTimeout to provide additional throttling. Increase the value in case your scripts need more time.

Categories

Resources