0

This sample code should dump a list of all bookmarks. It shows nothing in the alert but populates the list on close correctly. Without the alert, it doesn't build the list. Since chrome api functions are all asynchronous is there a "legit" way to solve this type of problem other than a timeout?

<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.js"></script>
<body>
<script>
$(document).ready(function() {

var bookmarksList ='';

chrome.bookmarks.getTree(function(bookmarks) {
    traverseBookmarks(bookmarks);
});

function traverseBookmarks(bookmarkTreeNodes) {
for(var i=0;i<bookmarkTreeNodes.length;i++) {
    if(bookmarkTreeNodes[i].url) {
        bookmarksList += '<li>Name: ' + bookmarkTreeNodes[i].title + ' ID: ' + bookmarkTreeNodes[i].id + ' URL: ' + bookmarkTreeNodes[i].url + ' Parent ID: ' + bookmarkTreeNodes[i].parentId;
        }

    if(bookmarkTreeNodes[i].children) {
        traverseBookmarks(bookmarkTreeNodes[i].children);
    } 

}
}
alert(bookmarksList);
$('#list').html(bookmarksList);
});
</script>
<ul id="list"></ul>
</body>
</html>
Korak
  • 231
  • 4
  • 11
  • @Francesco and @Matt - Thanks for the quick responses and help! Moving the request worked on it's own and I learned a lot from your example code. – Korak Apr 20 '11 at 01:43

3 Answers3

3

I'm not familiar with the Chrome extension API, but I'd hazard a guess that this is what you're looking for:

$(function() {

    function traverseBookmarks(nodes) {

        var toReturn = [],
            numNodes = nodes.length,
            node;

        for (var i = 0; i < numNodes; i++) {
            node = nodes[i];
            if (node.url) {
                toReturn.push('<li>Name: ' + node.title + ' ID: ' + node.id + ' URL: ' + node.url + ' Parent ID: ' + node.parentId + '</li>');
            }

            if (node.children) toReturn.push(traverseBookmarks(node.children));
        }

        return toReturn.join('');
    }

    chrome.bookmarks.getTree(function(bookmarks) {
        var bookmarksList = traverseBookmarks(bookmarks);
        alert(bookmarksList);
        $('#list').html(bookmarksList);
    });
});

Notes:

  • The rewritten version uses straightforward recursion, rather than using a (more-or-less) global variable.
  • I added a </li> tag, which I think you missed.
  • I used a "StringBuilder" approach rather than string concatenation, for better performance.
Community
  • 1
  • 1
Matt Ball
  • 332,322
  • 92
  • 617
  • 683
  • 1
    +1, chrome.bookmarks.getTree is an asyncronous function, you have to put your list populating code into the callback. – DarthJDG Apr 19 '11 at 21:14
1

Ok, if we are about refactoring and we are in Chrome it can be used the native Array.prototype.forEach function and a named anonymous function for a more compact and clear code... :P

$(function(){

    chrome.bookmarks.getTree(function(bookmarks) {
        var bookmarksList = [];
        bookmarks.forEach(function me (node) {
            if (node.url) {
                bookmarksList.push('<li>Name: ' + node.title + ' ID: ' + node.id + ' URL: ' + node.url + ' Parent ID: ' + node.parentId + '</li>');
            }

            if (node.children) {
                me(node.children);
            }

        });
        $('#list').html(bookmarksList.join(''));
    });
});
Francesco Terenzani
  • 1,341
  • 7
  • 14
  • +1, that's a good point about using `forEach`. I'm not very good at taking advantage of browser-specific functionality when I know I don't have to worry about IE. – Matt Ball Apr 19 '11 at 21:22
0

I suppose you can move $('#list').html(bookmarksList); after traverseBookmarks(bookmarks); like so:

$(document).ready(function() {

    var bookmarksList ='';

    chrome.bookmarks.getTree(function(bookmarks) {
        traverseBookmarks(bookmarks);
        // ++++
        $('#list').html(bookmarksList);
    });

    function traverseBookmarks(bookmarkTreeNodes) {
        for(var i=0;i<bookmarkTreeNodes.length;i++) {
            if(bookmarkTreeNodes[i].url) {
                bookmarksList += '<li>Name: ' + bookmarkTreeNodes[i].title + ' ID: ' + bookmarkTreeNodes[i].id + ' URL: ' + bookmarkTreeNodes[i].url + ' Parent ID: ' + bookmarkTreeNodes[i].parentId;
            }

            if(bookmarkTreeNodes[i].children) {
                traverseBookmarks(bookmarkTreeNodes[i].children);
            } 

        }
    }

});

locrizak
  • 11,687
  • 11
  • 56
  • 80
Francesco Terenzani
  • 1,341
  • 7
  • 14