74

I have two functions on my form except one does not work if the other is active. Here is my code:

window.onload = function(event) {
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function() {
        $input2.value = $input1.value;
    });
}

window.onload=function(){
    document.getElementById('enable').onchange=function(){
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };
};

What I mean is that when I have both these functions in my form the second function works fine but the first will not work, if take out the second function the first one will work like normal, why is this happening? Is it because of the names?

lulalala
  • 17,572
  • 15
  • 110
  • 169
AJJ
  • 899
  • 3
  • 11
  • 16
  • Why don't you just add the functionality in the second function into the first one. Or call the second one from the first one. – Adarsh May 22 '13 at 03:55
  • 6
    Why don't you continue to use the better way for handling events - `addEventListener`? Then you wouldn't have overwriting problems like this – Ian May 22 '13 at 04:14

17 Answers17

136
window.addEventListener("load",function(event) {
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function() {
        $input2.value = $input1.value;
    });
},false);

window.addEventListener("load",function(){
    document.getElementById('enable').onchange=function(){
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };
},false);

Documentation is here

Note that this solution may not work across browsers. I think you need to rely on a 3-rd library, like jquery $(document).ready

Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • 4
    `+1` However, he used `addEventListener` already in his code, so this solution is fair. –  May 22 '13 at 04:05
  • 1
    +1 Answer below like extend or IE specific might satisfy cross browser support, if vanilla JS implementation is favor. It is good and simple if IE10 and other browser support addEventListener mean adding more EventListener in addition of default handle: onload, onReadyStateChange, readystatechange, which would' not affect from using third party script. Hope we won't have the problem of this specification mismatch in future. – Edward Chan JW Jul 14 '18 at 16:42
  • 1
    Caution about cross-browser support made sense back in 2013 when this question was written, but now in 2021 every browser still in non-negligible use supports `addEventListener`. For example, my data for the last year shows only 0.19% of users using IE, and of those, only 0.5% use IE <= 8 (the last version not to support this feature). So less than 1 in 100,000 users, and it will only decrease over time. Not worth worrying about. – cazort Dec 14 '21 at 17:02
48

If you can't combine the functions for some reason, but you have control over one of them you can do something like:

window.onload = function () {
    // first code here...
};

var prev_handler = window.onload;
window.onload = function () {
    if (prev_handler) {
        prev_handler();
    }
    // second code here...
};

In this manner, both handlers get called.

chad
  • 2,888
  • 1
  • 17
  • 15
  • 1
    This is the way I'd do it. +1 – Chris Kempen Oct 20 '15 at 10:06
  • 2
    I get `Uncaught RangeError: Maximum call stack size exceeded` error :( – joseantgv Sep 27 '16 at 11:46
  • 1
    I also got that stack overflow error. I believe the problem is that prev_handler ends up pointed to the window.onload function itself which in turn calls the prev_handler which calls the window.onload function. Try making a double delegate as shown in https://stackoverflow.com/questions/12213234/using-window-onload-more-than-1-times#answer-22377112 – Brett Jun 08 '17 at 16:20
  • Worked great for me. THX – Alex Manea Feb 28 '22 at 15:44
34

Try putting all you code into the same [and only 1] onload method !

 window.onload = function(){
        // All code comes here 
 }
Janak
  • 4,986
  • 4
  • 27
  • 45
  • 9
    I can't do this as my onLoad functions are dynamically echoed... =/ – Marcelo Dec 09 '16 at 18:47
  • When that happens, you may want to refactor the code where a single so-called registry gets all functions and then outputs a single function where other functions are called – Alexander Kucheryuk Feb 14 '21 at 17:20
16

You cannot assign two different functions to window.onload. The last one will always win. This explains why if you remove the last one, the first one starts to work as expected.

Looks like you should just merge the second function's code into the first one.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
13

window.addEventListener will not work in IE so use window.attachEvent

You can do something like this

function fun1(){
    // do something
}

function fun2(){
    // do something
}


var addFunctionOnWindowLoad = function(callback){
      if(window.addEventListener){
          window.addEventListener('load',callback,false);
      }else{
          window.attachEvent('onload',callback);
      }
}

addFunctionOnWindowLoad(fun1);
addFunctionOnWindowLoad(fun2);
rohit verma
  • 101
  • 1
  • 7
  • 1
    Works fine > tested on chrome – Ahmed Taha Dec 13 '21 at 00:59
  • Some 6+ years after your answer was working, it is more compatible than when you wrote it. It works in IE >=9. In my last year of data, it is less than 1 in 100,000 users who are still using IE <=8, and this number will only decrease over time. So I'd say from 2021 onward it is safe to use this approach. – cazort Dec 14 '21 at 20:02
10

Because you're overriding it. If you want to do it with onload you could just extend the previous function. Here's one way to do it:

Function.prototype.extend = function(fn) {
  var self = this;
  return function() {
    self.apply(this, arguments);
    fn.apply(this, arguments);
  };
};

window.onload = function() {
  console.log('foo');
};

window.onload = window.onload.extend(function() {
  console.log('bar');
});

// Logs "foo" and "bar"

Demo: http://jsbin.com/akegut/1/edit

Edit: If you want to extend with multiple functions you can use this:

Function.prototype.extend = function() {
  var fns = [this].concat([].slice.call(arguments));
  return function() {
    for (var i=0; i<fns.length; i++) {
      fns[i].apply(this, arguments);
    }
  };
};

window.onload = window.onload.extend(function(){...}, function(){...}, ...);
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • 1
    Only modify your own prototypes. Never modify the prototypes of standard JavaScript objects. Source: https://www.w3schools.com/js/js_object_prototypes.asp – Shayan Dec 10 '19 at 16:10
8

If you can not access to the old window.onload yet still want to keep and add another one, here is the way,

       function addOnload(fun){
          var last = window.onload;
          window.onload = function(){
            if(last) last();
            fun();
          }
        } 

        addOnload(function(){
            console.log("1");
        });

        addOnload(function(){
            console.log("2");
        });
serkan
  • 6,885
  • 4
  • 41
  • 49
7

if you use jQuery:

$(window).load(function() {
  //code
})

$(window).load(function() {
 //code
})
Sebastien Horin
  • 10,803
  • 4
  • 52
  • 54
4

For some time I used the above solution with:

window.onload = function () {
    // first code here...
};

var prev_handler = window.onload;
window.onload = function () {
    if (prev_handler) {
        prev_handler();
    }
    // second code here...
};

However it caused in some cases IE to throw a "stack overflow error" described here in this post: "Stack overflow in line 0" on Internet Explorer and a good write-up on it here

After reading through all the suggested solutions and having in mind that jquery is not available, this is what I came up with(further expanding on Khanh TO's solution with some browser compatibility checking) do you think such an implementation would be appropriate:

function bindEvent(el, eventName, eventHandler) {
            if (el.addEventListener){
                    el.addEventListener(eventName, eventHandler, false); 
                } else if (el.attachEvent){
                    el.attachEvent("on"+eventName, eventHandler);
                }
            }
      render_errors = function() {
      //do something
      }

      bindEvent(window, "load", render_errors);

      render_errors2 = function() {
      //do something2
      }

      bindEvent(window, "load", render_errors2);
Community
  • 1
  • 1
Tsonev
  • 435
  • 7
  • 17
4

Why not just call both functions from one onload-function?

function func1() {
    // code
}

function func2() {
    // code
}

window.onload = function() {
    func1();
    func2();
}
das Keks
  • 3,723
  • 5
  • 35
  • 57
3

If you absolutely must have separate methods triggered as the result of window.onload, you could consider setting up a queue of callback functions which will be triggered.

It could look like this in its simplest form:

var queue = [];
var loaded = false;

function enqueue(callback)
{
    if(!loaded) queue.push(callback);
    else callback();
}

window.onload = function()
{
    loaded = true;
    for(var i = 0; i < queue.length; i++)
    {
        queue[i]();
    }
}

And used in your case like so:

enqueue(function()
{
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function()
    {
        $input2.value = $input1.value;

    });

});

enqueue(function()
{
    document.getElementById('enable').onchange=function()
    {
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };

});
Marty
  • 39,033
  • 19
  • 93
  • 162
3

By keeping 2 window.onload(), the code in the last chunk is executed.

SadhanaP
  • 37
  • 3
2

When you put the second function into window.onload basically what you are doing is replacing a value. As someone said before you can put the two functions into one function and set window.onload to that. If you are confused think about it this way, if you had an object object, and you did object.value = 7; object.value = 20 the value would be 20 window is just another object

aaronman
  • 18,343
  • 7
  • 63
  • 78
2

You can not bind several functions to window.onload and expect all of these functions will be executed. Another approach is using $(document).ready instead of window.onload, if you already use jQuery in your project.

Xiaodan Mao
  • 1,648
  • 2
  • 17
  • 30
1

this worked for me

function first() {
    console.log(1234);
}

function second() {
    console.log(5678);
}

const windowOnload = window.onload = () => {
    first();
    second();
};

windowOnload();

console

1234

5678

Adam
  • 11
  • 1
  • 1
0

I didn't like other answers and found another way of doing this.

This can be achieved with this function.
readyState has 3 options loading, interactive and complete https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState

Therefore, this script would work:

<script>
  if (typeof whenDocReady === "function") {
    // already declared, do nothing
  } else {
    function whenDocReady(fn) {
      // see if DOM is already available
      if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
      } else {
        document.addEventListener("DOMContentLoaded", fn);
      }
    }
  }
</script>

Usage after defining this script:

<script>
whenDocReady(function() {
//do whatever stuff what you would do on window.onload
};
</script>

Credit: https://stackoverflow.com/a/9899701/1537394

Mladen Adamovic
  • 3,071
  • 2
  • 29
  • 44
0

using promises:

    function first(){
          console.log("first");
    }

    function second(){
          console.log("second");
    }
    
    isLoaded = new Promise((loaded)=>{ window.onload = loaded });
    isLoaded.then(first);
    isLoaded.then(second);