Re: Issue 52 in canviz: add json capability to load()

14 views
Skip to first unread message

Ryan Schmidt

unread,
Jan 12, 2009, 11:21:35 PM1/12/09
to can...@googlegroups.com
On Jan 11, 2009, at 12:08, codesite...@google.com wrote:

> Oftentimes it is necessary to pass back from a server auxiliary data
> besides the xdot source: prompts, thumbnail data, etc.
>
> So I suggest that the load() method have an additional parameter:
> is_json.
> When true, canviz expects JSON data, and parses the xdot portion
> using of
> it Prototype, then calls a user javascript function outside of
> canviz for
> any postprocessing of the rest of the JSON data.
>
> Something like:
> // ********* this part unchanged ***************
> load: function(url, url_params,is_json) {
> $('debug_output').innerHTML = '';
> new Ajax.Request(url, {
> method: 'get',
> parameters: url_params,
> onComplete: function(response) {
>
> // *** changed part: **************
> if(is_json) {
> this.json = response.responseText.evalJSON(true);
> this.parse(this.json.image);
> postproc_json(this.json);
> }
> else {
> this.parse(response.responseText);
> }
> // ***** end changed part *****************
>
> }.bind(this)
> });
> },
>
>
>
> and the user might have, outside of canviz.js, something like:
>
> function postproc_json(jsonresponse) {
> $('thumbnails').innerHTML = jsonresponse.thumbnails;
> $('refresh_prompt').innerHTML = jsonresponse.refresh_prompt;
> $('auxactions').innerHTML = jsonresponse.auxactions; // anything
> that
> requires a script to run AFTER the Ajax response is complete.
>
> eval($('auxactions').innerHTML);
> return(true);
> }

You mentioned this request on this discussion group on January 7:

http://groups.google.com/group/canviz/browse_thread/thread/
a3d37ed8a0905326

The problem I see with your proposed change is that it introduces
specifics of your project into Canviz, or at least it limits the way
this new feature could be used. For example, it mandates that if you
use the JSON mode, then the xdot data must be in the "image" part of
the JSON data; what if the user wanted to call it something else? It
also requires that the user provide a global function called
"postproc_json" to handle the remaining data; what if the user wanted
to use a different function name, or wanted to call a method of an
object?

This could all be addressed by additional parameters to the load()
method, but that starts getting unwieldy. And what if, say, you
wanted to update two graphs in a single AJAX call? You would have two
Canviz objects, each bound to a different div, so if you use either
object's load() method, it would only load data for that graph and
not the other one.

So for these reasons I still feel that this is best handled in your
own code. Don't call the Canviz object's load() method at all.
Instead, load the data in a function of your own creation, and when
you have it, pass the xdot data to the Canviz object's parse method
and do what you want with the rest of it. For example:


var gCanviz;

document.observe('dom:loaded', function() {
gCanviz = new Canviz('canviz_div');
// any other initializations
loadData('json.php', {foo: 'bar'});
}

function loadData(url, urlParams) {
new Ajax.Request(url, {
method: 'get',
parameters: urlParams,
onComplete: function(response) {
gCanviz.parse(response.responseJSON.image);
$('thumbnails').update(response.responseJSON.thumbnails);
$('refresh_prompt').update(response.responseJSON.refresh_prompt);
$('auxactions').update(response.responseJSON.auxactions);
}.bind(this)
});
}


Does this meet your needs?


Note from the Prototype documentation that it automatically evaluates
JSON data and places it into the response object's responseJSON
property if the Content-Type header is set to "application/json".

http://prototypejs.org/api/ajax/response


I also used update() instead of setting innerHTML directly. This also
has the effect of automatically running evalScripts() if necessary.
Not sure if this works as you wanted (or at all -- I just typed it
without testing it). If auxactions contains only scripts and nothing
visible, you may want to not put it in a DOM element at all, and just
call evalScripts() on the string directly.

http://prototypejs.org/api/element/update

http://prototypejs.org/api/string/evalScripts


Ron Newman

unread,
Jan 14, 2009, 11:39:58 AM1/14/09
to can...@googlegroups.com

I agree, user-app specific stuff is better completely divorced from canviz.  I've taken your suggestion but left out onload:dom, which caused an infinite loop.

If I use content type:  application/json  does that conflict with using
Content-Type: text/vnd.graphviz; charset=UTF-8  
for the benefit of canviz?

I went to that content type per your suggestion to fix javascript's complaining about htmlentities in the image map like    •   (it still complains, anyway, I may have an escaping problem)

For benefit of future coders:  it's actually easier in a way if (by using text/vnd.graphviz) Prototype does not automatically evaluate scripts coming over JSON for me, since it's much easier to debug using Firebug if all that isn't buried in Prototype but visible in my own client-side script, though it's prettier using the .update() as you suggest.  I'm not using eval() but ' var myfunc=new Function(mycode); myfunc() '  instead for speed purposes.



Reply all
Reply to author
Forward
0 new messages