javascripthtmllisttreeview

Why is child html object undefined/null


i can't figure out why the child object returns undefined in this code.

What the code does is create a tree of html objects it finds the child objects and the parent object of that element it finds an elements child objects, then adds them to a list, you can then (or meant to be able to) click on that list select the child you want and then that regenerates the tree with the child object you selected as the new current object.

an example

<div id="setone">
     <div id="setwo-one">
         <div id="setthree">
         </div>
     </div>
     <div id="settwo-two">
     </div>
</div>

the list will first select setone which becomes the current object you will see the child objects settwo-one and settwo-two you then click on them and then they become the current object except when you click on the childobject the onclick > elementstart.children[i] < becomes undefined and then can't find the tag or id of the object so the list breaks.

function treedialogupdate(elementstart)
{
if(elementstart != null)
{
    var treelog = document.getElementById("treedialog");

    var listset = treelog.getElementsByTagName("UL")[0];
    listset.innerHTML = "";
    var beforeitem = treelog.getElementsByClassName("before")[0];
    var startitem = treelog.getElementsByClassName("start")[0];

    startitem.innerHTML =  "Current Object: " + elementstart.tagName + " " + elementstart.id;

    for(i = 0; i < elementstart.children.length; i++)
    {
        if(elementstart.children[i].tagName)
        {
            listset.innerHTML += "<li>" + elementstart.children[i].tagName + " " + elementstart.children[i].id + "</li>";

        }   
    }
    for(i = 0; i < childObjectList.length; i++)
    {
        listset.children[i].onclick =function(){ 
        treedialogupdate(elementstart.children[i]); };
    }

    if(elementstart.parentNode != null || elementstart.parentNode == "undefined")
    {
        beforeitem.innerHTML = "Parent Object: " +  elementstart.parentNode.tagName + " " elementstart.parentNode.id;
        beforeitem.onclick =function(){ treedialogupdate(elementstart.parentNode); };
    }
    else
    {
        beforeitem.innerHTML = "";
        beforeitem.onclick = "";
    }
}
}

(important section below) I set the on click like this

 for(i = 0; i < elementstart.children.length; i++)
    {
        listset.children[i].onclick =function(){ 
            childrenOfElement = elementstart.children;
            console.log(childrenOfElement);
            console.log(childrenOfElement[i]);
            treedialogupdate(childrenOfElement[i]); 

        };
    }

This is what i get in the console

[section#header, section.fullwidth, section#footer, header: section#header, footer:      section#footer, item: function, namedItem: function]
page-functions.js:278 undefined

What your seeing is that the elementstart.children has children but when i go to use a specific element i.e childrenOfElement[i] it becomes undefined


Solution

  • Your problem is that i is not what you think it is inside of your onclick handler. i belongs to the global scope. When the for loop that assigns the click handlers has completed, i will have a value equal to elementstart.children.length (we know this because the for loop loops until i is equal to elementstart.children.length). When your onclick handler is called, childrenOfElement[i] is equivalent to childrenOfElement[elementstart.children.length] - which is, of course, undefined.

    What you need to do is to create a new scope (which in JavaScript is a new function) for each iteration of your for loop. This scope will create a new variable which will contain the value of i at that iteration. You will then use this new variable as your index into the childrenOfElement array.

    A sexy way of achieving this is with an immediately-invoked function expression (http://benalman.com/news/2010/11/immediately-invoked-function-expression/):

    listset.children[i].onclick = (function(index) {
        return function () {
            childrenOfElement = elementstart.children;
            treedialogupdate(childrenOfElement[index]); 
        };
    }(i));