1

Keep on getting the Cannot read property 'length' of undefined error"" with: (still a work in progress) It is only meant to add an image to the div as a kind of place holder.

var board=document.getElementsByClassName("square");
var blank = "<img src = blank.png alt= blank class = blank></img>";
for(var x in board){
  document.board[x].innerHTML(blank)
}

This is still a work in progress I do however require the board to test is

<!DOCTYPE HTML>
<html>
  <head>
    <title>Play four-in-a-Row</title>
    <meta charset=ütf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="styles.css">
  </head>
  <div class="container-fluid">
    <body onload="boardSetup()">
      <div id="header" >
        <h1 id = "Main">Four-in-a-Row</h1>
      </div>
      <hr>
      <table  border="1" id = "drop">
        <tr>
          <td data-toggle="tooltip" title = "Column 1"></td>
          <td data-toggle="tooltip" title = "Column 2"></td>
          <td data-toggle="tooltip" title = "Column 3"></td>
          <td data-toggle="tooltip" title = "Column 4"></td>
          <td data-toggle="tooltip" title = "Column 5"></td>
          <td data-toggle="tooltip" title = "Column 6"></td>
          <td data-toggle="tooltip" title = "Column 7"></td>
        </tr>
      </table>
      <hr>
      <div id="board" >
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
        <div class="row">
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure col-xs-1" ></div>
          <div class = "sqaure " ></div>
        </div>
      </div>
      <div  class= "piece">
        <img src= "player_1.png" alt= "Player 1 piece" height = 15% width = 15% id = "player1" data-toggle="tooltip" title = "Player one's piece"class ="player1 piece"></img>
        <img src= "player_2.png" alt= "Player 2 piece" height = 15% width = 15% data-toggle="tooltip" title = "Player two's piece" class = "player2 piece"></img>           
      </div>
      <script>
        var map;
        function boardSetup(){
          var board=document.getElementsByClassName("square");
          var blank = "<img src = blank.png alt= blank class = blank></img>";
          for(var x in board){
            document.board[x].innerHTML(blank)
          }

          document.getElementById("board").innerHTML=board;
          var temp2 = document.getElementsByClassName("blank");

          for(var z in temp2){
            temp2[z].className += " piece";
          }
        }

        function gameStart(){}

        $(document).ready(function(){
          $('[data-toggle="tooltip"]').tooltip();               
        });

        function draggover(ev){

        }

        function drag(ev){

        }
      </script>
      <input type="button" onclick="boardSetup()" value="Reset" class="btn btn-danger btn-block" ></input>
    </div>
  </body>
  <footer>
    <hr>
    <a href="../index.html">&lt;- Back to launch page</a>
    <hr>
    <p style= "text-align: right"> done by <br>Justin Michel <br> u14369852</p>
    <hr>
  </footer>
</html>
Sachin PATIL
  • 745
  • 1
  • 9
  • 16
Justin Michel
  • 123
  • 2
  • 14
  • What line of your code is throwing that error? Also, `` elements don't have a closing tag. – Scott Marcus Mar 10 '17 at 15:28
  • 1
    you seem to have a typo in sqaure `
    `
    – J O Mar 10 '17 at 15:28
  • 1
    Don't use `for...in...` to iterate over the elements of an array-like collection. [Why is using “for…in” with array iteration a bad idea?](https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea) – Andreas Mar 10 '17 at 15:29
  • 1
    `var blank = "blank";` Add quotes to HTML attribute values! -- `document.board[x].innerHTML(blank);` You set this with an equal sign; it's a variable, not a method. – Feathercrown Mar 10 '17 at 15:30
  • @Feathercrown HTML attribute values only need quotes around them if the value contains a space. – Scott Marcus Mar 10 '17 at 15:31
  • @ScottMarcus Huh, TIL. It's still a good idea to get in the habit of doing it, though. – Feathercrown Mar 10 '17 at 15:33
  • @Feathercrown Yes, but that is not related to the error and it is incorrect to say that you must use them. – Scott Marcus Mar 10 '17 at 15:36
  • @ScottMarcus It's still something that should be "fixed," though. However, since it isn't actually the problem, it belongs in a comment, not in an answer. – Feathercrown Mar 10 '17 at 15:46
  • @Feathercrown It's not broken. It's perfectly valid and therefore it's not relevant. – Scott Marcus Mar 10 '17 at 15:47

1 Answers1

1

Your problem is that you are using a for/in loop to loop over a node list (the set of DOM elements returned from your .getElementsByClassName() call), which is an array-like object. When you do that, you aren't iterating the elements within the collection, you are iterating the properties of the node list object itself.

You should be using a counting loop to iterate the node list or a .forEach loop on the node list that has been converted to an Array.

You also shouldn't qualify the DOM element you are looping over with document as the variable board[x] is a direct reference to the element.

Additionally, innerHTML is a property, not a method. You set it equal to the value you want to use, you don't pass it into it.

Lastly, HTML <img> elements do not get closed (</img>). They are elements that are not allowed to have "content", like: <br>, <meta>, <link>, <hr> and <base>.

Here's a simple counting loop that will iterate the elements returned:

    var board=document.getElementsByClassName("square");
    var blank = "<img src='blank.png' alt='blank' class ='blank'>";
    for(var x = 0; x < board.length; ++x){
        board[x].innerHTML = blank;
    }

And, JavaScript Arrays support a native .forEach() method that allows the elements to be iterated. A node list isn't an actual array, so it doesn't implement that method natively, but it is an "array like" object and can be converted to one using the Array.slice() method. That would look like this:

var board = document.getElementsByClassName("square");
var blank = "<img src='blank.png' alt='blank' class ='blank'>";

// Call the native slice array method (which returns an array)
// and then call forEach on that array:
Array.prototype.slice.call(board).forEach(function(element){
  element.innerHTML = blank;
});
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • `.forEach()` will only work after converting the `HTMLCollection`/`NodeList` into an actual array. – Andreas Mar 10 '17 at 15:35
  • My bad on the QSA reference. And yes, you are right about the use of `.forEach`, but I didn't say it could be used directly on the nodelist. I just said that it could be used. – Scott Marcus Mar 10 '17 at 15:37