According to this question, by the time the body onload gets called, all of the objects in the document are in the DOM, and all the images and sub-frames have finished loading.
I have some JS that is supposed to fire at body onload but my attempts to getElementByID are returning null which makes me think it's firing earlier than I think it is.
Am I wrong in my interpretation of body.onload or am I doing something else wrong?
Here is my code:
<script type="text/javascript">
window.document.body.onload = doStuff;
function doStuff() {
var txtElement = document.getElementById("myTextField");
if (txtElement != null) {
alert(txtElement.value);
}
else {
alert("Element not found!"); //This alert is always thrown
}
}
</script>
You are actually calling the doStuff function before the DOM is loaded because you have parenthesis after the function name, which causes the function to be invoked as soon as that line is encountered.
When you register a function as a callback to an event, you just want to reference the function, not invoke it. Also, you only need to register the "page" load function to the window.
Change:
window.document.body.onload = doStuff();
to:
window.onload = doStuff;
Additionally, you should modernize your code and, instead of using an event property of an element (which only allows for one function to be stored as a callback to an event), you should use the addEventListener() method to register callback functions.
Lastly, the type attribute is no longer necessary on script tags.
<script>
window.addEventListener("load", doStuff);
function doStuff() {
var txtElement = document.getElementById("myTextField");
if (txtElement != null) {
alert(txtElement.value);
}
else {
alert("Element not found!"); //This alert is always thrown
}
}
</script>
Related
Let's say there is a function that registers event handler for page load:
function onLoad(pageLoadedHandler) {
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler)
}
As it turned out, if page is already loaded pageLoadedHandler will not be called. I want onLoad function to call passed event handler if page is already loaded, so how can we check this?
We can go with some ugly way like this:
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded( function () {
window.pageIsAlreadyLoaded = true;
} );
function onLoad(pageLoadedHandler) {
if(window.pageIsAlreadyLoaded){
pageLoadedHandler();
} else {
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler);
}
}
It will only require putting this code to the early loaded JS file. But there should be a nice way to do this checking.
There are a number of posts on StackOverflow and other websites regarding the problem of avoiding namespace collisions. In my scenario, I just want a method in my JavaScript to be executed after the DOM is accessible.
If I do the following will it avoid namespace collisions?
<script type="text/javascript">window.onload = function() { //Define my namespace var here, and execute all my code }</script>
What if a script that is injected later also sets an onload function ? Will mine get overwritten? I'm fully aware that I can test this out, but I would also like some feedback as I am new to JavaScript and there could be a number of other scenarios which will do the something that I am not aware of.
EDIT: I need to support only Safari 5.0+
Yes, the last one will overwrite the previous ones.
The solution: use the new event API: addEventListener.
This is a fine Javascript way to do it right
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
/* more code to run on page load */
});
Explained Source
There's lots of information on this, but here's the short version:
if you want to play nicely with onload, you can do
var prev_onLoad = window.onload;
window.onload = function() {
if (typeof(prev_onLoad)=='function')
prev_onLoad();
// rest of your onLoad handler goes here
}
and hope that other's play nicely or make sure that's the last setting of onload in the code.
However, more modern browsers have event registration functions (addEventListener and attachEvent on IE) which take care of this chaining among other things. Quite a few cross-browser onload event functions have been written which take care of this logic for you.
It'll be overriden .
In Javascript, when you define handle event like
window.onload = function(){
console.log("in Load function 1");
};
window.onload = function(){
console.log(" In load function 2");
};
That will make an " assign " window.onload => function() . And window.onload will be assign to last function .
But in jQuery,
You can handle event in many times and the browser will make all
$("body").on("click",function(){
console.log("make a callback function 1");
});
$("body").on("click",function(){
console.log("make a callback function 2");
});
Because jQuery make a callback not "assign".
Hope it helps you.
I'm just trying to to register onclick for div, but it's not working. Instead, the cal to alert is getting triggered when page is loaded.
function print()
{
alert(' div clicked..');
}
var divElement = document.getElementById("content");
divElement.addEventListener("onclick", print());
Here's a jsFiddle.
The problem is you do not need the on prefix. And print should not have empty parenthesis. An empty parenthesis will cause the function to execute, and its return value be passed as the function to call - which is not what you want.
Try this:
var divElement = document.getElementById("content");
divElement.addEventListener("click", print);
Here's an updated working jsFiddle.
Edit: Per Ian's comment below, here's a helper function for backwards compatibility with certain version of Internet Explorer.
function AttachEventListener(element, event, handler) {
if (element.addEventListener) {
element.addEventListener(event, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + event, handler);
} else {
alert('Invalid element specified for AttachEventListener');
}
}
Instead of using divElement.addEventListener("click", print), you would do AttachEventListener(divElement, 'click', print).
The main reason to use the helper function is because older versions of Internet Explorer do not have addEventListener, and do require the on prefix when using attachEvent. This helper function will save you the trouble of doing the feature-check yourself on every event binding.
You should write it like this:
divElement.addEventListener("click", print);
print is a variable that points to your function.
print() is the output of that function. (it has no output, so it's undefined)
Since you want to assign the function, not the output, you must use print.
Also, you don't need the on prefix.
Presto: http://jsfiddle.net/AEjKC/
From what I have gathered, the former assigns the actual value of whatever that functions return statement would be to the onload property, while the latter assigns the actual function, and will run after the window has loaded. But I am still not sure. Thanks for anyone that can elaborate.
window.onload = init();
assigns the onload event to whatever is returned from the init function when it's executed. init will be executed immediately, (like, now, not when the window is done loading) and the result will be assigned to window.onload. It's unlikely you'd ever want this, but the following would be valid:
function init() {
var world = "World!";
return function () {
alert("Hello " + world);
};
}
window.onload = init();
window.onload = init;
assigns the onload event to the function init. When the onload event fires, the init function will be run.
function init() {
var world = "World!";
alert("Hello " + world);
}
window.onload = init;
window.onload = foo;
assigns the value of foo to the onload property of the window object.
window.onload = foo();
assigns the value returned by calling foo() to the onload property of the window object. Whether that value is from a return statement or not depends on foo, but it would make sense for it to return a function (which requires a return statement).
When the load event occurs, if the value of window.onload is a function reference, then window's event handler will call it.
Good answers, one more thing to add:
Browser runtimes ignore non-object (string, number, true, false, undefined, null, NaN) values set to the DOM events such as window.onload. So if you write window.onload = 10 or any of the above mentioned value-types (including the hybrid string) the event will remain null.
What is more funny that the event handlers will get any object type values, even window.onload = new Date is a pretty valid code that will prompt the current date when you log the window.onload. :) But sure nothing will happen when the window.load event fires.
So, always assign a function to any event in JavaScript.
I have two js files, each one with its own window.onload handler. Depending on how I attach the two onload handlers to the window object I get a different behaviour on the second handler.
More specifically, here is my html file:
<html>
<head>
<title>Welcome to our site</title>
<script type="text/javascript" src="script1.js"> </script>
<script type="text/javascript" src="script2.js"> </script>
</head>
<body id="pageBody">
<h2 align="center">
Wellcome to our site... c'mon in!
</h2>
</body>
</html>
It loads two js files, script1.js and script2.js.
Here is the version of these two scripts that leads to the (at least by me) unexpected behaviour.
Script1.js:
window.onload = initAll1(); // attach first onload handler
function initAll1() {
alert("initAll1");
document.getElementById("redirect").onclick = foo; // attach an onclick handler
}
function foo() {
alert("we are in foo");
return false;
}
Script2.js:
addOnloadHandler(initAll2); // with this we should attach a second onload handler
function initAll2() {
alert("initAll2");
if (linkHasOnclickHandler(document.getElementById("redirect"))) {
alert("correct!");
}
else {
alert("wrong!");
}
}
function addOnloadHandler (newFunction) {
var oldevent = window.onload;
if (typeof oldevent == "function") {
window.onload = function() {
if (oldevent) {
oldevent();
}
newFunction();
};
}
else {
window.onload = newFunction;
}
}
function linkHasOnclickHandler() {
var oldevent = document.getElementById("redirect").onclick;
if (typeof oldevent == "function") {
return true;
}
else {
return false;
}
}
In Script2.js I tried to add the second onload handler in a nice noninvasive way using function addOnloadHandler(). This function does not make any assumption on whether there is already any onload handler attached to the window object. It is noninvasive because it should add the new handler without deleting previous ones.
The thing is that when loaded with addOnloadHandler(), initAll2() is not capable of detecting the fact that document.getElementById("redirect") already has foo() attached as an onclick event handler (see initAll1()). The alert message "wrong!" is triggered, which to me seems to be the wrong behaviour.
When I forget about addOnloadHandler() and attach both onload handlers in Script1.js using:
window.onload = function () {initAll1(); initAll2();};
then everything works as expected, and initAll2() launches the "correct!" alert message.
Is there something wrong about addOnloadHandler()? Could anybody make it work? I would really like to use it instead of the second method.
Thanks!
Just in case future people find this, and are looking for a way to use multiple event handlers when the object itself doesn't support addEventListener, attachEvent or some other form of listener stacking - i.e. it is a bespoke object, badly implemented. Then you can do the following:
object.onload = (function(pre){
return function(){
pre && pre.apply(this,arguments);
/// do what you need for your listener here
}
})(object.onload);
Each time you use the above code the previous onload listener is passed in as an argument, and when your new listener is triggered it runs the old listener first - meaning you can stack many listeners like this, if you so wish. However, this will only work for as long as the above code is always used to add listeners to your object. All your hard work will be undone if somewhere else it is overridden with a simple:
object.onload = function(){}
As a note to coders, if you are to implement a library, plugin or constructor, and it is possible other coders will take over your work. Please, please code the ability for multiple event listeners. It's really not that difficult.
You need to look at addEventListener and attachEvent, which are native implementations of your addOnloadHandler.
PPK's reference on addEventListener explains how do this pretty well:
http://www.quirksmode.org/js/events_advanced.html
Thanks for the answers!
I rewrote my script2.js using addEventListener and attachEvent like this:
//addOnloadHandler(initAll1); // it works only when uncommenting this
addOnloadHandler(initAll2);
function initAll2() {
alert("initAll2");
if (linkHasOnclickHandler(document.getElementById("redirect"))) {
alert("correct!");
}
else {
alert("wrong!");
}
}
function addOnloadHandler(newFunction) {
if (window.addEventListener) { // W3C standard
window.addEventListener('load', newFunction, false); // NB **not** 'onload'
}
else if (window.attachEvent) { // Microsoft
window.attachEvent('onload', newFunction);
}
}
function linkHasOnclickHandler(element) {
var oldevent = document.getElementById("redirect").onclick;
if (typeof oldevent == "function") {
return true;
}
else {
return false;
}
}
As you can see, addOnloadHandler() has been rewritten using the native implementations you guys mentioned. I left script1.js untouched.
The resulting code still does not work (i.e., the "wrong!" alert message is shown). It only works when I register the onload initAll1() handler twice by uncommenting the first line of code in script2.js.
Apparently, mixing
window.onload = handler1;
and
window.addEventListener('load', handler2, false);
or
window.attachEvent('onload', handler2);
does not work fine.
Is there any way to work around this problem that does not imply touching script1.js?
Just in case you wonder why I don't want to touch script1.js, the reason is that I want my code (script2.js) to be reusable in other projects as well, no matter which other js files each project uses. So, it should work with every possible event-handling registration method used in script1.js.
thanks once more for your help!