Abhay Bhave
Abhay Bhave

Reputation: 45

JavaScript DOM insertBefore isn't working properly

It's my first question here, so pardon me for my mistakes if any.

I am trying to add rows to a table through JavaScript. The newly added row is to be added at the second-last position, the last row contains the button that creates new row. The last row has id "submitrow", but getting that element and passing it to insertBefore is somehow not working. passing lastChild as 2nd param to insertBefore also behaves odd.

In the body, this is the form:

<form>
    <input type="hidden" name="submit_done" value="true" />
    <table id="formtable">
        <tr>
            <td>Number : </td>
            <td><input type="text" name="num[]" /></td>
        </tr>
        <tr id="submitrow">
            <td><input type="button" value="Add one more" onclick="addRow()" /></td>
            <td><input type="submit" value="Go!" /></td>
        </tr>
    </table>
</form>

Here is JavaScript function:

function addRow(){
    var new_tr  = document.createElement('tr');
    var new_td1     = document.createElement('td');
    var new_td2     = document.createElement('td');
    var new_input   = document.createElement('input');

    new_td1.innerHTML = 'Number : ';

    new_input.type = 'text';
    new_input.name = 'num[]';
    new_td2.appendChild(new_input);

    new_tr.appendChild(new_td2);
    new_tr.insertBefore(new_td1, new_td2);

    var formtable   = document.getElementById('formtable');
    var submitrow   = document.getElementById('submitrow');
    submitrow.style.backgroundColor='red'; /*Works fine, paints button row red*/
    formtable.insertBefore(new_tr, submitrow); /*fails, invalid argument*/
}

Now, the problem is:

  1. insertBefore fails on last line. Please note, that insertBefore has been tried on new_tr object as wel, and it works fine. So the only possibe invalid argument can be submitRow, shich is painted red successfully just one line above the failing statement.

  2. If for the failing call, instead of submitrow, if formtable.lastChild is used, it runs. But then somehow that lastChild includes upper row too. That means, if I put say 4 more rows and enter 1, 2, 3, 4, 5 in the test inputs, and then if you hit "Add one more" button, now a row is added between 4 and 5!

I have tried a lot to reason it, but could get no logic behind either of the situation.

In hope of a solution, thanking you all,

Abhay Bhave, India

Upvotes: 2

Views: 4275

Answers (1)

MaxArt
MaxArt

Reputation: 22617

The title should be changed in "JavaScript DOM insertBefore isn't used properly".

That's because, even if you didn't put in your DOM, the browser automatically creates a <tbody> element that wraps the rows of the table. So, it happens that #formtable is not the parent of #submitrow, and that's why you get an error.

Try this:

formtable.tBodies[0].insertBefore(new_tr, submitrow);

Or, more generally:

submitrow.parentNode.insertBefore(new_tr, submitrow);

(In browsers that support it, there's even this one:

submitrow.insertAdjacentElement("beforeBegin", new_tr);

Internet Explorer, Chrome, Safari and Opera support it, Firefox doesn't but it can be easily shimmed. I don't recommend using this stuff, anyway.)

And, as a general advice, always use the <tbody> tag when writing down tables:

<table id="formtable">
    <tbody>
        <tr>
            <td>Number : </td>
            <td><input type="text" name="num[]" /></td>
        </tr>
        <tr id="submitrow">
            <td><input type="button" value="Add one more" onclick="addRow()" /></td>
            <td><input type="submit" value="Go!" /></td>
        </tr>
    </tbody>
</table>

And, of course, <thead> and <tfoot> when you need them.

Upvotes: 6

Related Questions