0

I have a table:

<div ID="documents_list" style="visibility: hidden;">
    <table style="background-color:#000000;border:0;border-collapse:separate;border-spacing:0px;">
        <tr>
            <td style="padding:0px;">
                <table id="documentsTable" style="border:0;border-collapse:separate;border-spacing:1px;">
                    <tr bgcolor='#ffffff'>
                        <td bgcolor='#cccccc' style="padding:2px;" nowrap>Catalog:</td>
                        <td style="padding:2px;" colspan=3></td>
                    </tr>
                    <tr bgcolor='#ffffff'>
                        <td bgcolor='#cccccc' style="padding:2px;" nowrap>Doc.nr.</td>
                        <td bgcolor='#cccccc' style="padding:2px;" nowrap>Document name</td>
                        <td bgcolor='#cccccc' style="padding:2px;" nowrap></td>
                        <td bgcolor='#cccccc' style="padding:2px;" nowrap></td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    <input type="button" value="Close" onClick="hide_documents_list()">
</div>

And I'm trying to access it from Javascript, so I could change it's content and add rows to it. The method for it is following:

function show_documents(documents) {
    var table = document.getElementById("documentsTable");
    for (var i=0; i<documents.length; i++) {
        var row = table.insertRow(-1);

        var document = row.insertCell(0);
        var name = row.insertCell(1);
        var button = row.insertCell(2);
        var checkbox = row.insertCell(3);

        document.innerHTML = documents[i].document;
        name.innerHTML = "<a href='${pageContext.request.contextPath}/s?id=" + documents[i].document + "'>" + documents[i].name + "</a>";
        button.innerHTML = "<input type='button' value='Delete'>";
        name.innerHTML = "<input type='checkbox'>";
    }
    show_documents_list();
}

But whenever I try to call this method, I get the following error Uncaught TypeError: Cannot read property 'getElementById' of undefined. The thing is, the element is defined in HTML, so I can't really figure out where the problem is.

2
  • 1
    looks like you have defined the document as local variable in your function, rename it to something else in document = row.insertCell(0); Commented May 23, 2015 at 10:04
  • I renamed the document variables in Javascript and seems that it fixed the problem. Thanks! Commented May 23, 2015 at 10:08

3 Answers 3

1

Yes like Tero Tolonen says. Because of hoisting Javascript pulls all variable declarations to the top at execution.

This means code execution wise you would get something like:

// because of hoisting variable decalarations get pulled to the top of the scope
var document;

after which you try to access the method getElementByID on your declared variable.

Thus resulting in a type error.

Sign up to request clarification or add additional context in comments.

Comments

1

document in the browser is a global object always available. You must not use a variable on your own which you give this name.

Comments

0

In JavaScript there is a Hoisting behavior, such that all variable declarations (either regular objects or functions, note that functions in JavaScript are also of type object) will be moved to the top of their function scope.

Note that initializations will NOT hoisted to the top.

For example, consider this one:

function(){
    alert("hi there!");
    var x = 5; // Declaration and initialization
    alert(x);
}

This example after that hoisting is applied will look like this:

function(){
    var x; // Declaration is hoisted but not for initialization
    alert("hi there!");
    x = 5; // Initialization is still here.
    alert(x);
}

In your case we would have something like this after that hoisting is applied.

function show_documents(documents) {
    var table;
    var row;
    var document; // This variable is now of type Unknown
    var name;
    var button;
    var checkbox;

    table = document.getElementById("documentsTable");
    //         ^--- Unknown, But 'window.document' does work.
    for (var i=0; i<documents.length; i++) {
        row = table.insertRow(-1);

        document = row.insertCell(0); // Initialization is here!
        name = row.insertCell(1);
        button = row.insertCell(2);
        checkbox = row.insertCell(3);

        document.innerHTML = documents[i].document;
        name.innerHTML = "<a href='${pageContext.request.contextPath}/s?id=" + documents[i].document + "'>" + documents[i].name + "</a>";
        button.innerHTML = "<input type='button' value='Delete'>";
        name.innerHTML = "<input type='checkbox'>";
    }
    show_documents_list();
}

There is another important point that, I think you should know. In JavaScript when you declare an variable with same name as another global variable (or variable that has been declared in the parent function scope) and use it, JavaScript always take the most localized one.

For example:

var x = 5;
function (){
    var x = 4; // same name
    alert(x); // result would be 4 not 5
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.