I'm trying to create a collapsing/expanding animated treeview in Javascript. I found the JQuery treeview plugin, and it's working great. However, I have one key need that I can seem to figure out with the samples provided:
Basically I need the "advanced async feature" they provide (http:// jquery.bassistance.de/treeview/demo/async.html). As the user clicks on each "main node" in the tree, I need to make an AJAX-call to pull in the sub-tree links. My problem is that I need to do some post- processing in JS of the JSON data that comes back from the server in order to keep the tree-view plugin happy (and I don't control the API's on the server for the data-source) When I make my call to the API to retrieve it top-level tree, the JSON data comes back like this: navcallback({"response":{"statusCode":200,"data":{"genrelist":{"genre": [{"id":1,"haschildren":true,"name":"Alternative","parentid":0},{"id": 24,"haschildren":true,"name":"Blues","parentid":0},{"id": 32,"haschildren":true,"name":"Classical","parentid":0},{"id": 44,"haschildren":true,"name":"Country","parentid":0},{"id": 212,"haschildren":true,"name":"Decades","parentid":0},{"id": 54,"haschildren":true,"name":"Easy Listening","parentid":0},{"id": 61,"haschildren":true,"name":"Electronic","parentid":0},{"id": 82,"haschildren":true,"name":"Folk","parentid":0},{"id": 122,"haschildren":true,"name":"Inspirational","parentid":0},{"id": 134,"haschildren":true,"name":"International","parentid":0},{"id": 163,"haschildren":true,"name":"Jazz","parentid":0},{"id": 177,"haschildren":true,"name":"Latin","parentid":0},{"id": 195,"haschildren":true,"name":"Metal","parentid":0},{"id": 295,"haschildren":false,"name":"Misc","parentid":0},{"id": 206,"haschildren":true,"name":"New Age","parentid":0},{"id": 220,"haschildren":true,"name":"Pop","parentid":0},{"id": 232,"haschildren":true,"name":"R&B/Urban","parentid":0},{"id": 110,"haschildren":true,"name":"Rap","parentid":0},{"id": 242,"haschildren":true,"name":"Reggae","parentid":0},{"id": 250,"haschildren":true,"name":"Rock","parentid":0},{"id": 265,"haschildren":true,"name":"Seasonal/Holiday","parentid":0},{"id": 276,"haschildren":true,"name":"Soundtracks","parentid":0},{"id": 282,"haschildren":true,"name":"Talk","parentid":0},{"id": 89,"haschildren":true,"name":"Themes","parentid": 0}]}},"statusText":"Ok"}}); All is well, but I need to do some JS processing on it as it comes back, so I run it through a script like this: function navcallback(d) { var response='['; for (i=0;i<=d.response.data.genrelist.genre.length - 1;i++) { response += '{"text": "'+d.response.data.genrelist.genre[i].name +'","id": "'+d.response.data.genrelist.genre[i].id+'","hasChildren": true},'; } response = response.slice(0, -1); response += ']'; } Which then gets the data in the format that jQuery treeview expects it: [{"text": "Alternative","id": "1","hasChildren": true},{"text": "Blues","id": "24","hasChildren": true},{"text": "Classical","id": "32","hasChildren": true},{"text": "Country","id": "44","hasChildren": true},{"text": "Decades","id": "212","hasChildren": true},{"text": "Easy Listening","id": "54","hasChildren": true},{"text": "Electronic","id": "61","hasChildren": true},{"text": "Folk","id": "82","hasChildren": true},{"text": "Inspirational","id": "122","hasChildren": true},{"text": "International","id": "134","hasChildren": true},{"text": "Jazz","id": "163","hasChildren": true},{"text": "Latin","id": "177","hasChildren": true},{"text": "Metal","id": "195","hasChildren": true},{"text": "Misc","id": "295","hasChildren": true},{"text": "New Age","id": "206","hasChildren": true},{"text": "Pop","id": "220","hasChildren": true},{"text": "R&B/Urban","id": "232","hasChildren": true},{"text": "Rap","id": "110","hasChildren": true},{"text": "Reggae","id": "242","hasChildren": true},{"text": "Rock","id": "250","hasChildren": true},{"text": "Seasonal/Holiday","id": "265","hasChildren": true}, {"text": "Soundtracks","id": "276","hasChildren": true},{"text": "Talk","id": "282","hasChildren": true},{"text": "Themes","id": "89","hasChildren": true}] However, I can't for the life of me figure out how to get this integrated with the JQuery treeview's async.js code (below). All would be fine if I didn't need to do this post-processing, but I need to. Gotcha's that I'm dealing with: 1) The API data is coming from a cross-domain server, so I think I probably need to use the $.getScript call to retrieve the JSONp data. 2) I can't figure out how to get my navback handler integrated into the "load" function of treeview. If I insert my "response- reformatting code" inside the getJSON function, all kinds of bad things start happening. I suspect it has to do with the "this" objects and parent and other things which are quite complex in this plugin. function load(settings, root, child, container) { $.getJSON(settings.url, {root: root}, function(response) { function createNode(parent) { mythis = this; var current = $("<li/>").attr("id", this.id || "").html("<span>" + this.text + "</span>").appendTo(parent); if (this.classes) { current.children("span").addClass(this.classes); } if (this.expanded) { current.addClass("open"); } if (this.hasChildren || this.children && this.children.length) { var branch = $("<ul/>").appendTo(current); if (this.hasChildren) { current.addClass("hasChildren"); createNode.call({ text:"placeholder", id:"placeholder", children:[] }, branch); } if (this.children && this.children.length) { $.each(this.children, createNode, [branch]) } } } $.each(response, createNode, [child]); $(container).treeview({add: child}); }); } var proxied = $.fn.treeview; $.fn.treeview = function(settings) { if (!settings.url) { return proxied.apply(this, arguments); } var container = this; load(settings, "source", this, container); var userToggle = settings.toggle; return proxied.call(this, $.extend({}, settings, { collapsed: true, toggle: function() { var $this = $(this); if ($this.hasClass("hasChildren")) { var childList = $this.removeClass("hasChildren").find("ul"); childList.empty(); load(settings, this.id, childList, container); } if (userToggle) { userToggle.apply(this, arguments); } } })); }; })(jQuery);