Search code examples
javascriptdomaddeventlistenergetelementbyid

Using document.addEventListener breaks document.getElementById


really hope someone can help me out here. Cutting a very long story short, on a few replies on this site I've seen people write that we should move away from:

<body onLoad="init();">

In the HTML to:

document.addEventListener("DOMCONTENTLOADED", init, false);

In the JavaScript file so we aren't mixing interactive code with content code etc.

But by switching to this method my code breaks, I can no longer access the DOM tree, here is an example:

function Tester(){
    this.value1 = 10;
    this.container = document.getElementById("fred");
    this.list = this.container.childElementCount;       
    this.in_func = function(){
        alert(this.value1+" "+ this.list);
    };//end of this.in_func
}//end of function Tester
function init(){
    var alpha = new Tester();
    alpha.in_func();
}//end of function init

document.addEventListener("DOMCONTENTLOADED", init(), false);
<!doctype html>
<html>
  <head>
  <meta charset="utf-8">
  <title>Untitled Document</title>

  </head>

  <body><!--onLoad="init();"-->
    <section id="fred">
    <section id="elem1"></section>
    <section id="elem2"></section>
    <section id="elem3"></section>
    <section id="elem4"></section>
    <section id="elem5"></section>  
    </section>
  </body>
</html>

The this.container is always null so the childElementCount generates an error of:

"Uncaught TypeError: Cannot read property 'childElementCount' of null"

Yet when I comment out the event listener and use the onLoad technique it works, am I just doing something stupid? I've tried using a variable instead of using this.list, tried using querySelector instead of getElementById, I've tried "load" instead of "DOMCONTENTLOADED" but nothing seems to work.

I know it will be something really simple but I cannot find the solution anywhere online, maybe I am just searching for the wrong thing.

Please put me out of my misery.

thanks

Zen


Solution

  • This is the correct way of doing it:

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Untitled Document</title>
    <script>
    
    function Tester(){
        this.value1 = 10;
        this.container = document.getElementById("fred");
        this.list = this.container.childElementCount;       
        this.in_func = function(){
            alert(this.value1+" "+ this.list);
        };//end of this.in_func
    }//end of function Tester
    function init(){
        var alpha = new Tester();
        alpha.in_func();
    }//end of function init
      document.addEventListener("DOMContentLoaded", function(event) {
      init();
        console.log("DOM fully loaded and parsed");
      });
    
    // document.addEventListener("DOMContentLoaded", init(), false);
    </script>
    </head>
    
    <body>
    <section id="fred">
    <section id="elem1"></section>
    <section id="elem2"></section>
    <section id="elem3"></section>
    <section id="elem4"></section>
    <section id="elem5"></section>  
    </section>
    </body>
    </html>
    

    In you code you called init() and then passed it, but you should passed it as a function! document.addEventListener("DOMContentLoaded", init, false); That's why