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);

Reply via email to