Javascript DOM errors

this is my javascript code , I am trying to create a dynamic list in HTML with data I recieve from the server , The data is of type "json"

My Javascript snippet

function addBooks(data) { // USing DOM to populate the tables 


    //var  newdata=document.getElementById('addBooks');
    //newdata.setattribute()

    //get the unordered list

    var newdata = document.getElementById('addBooks');
    var parent = document.getElementById('gBookList');
    //removeChildrenFromNode(parent);

    //create list divider
    var listdiv = document.createElement('li');
    listdiv.setAttribute('id', 'gBookListDiv');
    listdiv.innerHTML = ("Books Found:");
    parent.appendChild(listdiv);
    // (this is where the first error happens)

    //create dynamic list

    for (i = 0; i < data.length; i++) {
        // (this is where the second error happens)



        //create each list item 
        var listItem = document.createElement('li');
        listItem.setAttribute('id', 'gBookListItem');
        parent.appendChild(listItem);
        //var link = document.createElement('a');
        //link.setAttribute('onclick','displayBook(data[i])');
        //link.setAttribute('href','#FindBook)');
        //listItem.appendChild(link);
        var pic = document.createElement('img');
        pic.setAttribute('src', data[i].pictureURL);
        pic.setAttribute('width', '80px');
        pic.setAttribute('height', '100px');
        pic.setAttribute('style', 'padding-left: 10px');
        link.appendChild(pic);
        var brk = document.createElement('br')
        link.appendChild(brk);
        var title = document.createElement('p');
        title.innerHTML = data[i].title;
        title.setAttribute = ('style', 'float:right');
        link.appendChild(title);
        var author = document.createElement('p');
        author.innerHTML = data[i].author;
        link.appendChild(author);
    }
    var list = document.getElementById('gBookList');
    // $(list).listview("refresh");
}

/*function removeChildrenFromNode(node){
            while (node.hasChildNodes()){
                node.removeChild(node.firstChild);
            }
        //}*/

My html code is

<!DOCTYPE html>

<head>
   <script ...> 
 <head>                  
<body onLoad="addBooks()">
    <div id="addBooks" class="row-fluid">
        <div id="gBookList">
        </div>
    </div>
</body>
</html>

I keep getting the following error which prevents me from populating the list , I am using chrome

1) Uncaught TypeError: Cannot call method 'appendChild' of null
2) Uncaught TypeError: Cannot read property 'length' of undefined

I do not understand why this should happen as the .length commands returns the correct integer ( amount of json objects) when I debug using a alert box .

the function that calls it

$.ajax({
    type: 'GET',
    url: ........,
    dataType: "json",
    complete: function (xhr, statusText) {
        alert(xhr.status);
    },
    success: function (data, textStatus, jqXHR) {
        alert(JSON.stringify(data));
        window.location.replace("Page2_updated.html");
        addBooks(data); // Passing JSON to be replaced on page
    },

    function (data, textStatus, jqXHR) {
        alert(data);
        alert('error');
    },

});

Edit

I changed my HTML file to the following structure after advice on this forum

<html>
<head>
</head>
<body>
<div id="1" "display:block">
</div>
<div id="2" "display:none">  // no onLoad() anymore!!
</div>
</body>
</html>

I have edited this part int he calling function

 $.ajax({
        type: 'GET',
        url: ........,
        dataType: "json",
        complete: function (xhr, statusText) {
            alert(xhr.status);
        },
        success: function (data, textStatus, jqXHR) {
            alert(JSON.stringify(data));
            if(document.getElementById(1).style.display == "block"){ 
                document.getElementById(1).style.display = "none"; 
                document.getElementById(2).style.display = "block"; }
            addBooks(data); // Passing JSON to be replaced on page
        },

        function (data, textStatus, jqXHR) {
            alert(data);
            alert('error');
        },
    });

But I still get the following errors Uncaught TypeError: Cannot call method 'appendChild' of null Uncaught TypeError: Cannot read property 'length' of undefined

Answers:

Answer

Here is a working version of your code that builds a list. Compare with your version to see where you made the mistakes, in both mark up and code.

The source of your second error is incorrect data (most likely null) being passed to the addBooks function, so you would have to fix that.

Chrome and Firebug have excellent JavaScript debuggers with breakpoints, so use that to your advantage to identify the issues:

http://jsfiddle.net/tgth2/

EDIT:

Your problem is gleamingly obvious, after your comments and updates to the question:

  1. Your first page is loading the JSON data from the service, but then does window.location.replace("Page2 Updated.html");, which sends the browser to the new page (notice that you're calling addBooks(data); immediately after. But that code is never executed because browser has already gone to another page
  2. Your second page has <body onload="addBooks();"> in it, which will cause the function to be called with a null data. This is the cause of your problem.

SOLUTION:

Number one suggestion would be to start using jQuery for everything else you're doing, and not just for the AJAX call.

Secondly, you should have the ajax call and the results rendering in one page, as it does not make any sense to redirect the browser to another page. Because your javascript always works in the context of a single page. As soon as you do something like window.location.replace(..) you end up losing everything you've done in the current page.

If you make these changes, you will see that your list loads just fine!

Answer

This line in your loop creates multiple list items with the same ID:

listItem.setAttribute('id','gBookListItem');

try removing it - i don't think you need it.

Answer

That's an error :

title.setAttribute=('style','float:right');

do:

var title = document.createElement('p');
    title.innerHTML = data[i].title;
    title.style.cssFloat = 'right';
link.appendChild(title);

and

var pic = document.createElement('img');
    pic.src = data[i].pictureURL;
    pic.width = '80px';
    pic.height = '100px';
    pic.style.paddingLeft = '10px';
link.appendChild(pic);

etc......

Answer

Any chance that you're accidentally calling addBooks() somewhere in your code without any data?

Answer

I tried to cut it down to the barebones and I'm pretty sure the fact that link is undefined is the reason you get an error when you call appendChild. It's certainly the first error I found in the console in Firebug. The following barebones sequence works in Firefox (sorry I don't have Chrome):

    var json =[
        {"pictureURL":"/test1.jpg/","title":"test1"},
        {"pictureURL":"/test2.jpg/", "title":"test2"},
        {"pictureURL":"/test3.jpg", "title":"test3"}
    ];
    function displayBook(title){
        alert(title);
        return false;
    }
    function addBooks(data) {
        var  newdata=document.getElementById('addBooks');
        var parent = document.getElementById('gBookList');
        var listdiv = document.createElement('li');
        listdiv.id = 'gBookListDiv';
        listdiv.innerHTML = "Books Found:";
        parent.appendChild(listdiv);
        for(var i=0;i<data.length;i++){
            var listItem = document.createElement('li');
            listItem.id = 'gBookListItem-' + i;
            parent.appendChild(listItem);
            var link = document.createElement('a');
            link.id = listItem.id + "-link";
            link.href = '#FindBook';
            link.innerHTML = data[i].title;
            listItem.appendChild(link);
            link.setAttribute("onclick", "return displayBook('" + data[i].title + "');");
            var pic = document.createElement('img');
            pic.src = data[i].pictureURL;
        }
        var list = document.getElementById('gBookList');
    }

I discovered from this answer JavaScript: changing the value of onclick with or without jQuery that I had to use setAttribute to add the onclick handler. I'm used to adding other attributes like id directly as mentioned by adeneo without calling setAttribute.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.