Undefined when passing DOM object in Javascript

2.4k views Asked by At

I am (attempting) to have a table which can switch the background color based on an RGB value, where each row of the table has clickable <td>s, and they will add up to give and RGB value (eg. first row is +/- 123, second row is +/- 123.

#2: The issue I'm running into currently is that when I attempt to pass my DOM object from my listener-creating for loop to the switch_JS' function, the DOM that is being passed indomobj` is undefined.

I would then like to switch the value of the hidden inputs inside of the <td>s each time the user clicks, and define a separate function (probably not in the JS) to add them up and render a rgb color based on that.

As I said, the real issue is above as #2, but any other help would be greatly appreciated. I am very new to programming in general, and this is mainly for my own learning.

<script>

var JS_elements = document.getElementsByClassName("JS")

for (y = 0; y < JS_elements.length; y++){
x = JS_elements[y].getElementsByTagName("input")[0]
alert(String(x.value)) **this loop runs 3 times, and puts 'false' to the alert pop-up each time

JS_elements[y].addEventListener('click', function() {
    switch_JS(JS_elements[y].getElementsByTagName("input")[0]);
});

function testfunc() {
    alert("TestFunc");
}

function true_switch(val) {
    document.getElementById("testblock").innerHTML += "true_switch worked; "; <!-- debug line -->
    if (val == true) {
        return false;
    } else if (val == false) {
        return true;
    } else {
        alert("Error #475989 in function true_switch");
    }
}

function switch_JS(domobj) {
    <!-- takes as input an HTML object, and switched the value from true to false, or from false to true -->
    document.getElementById("testblock").innerHTML = document.getElementById("testblock").innerHTML + "Step 1 worked; "; <!-- debug line -->
    alert(String(domobj)); <!-- debug line -->
    val = domobj.querySelector("input").value;
    document.getElementById("testblock").innerHTML += "Step 2 worked; "; <!-- debug line -->
    if ((typeof val) != Boolean) {
        alert("Error, non-boolean passed into switch_JS");
        document.getElementById("testblock").innerHTML += "1st if worked; ";
    } else {
        domobj.querySelector("input").value = true_switch(HTML.value);
        document.getElementById("testblock").innerHTML += "else worked; "; <!-- debug line -->
    }
}
</script>

HTML:

<body>
    <div id="testblock">Testblock: </div>
    <header>
        <hr>
            <p>- Header Background Color Controller -</p>
            <table>
                <tr>
                    <td>Javascript Controller:</td>
                    <td class="JS">Red
                        <input type="hidden" value='false'>
                    </td>
                    <td class="JS">Green
                        <input type="hidden" value='false'>
                    </td>
                    <td class="JS">Blue
                        <input type="hidden" value='false'>
                    </td>
                </tr>
                <tr>
                    <td>jQuery Controller:</td>
                    <td class="jQ" value=false>Red</td>
                    <td class="jQ" value=false>Green</td>
                    <td class="jQ" value=false>Blue</td>
                <tr>
            </table>
        <hr>
    </header>
    <div class="main_div">

</div>
2

There are 2 answers

0
mplungjan On BEST ANSWER
  1. Closure - use this instead of the array element
  2. use an onload function
  3. domObj is a node list so this will not work either: val = domobj.querySelector("input").value;

FIDDLE

window.onload=function() {
  var JS_elements = document.getElementsByClassName("JS")

  // why not use document.querySelectorAll(".JS");

  for (y = 0; y < JS_elements.length; y++){
    JS_elements[y].addEventListener('click', function() {
        switch_JS(this); // do not use [y] here
    });
  }
}

and then this will work when you pass in (this)

val = domobj.querySelector("input").value;

Update for 2020

window.addEventListener("load",function() {
  [...document.querySelectorAll(".JS")].forEach(function() {
    this.addEventListener('click', function() {
        switch_JS(this); 
    });
  })
})

but I suggest you delegate to the nearest static container

2
Keval Bhatt On

As you can see in example i printed 2 console one for your input and one for your i

So your problem is:

when in listener function you are trying to access JS_elements[y].childNodes so at that time your Y is 4 and your Class Js array length is 0-3 and because of for loop Y will be incremented to 4 so you got undefined because JS_elements[4] is not present in your array.

so use this.chiledNode in

see this one type of solution :

Working example:http://jsfiddle.net/kevalbhatt18/gqce9htx/

var input = document.querySelectorAll('input');
  console.log(input)
   for(var i=0;i<input.length;i++){
      input[i].addEventListener('input', function()
      {  
         console.log(input)
         console.log(i)
         console.log('input changed to: ', this.value);
      });

 }