window.onload in external script gets ignored in Javascript - javascript

index.html
<html>
<head>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
window.onload = function() {
console.log("hello from html");
};
</script>
</head>
<body>
<div class="bar">bar</div>
</body>
</html>
foo.js
// this js file will be completely ignored with window.onload
//window.onload = function() {
console.log("hello from external js");
var bar = document.getElementsByClassName("bar");
// this returns 0 instead of 1
console.log(bar.length);
//};
When window.onload is used in html, window.onload from external js will be ignored.
When window.onload from external js is commented out, bar.length returns 0.
When window.onload from html is removed, window.onload from external js works fine.
Can anyone explain why I can't use both window.onload?
If I had to use window.onload in html, how do tell if window is loaded from external js?

1)The way you're binding, you can have just one method attached to an event. You need to add an event listener for what you want.
window.addEventListener("load", function() { alert("hello!");});
Setting directly a method to the onload event will replace any previously attached method. But if you use listeners instead, you can have many of them bound to an event.
2)If you comment out the onload in your external file, when the document.getElementsByClassName("bar") is called, your document isn't ready yet, then, it will return 0 items.
3)Use the addEventListener as I explained in the first point. If you apply this in both places, it will work like a charm.

onload is a property of window. It acts like any other variable property. When you try to use it twice you're overwriting the original value with your second write.
So your entire external script is ignored when you wrap it in window.onload, because window.onload is then overwritten to be
function() {
console.log("hello from html");
};
If you want to do execute 2 functions, define 2 functions, a and b,
and set window.onload like this:
window.onload = function(){
a();
b();
}
Alternatively, you can bind 2 separate events in the way Alcides' answer suggests. My personal view is that its cleaner to do a single bind with multiple functions since its easier to know whats bound, know what order your functions will execute in, and see everything thats happening in one place, but its mostly a matter of style/preference if the order doesn't matter.

Thats Correct, you are overwriting your own onload, but you can always attach a new event listener to the window like this
function onLoadHandler(){
console.log("hello from external js");
var bar = document.getElementsByClassName("bar");
// page not loaded, so this returns 0 instead of 1
console.log(bar.length);
}
if (window.addEventListener) {
window.addEventListener('load', onLoadHandler); }
else if (window.attachEvent) { window.attachEvent('onload', onLoadHandler ); }

Related

Does "onload()" of HTML conflicts with the delay of loading javascript?

The thing is, i'm adding Annotorious to my openSeadragon project.
http://annotorious.github.io/demos/openseadragon-preview.html
to get this plugins start, Following are the options.
<script>
function init() {
anno.makeAnnotatable(document.getElementById('myImage'));
}
</script>
...
<body onload="init();">
<img src="example.jpg" id="myImage" />
</body>
Here is the problem, i use these to delay the loading of javascript on the viewer block.
<script type="text/javascript">
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
Once i add onload="init();" to my code.the viewer won't function.
Are there conflicts between these two? if so, how to solve it?
I think this should help:
<script type="text/javascript">
var htmlOnLoad = window.onload;
window.onload = function(e){htmlOnLoad(e); downloadJSAtOnload(e)};
</script>
The idea is to keep the handler bound with HTML and call both: the html- and js- handlers.
Onload behavior is like so:
(probably depends on the browser type - behavior will might change - I worked on chrome)
If you set body onload="_fn" it will work on page loads
If you add window.onload=_fn on top of the page script (before the body tag) they will both load (2 then 1)
If you will add window.onload on the most bottom area of the HTML. It will be the only one to be executed on page load. (body "onload" will be override)
Adding an event listener to the window - you can add as much as you need and they will all be loaded as ordered respectively.
When the load event fires you are trying to do two things:
Call init (which, in turn, calls anno.makeAnnotatable)
Asynchronously load the JavaScript which makes anno.makeAnnotatable available
You can't call the function before it exists. You have to delay the calling of init until the loading of the JS that downloadJSAtOnload triggers has finished. (The specifics of that depend on how downloadJSAtOnload works).

How can I make this function execute automatically / on load [duplicate]

Traditionally, to call a JavaScript function once the page has loaded, you'd add an onload attribute to the body containing a bit of JavaScript (usually only calling a function)
<body onload="foo()">
When the page has loaded, I want to run some JavaScript code to dynamically populate portions of the page with data from the server. I can't use the onload attribute since I'm using JSP fragments, which have no body element I can add an attribute to.
Is there any other way to call a JavaScript function on load? I'd rather not use jQuery as I'm not very familiar with it.
If you want the onload method to take parameters, you can do something similar to this:
window.onload = function() {
yourFunction(param1, param2);
};
This binds onload to an anonymous function, that when invoked, will run your desired function, with whatever parameters you give it. And, of course, you can run more than one function from inside the anonymous function.
Another way to do this is by using event listeners, here's how you use them:
document.addEventListener("DOMContentLoaded", function() {
your_function(...);
});
Explanation:
DOMContentLoaded It means when the DOM objects of the document are fully loaded and seen by JavaScript. Also this could have been "click", "focus"...
function() Anonymous function, will be invoked when the event occurs.
Your original question was unclear, assuming Kevin's edit/interpretation is correct, then this first option doesn't apply
The typical options is using the onload event:
<body onload="javascript:SomeFunction()">
....
You can also place your JavaScript at the very end of the body; it won't start executing until the doc is complete.
<body>
...
<script type="text/javascript">
SomeFunction();
</script>
</body>
Another option is to use a JS framework which intrinsically does this:
// jQuery
$(document).ready( function () {
SomeFunction();
});
function yourfunction() { /* do stuff on page load */ }
window.onload = yourfunction;
Or with jQuery if you want:
$(function(){
yourfunction();
});
If you want to call more than one function on page load, take a look at this article for more information:
Using Multiple JavaScript Onload Functions
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
</head>
<body>
</body>
</html>
You have to call the function you want to be called on load (i.e., load of the document/page).
For example, the function you want to load when document or page load is called "yourFunction". This can be done by calling the function on load event of the document. Please see the code below for more detail.
Try the code below:
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
yourFunction();
});
function yourFunction(){
//some code
}
</script>
here's the trick (works everywhere):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
For detect loaded html (from server) inserted into DOM use MutationObserver or detect moment in your loadContent function when data are ready to use
let ignoreFirstChange = 0;
let observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirstChange++ > 0) console.log('Element added on', new Date());
}
)).observe(content, {childList: true, subtree:true });
// TEST: simulate element loading
let tmp=1;
function loadContent(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadContent('Senna');
loadContent('Anna');
loadContent('John');
<div id="content"><div>

Passing reference to object javascript function

I have a function that gets called during a control update where 'This' is passed so the function knows what control is updating. I am also calling the function at page load to get initial values but sending document.getElementById() doesn't seem to work. What should I be passing here?
For example:
<script type="text/javascript">
window.onload = function () {
alert("Got to window.onload");
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
in the js file...
function materialSelectionChange(obj) {
alert("Got into function");
}
Also, it does fire the js function on change properly
EDIT
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. Likely because of window.onload. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?
You are not delegating for window load event, you are invoking it, also your missing quotes around the id:
window.onload = myFunction(document.getElementById(typeSelect));
Try wrapping it around:
window.onload = function() {
myFunction(document.getElementById('typeSelect')); //id in quotes
};
EDIT
You must take care of js file import, import must be first before invoking the function within:
<script src='your-script-file.js'></script>
<script type="text/javascript">
window.onload = function () {
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
<select id="typeSelect" onchange="myFunction(this)">
window.onload = function(){
myFunction.bind(document.getElementById('typeSelect'));
}
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?

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 call a JavaScript function on page load?

Traditionally, to call a JavaScript function once the page has loaded, you'd add an onload attribute to the body containing a bit of JavaScript (usually only calling a function)
<body onload="foo()">
When the page has loaded, I want to run some JavaScript code to dynamically populate portions of the page with data from the server. I can't use the onload attribute since I'm using JSP fragments, which have no body element I can add an attribute to.
Is there any other way to call a JavaScript function on load? I'd rather not use jQuery as I'm not very familiar with it.
If you want the onload method to take parameters, you can do something similar to this:
window.onload = function() {
yourFunction(param1, param2);
};
This binds onload to an anonymous function, that when invoked, will run your desired function, with whatever parameters you give it. And, of course, you can run more than one function from inside the anonymous function.
Another way to do this is by using event listeners, here's how you use them:
document.addEventListener("DOMContentLoaded", function() {
your_function(...);
});
Explanation:
DOMContentLoaded It means when the DOM objects of the document are fully loaded and seen by JavaScript. Also this could have been "click", "focus"...
function() Anonymous function, will be invoked when the event occurs.
Your original question was unclear, assuming Kevin's edit/interpretation is correct, then this first option doesn't apply
The typical options is using the onload event:
<body onload="javascript:SomeFunction()">
....
You can also place your JavaScript at the very end of the body; it won't start executing until the doc is complete.
<body>
...
<script type="text/javascript">
SomeFunction();
</script>
</body>
Another option is to use a JS framework which intrinsically does this:
// jQuery
$(document).ready( function () {
SomeFunction();
});
function yourfunction() { /* do stuff on page load */ }
window.onload = yourfunction;
Or with jQuery if you want:
$(function(){
yourfunction();
});
If you want to call more than one function on page load, take a look at this article for more information:
Using Multiple JavaScript Onload Functions
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
</head>
<body>
</body>
</html>
You have to call the function you want to be called on load (i.e., load of the document/page).
For example, the function you want to load when document or page load is called "yourFunction". This can be done by calling the function on load event of the document. Please see the code below for more detail.
Try the code below:
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
yourFunction();
});
function yourFunction(){
//some code
}
</script>
here's the trick (works everywhere):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
For detect loaded html (from server) inserted into DOM use MutationObserver or detect moment in your loadContent function when data are ready to use
let ignoreFirstChange = 0;
let observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirstChange++ > 0) console.log('Element added on', new Date());
}
)).observe(content, {childList: true, subtree:true });
// TEST: simulate element loading
let tmp=1;
function loadContent(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadContent('Senna');
loadContent('Anna');
loadContent('John');
<div id="content"><div>

Categories