Alexander Tepe
Alexander Tepe

Reputation: 190

Javascript Array or indices undefined

I am building a web app which contains a DOM table. This is my code that should create a table from an array:

function create_table() {
    var tablediv=document.getElementById('icon-table');
    var table = document.createElement("table");
    var grid = [[15][15]];
    var template = "pixel-{1}-{2}";
    table.className = "icon-table";
    tablediv.appendChild(table);
    for (var i = 0; i < 16; i++) {
        var tr = document.createElement("tr");
        table.appendChild(tr);
        for (var j = 0; j < 16; j++) {
            var td = document.createElement("td");
            td.className = "icon-pixel";
            td.id="pixel-"+ i + "-" + j;
            td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
            grid[i][j] = td;
            td.addEventListener("click", setpixel)
            td.addEventListener("mousedown", pinselpixel)
            tr.appendChild(td);
        }
    }
}

The assignment grid[i][j] = td; fails during the first loop iteration. On the console in my browser the output says:

TypeError: undefined is not an object (evaluating 'grid[i][j] = td')

what am I missing?

Upvotes: 1

Views: 545

Answers (5)

KHACHORNCHIT
KHACHORNCHIT

Reputation: 2320

Can change to this and try it?

var grid = [[15][15]];

to

var grid = [new Array(15), new Array(15)];

Upvotes: 1

Mitya
Mitya

Reputation: 34556

There's a couple of problems here. First, you seem to be under the impression that

[[15],[15]]

will create an an array with two sub-arrays, each with 15 keys.

Instead, what that actually gives you is an array with two sub-arrays each containing one key each, with the value 15.

You probably meant this:

[new Array(15), new Array(15)]

Passing an integer to the array constructor creates the slots; passing it to an array literal simply adds that value to the array.

Even then, this approach isn't ideal. Yes, you're containing 15 (actually you presumably meant 16) slots, but they're just undefined slots right now, so this line will fail, since you can't treat undefined as an array:

grid[i][j] = td; //grid[i] == undefined, not an array

Better this (truncated for brevity):

   for (var i = 0; i < 16; i++) {
        grid[i] = []; //<-- create the row array in the loop
        var tr = document.createElement("tr");
        table.appendChild(tr);
        for (var j = 0; j < 16; j++) {
            var td = document.createElement("td");
            grid[i][j] = td; //<-- now we can append the column cell
            tr.appendChild(td);
        }
    }

Upvotes: 3

samanime
samanime

Reputation: 26527

Your grid initialization is wrong. As mentioned by some comments:

var grid = [[15][15]];

is equivalent to:

const arr = [15]; // array with one element, 15
var grid = arr[15]; // 16th element, which doesn't exist

You probably instead want:

var grid = new Array(15).fill(new Array(15));

Which will give you a two-dimensional array that is 15 "wide" and 15 "tall".

That said, you really don't need to prefill your grid unless it is a requirement for some other reason (like you are printing out a chessboard or something that always has a fixed size).

Upvotes: 1

Naren Murali
Naren Murali

Reputation: 56297

The method of intializing the two dimensional array is wrong.

Please use the below method to initialize.

var grid = new Array(15);
for (var i = 0; i < 16; i++) {
  grid[i] = new Array(15);
}

First we create the rows of the array (15 rows), then using a for loop we initialize 15 columns for each row. Then the code works fine!

function create_table() {
    var tablediv=document.getElementById('icon-table');
    var table = document.createElement("table");
    var grid = new Array(15);
    for (var i = 0; i < 16; i++) {
      grid[i] = new Array(15);
    }
    var template = "pixel-{1}-{2}";
    table.className = "icon-table";
    tablediv.appendChild(table);
    for (var i = 0; i < 16; i++) {
        var tr = document.createElement("tr");
        table.appendChild(tr);
        for (var j = 0; j < 16; j++) {
            var td = document.createElement("td");
            td.className = "icon-pixel";
            td.id="pixel-"+ i + "-" + j;
            td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
            grid[i][j] = td;
            td.addEventListener("click", function(){console.log("clicked");})
            td.addEventListener("mousedown", function(){console.log("mousedown");})
            tr.appendChild(td);
        }
    }
}
create_table();
<div id="icon-table"></div>

Upvotes: 1

messerbill
messerbill

Reputation: 5629

you are trying to loop over an array of array which has 2 elements inside. Each element is (like i said) an array, with a single entry - in your case 15.

Afterwards you are trying to iterate from 0 up to 15.

So your iterations should at first loop over grid array and afterwards over grid's elements up to their length.

but in my opinion it is not necessary to loop over an array here. just do the following:

var myGrid = []
for (var i = 0; i < 16; i++) {
  for var k = 0; k < 16; k++) {
    //do your stuff
    myGrid[i][k] = td
  }
}

this should work

Upvotes: 3

Related Questions