appendChild in for loop only adds 1 child
Asked Answered
L

3

18

In JavaScript I am creating a grid (the type of grid you see in Photoshop) with HTML tables. The grid size is going to be variable, i.e., changeable by the user, so the size of each grid square must be calculated and divided by the number of pixels available to get an exact size grid.

I've done all this, but I have a problem adding in the necessary table elements to create the grid. My code is in full working order, except when I use the appendChild() function inside a for loop it only ever appends a single child, when it should be appending up to a couple of hundred.

My code:

grid.show = function(event)
{
    var e = event;

    if(grid.show_grid == false)
    {
        grid.show_grid = true;

        parent.document.getElementById("grid_table").style.display = "block";

        // Get grid (table) and create some elements.
        grid.get_grid = parent.document.getElementById("grid_table");
        grid.tr       = parent.document.createElement("tr");
        grid.td       = parent.document.createElement("td");

        // Clear the grid of all squares so we don't have to worry about subtracting anything.
        grid.get_grid.innerHTML = "";

        // Calculate the number of horizontal and vertical squares.
        var horizontal = Math.ceil(grid.total_width / grid.size);
        var vertical   = Math.ceil(grid.total_height / grid.size);

        // This was a nested loop, removed for demonstration.
        // Attempting to add 10 "<tr><td></td></tr>" to the table.
        for(var j = 0; j < 10; j++)
        {
            grid.tr.appendChild(grid.td);
        }

        //console.log(grid.tr);

        // Add the elements to the table.
        grid.get_grid.appendChild(grid.tr);

    }
    else
    {   
        grid.show_grid = false;
        parent.document.getElementById("grid_table").style.display = "none";
    }
}

This only ever returns a single table row with single table data inside, like so:

<tr>
    <td></td>
</tr>

I've already looked at this page and this page, and they sound promising but I just can't figure out how to make this work.

EDIT: Code now working, solution:

grid.show = function(event)
{
    var e = event;

    if(grid.show_grid == false)
    {
        grid.show_grid = true;

        parent.document.getElementById("grid_table").style.display = "block";

        grid.get_grid           = parent.document.getElementById("grid_table");
        grid.tr                 = null;
        grid.td                 = null;
        grid.get_grid.innerHTML = "";

        var horizontal = Math.ceil(grid.total_width / grid.size);
        var vertical   = Math.ceil(grid.total_height / grid.size);

        for(var i = 0; i < vertical; i++)
        {
            grid.tr = parent.document.createElement("tr");

            for(var j = 0; j < horizontal; j++)
            {
                grid.td = parent.document.createElement("td");

                grid.td.width = grid.size;
                grid.td.height = grid.size;

                grid.tr.appendChild(grid.td);
            }
            grid.get_grid.appendChild(grid.tr);
        }
    }
    else
    {   
        grid.show_grid = false;
        parent.document.getElementById("grid_table").style.display = "none";
    }
}
Lamia answered 4/10, 2012 at 15:38 Comment(0)
I
32

You are appending the same element over and over. You need to call document.createElement each time you wish to have a new element.

EDIT: If the element setup is really complicated and potentially includes children then you can also use Node.cloneNode

Iggie answered 4/10, 2012 at 15:40 Comment(1)
Thank you, this was the problem. Code now working as expected (solution in OP).Lamia
S
15

If you want to make one copy of the element, you will need to clone it. Use cloneNode()

So change

grid.tr.appendChild(grid.td);

to

grid.tr.appendChild(grid.td.cloneNode(true));
Stimulative answered 4/10, 2012 at 15:42 Comment(0)
S
5
for(var j = 0; j < 10; j++)
{
        grid.tr.appendChild(grid.td);
}

should be

for(var j = 0; j < 10; j++) {
    var newTd = parent.document.createElement('td');
    grid.tds.push(newTd); // if you need it, not sure why though
    grid.tr.appendChild(newTd);
}
Strangle answered 4/10, 2012 at 15:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.