views:

54

answers:

3

Funny thing is that if i delete the comment for alert(data[i].id) the code works. As it is in the example, the string is not concatenated thus i have no options in the select box. Hints? Help?

Re-edited so that you guys can see the whole method

function socialbookmarksTableData(data)
{
    var toAppend = '';
    var bookmarkingSites = '';

    $.getJSON("php/socialbookmark-get-bookmarking-sites.php",function(data){

        for(var i = 0; i < data.length; i++){
            //alert( data[i].id);
            bookmarkingSites += '<option value = "' + data[i].id + '">' + data[i].title + '</option>';
        }
    });

    $.each(data.results, function(i, id){

        if(i%2 == 1)
            toAppend += '<tr class="first">';
        else
            toAppend += '<tr class="second">';
        if(data.results[i].status == "PENDING" || data.results[i].status == "POSTED")
            toAppend += '<td><span class="approved">' + data.results[i].status + '</span></td>';
        else
            toAppend += '<td>' + data.results[i].status + '</td>';
        toAppend += '<td><select name="sb2" id="sb2">'+
        '<option value="'+ data.results[i].bookmark +'">' + data.results[i].bookmark +'</option>' +
        bookmarkingSites + '</select></td>';
        toAppend += '<td>' + data.results[i].user + '</td>';
        toAppend += '<td>' + data.results[i].link + '</td>';
        toAppend += '<td>Some Article</td>';
        toAppend += '<td>' + data.results[i].title + '</td>';
        toAppend += '<td>' + data.results[i].description + '</td>';
        toAppend += '<td>' + data.results[i].tags + '</td>';
        toAppend += '<td>' + data.results[i].date + '</td>';
        toAppend += '<td><div class="actions">';
        toAppend += '<ul><li><input class="radio" name="input" type="checkbox" value="' + data.results[i].id + '" /></li>';
        toAppend += '<li><a class="action1" href="#">1</a></li>';
        toAppend += '<li><a class="action4" href="#">4</a></li></ul></div></td></tr>';
    });
    $("#searchTable tbody").append(toAppend);
}
A: 

What you've got is a classic race condition. The getJSON code is making an asynchronous call. When you have the alert in there the code below the getJSON call is executed before the call returns from the callback. Without the alert, it's being executed after the callback. This is actually a lucky occurence as you can't be guaranteed that it will happen that way. You should put all the code that relies on the data returned from the getJSON call into the callback so you can guarantee that the data is returned before using it.

var bookmarkingSites = ''; 

$.getJSON("php/socialbookmark-get-bookmarking-sites.php",function(data){ 

    for(var i = 0; i < data.length; i++){ 
        //alert( data[i].id); 
        bookmarkingSites += '<option value = "'
                            + data[i].id + '">'
                            + data[i].title + '</option>'; 
    } 
    <some more code> 
    toAppend += '<td><select name="sb2" id="sb2">'
                 + '<option value="'+ data.results[i].bookmark +'">'
                 + data.results[i].bookmark +'</option>'
                 +  bookmarkingSites + '</select></td>'; 
    <some more code>
}); // end of JSON call/callback
tvanfosson
+2  A: 

One is reason: When you enclose strings in single quotes, you don't have to escape the double quotes (the backslash does not work as escape operate here anyway I think). So this:

bookmarkingSites += '<option value = \"' + data[i].id + '\">' + data[i].title + '</option>';

Should be:

bookmarkingSites += '<option value="' + data[i].id + '">' + data[i].title + '</option>';

The other reason: your code between <some more code> is not in the callback function, but you try o access data from the function (data and bookmarkingSites). Put all the HTML generation code inside the callback function.


Ah so it is an other data ;) Anyway you cannot access bookmarkingSites in your code because it does not yet exists when the code is executed. Try this:

function socialbookmarksTableData(data)
{

    $.getJSON("php/socialbookmark-get-bookmarking-sites.php",function(bookmarks){

        var toAppend = '';
        var bookmarkingSites = '';

        for(var i = 0; i < bookmarks.length; i++){
            //alert( bookmarks[i].id);
            bookmarkingSites += '<option value = "' + bookmarks[i].id + '">' + bookmarks[i].title + '</option>';
        }

        $.each(data.results, function(i, id){

            if(i%2 == 1)
                toAppend += '<tr class="first">';
            else
                toAppend += '<tr class="second">';
            if(data.results[i].status == "PENDING" || data.results[i].status == "POSTED")
                toAppend += '<td><span class="approved">' + data.results[i].status + '</span></td>';
            else
                toAppend += '<td>' + data.results[i].status + '</td>';
            toAppend += '<td><select name="sb2" id="sb2">'+
            '<option value="'+ data.results[i].bookmark +'">' + data.results[i].bookmark +'</option>' +
            bookmarkingSites + '</select></td>';
            toAppend += '<td>' + data.results[i].user + '</td>';
            toAppend += '<td>' + data.results[i].link + '</td>';
            toAppend += '<td>Some Article</td>';
            toAppend += '<td>' + data.results[i].title + '</td>';
            toAppend += '<td>' + data.results[i].description + '</td>';
            toAppend += '<td>' + data.results[i].tags + '</td>';
            toAppend += '<td>' + data.results[i].date + '</td>';
            toAppend += '<td><div class="actions">';
            toAppend += '<ul><li><input class="radio" name="input" type="checkbox" value="' + data.results[i].id + '" /></li>';
            toAppend += '<li><a class="action1" href="#">1</a></li>';
            toAppend += '<li><a class="action4" href="#">4</a></li></ul></div></td></tr>';
        });
        $("#searchTable tbody").append(toAppend);
    });
}
Felix Kling
thanks, works like a charm now.
As well as surrounding quotes you need HTML-escaping everywhere you put text into a string of HTML. The code as it standards is full of potential cross-site-scripting (XSS) security holes for this reason. It is often easier write the contents of `<td>`​s and attributes using called like `text()` and `attr()`/`val()` rather than constructing templated HTML strings.
bobince
A: 

From the code provided it looks like you do the JSON call and the callback function appends to the bookmarkingSites variable. so far so good.

The code that the arrow points to is outside the callback function and will run before the JSON callback is called, therefore bookmarkingSite will be empty string and there will be no options in the select box.

Wouldn't the code to build the option tag also go in the callback or be in a function called by the callback?

daddyman