View Full Version : eval-ing json

18 Oct 2006, 10:21 PM
I find myself sending back huge strings of grid properties from my serverside framework, like

new RUtil.prado.DataList('Admin:MusicManager:ArtistViewer:AlbumList', {"AllowSorting":false,"ShowHeader":true,"HeaderCssClass":"","ShowFooter":false,"ShowSearch":false,"TableCssClass":"recordset ygrid-mso","ItemCssClass":"","SelectedItemCssClass":"",
"AlternatingItemCssClass":"","Layout":"TABLE","tagName":"TABLE","AutoLoad":false,"UseDraggable":"","Group":"","UseDroppable":"","DropGroup":"","OnClick":"","Columns":[{"Class":"RTemplateColumn","TagType":"","TagName":"","Width":"","HeaderText":"","ItemTemplate":"\n\t\t\t\t\n\t\t\t{0}\"},{"Class":"RTemplateColumn","TagType":"","TagName":"","Width":"","HeaderText":"","ItemTemplate":"\n\t\t\t\t\n\t\t\t<div>{1}</div><div>{2}</div>"}],"js":"\t\t\/***\r\n\t\t *\r\n\t\t * var list = dh.append(this.id + ':recordset',
{\r\n \t\t\ttag: this.param.TagName, cls: this.param.TableCssClass, children: [\r\n\t\t {tag: 'li', id: 'item0', html: 'List Item 0'},\r\n\t\t {tag: 'li', id: 'item1', html: 'List Item 1'},\r\n\t\t {tag: 'li', id: 'item2', html: 'List Item 2'},\r\n\t\t
{tag: 'li', id: 'item3', html: 'List Item 3'},\r\n\t\t {tag: 'li', id: 'item4', html: 'List Item 4'}\r\n ]\r\n});\r\n\r\n\t\tvar list = dh.append(this.id +
':recordset', {tag: this.param.TagName, cls: this.param.TableCssClass});\r\n\r\n\t\t
var dh = YAHOO.ext.DomHelper;\r\n\t\t*\/\r\n\t\talert('motherer');\r\n"});

so why not cut out the middleman and just send back Grid creation / DomHelper.Template code and eval(json) ?

is there anything wrong with this?
my partner told me of talk on the yui forums of people abusing eval(json);

Dave says:
I was reading YUI on JSON, a little there explained how you eval JSON and that turns it into objects etc.. said it was probably the only acceptable use of eval.. in other words.. eval is one of those really abused things... in javascript...

anything wrong with eval-ing YAHOO.ext.grid.Grid, etc / YAHOO.ext.DomHelper code?

19 Oct 2006, 3:16 AM
In the site I'm working, I use eval a lot to cut down on bandwidth used. I retrieve (using Jack's great updatemanager) javascript from the server and run an eval on it using a seperate renderer I built just for this purpose and haven't had any problems so far.

Here's an example of a renderer I'm using in one portion of my site.

YAHOO.whasit.MODULE.prototype.renderer = {
render: function(el, o) {
try {
catch(err) {
el.update(err + ": " + o.responseText);

Note: Later that catch will probably end up turning into

catch(err) {

That way if what I pass isn't javascript, and rather straight html, it will be displayed without the error messages. I'm just using the current catch to see errors as I'm still in extreme development mode.

19 Oct 2006, 6:04 AM
The reason to not send and eval the JS is for caching reasons primarily. If you send the grid creation code and everything down the pipe with the data, then every load has to reload the UI. It's cheaper to just send the data.

What you can do is send "script" tags and have appended to the document referencing external predefined js files so your UI continues to be cached. Is that an option?

19 Oct 2006, 6:31 AM
I certainly wouldn't create a new grid after each ajax request, that'd be insane.

yes, I'm currently rendering script frags on the first postback, which contain a long string of properties related to the list that needs to be rendered.

after a few hours' sleep, I think I'll just send back the DomHelper templates, rather than including the actual js to process the templates, as well.

after all, wouldn't it take make *more* bandwidth to express the data as:

{tag: 'li', id: 'item0', html: 'List Item 0'},
{tag: 'li', id: 'item1', html: 'List Item 1'},
{tag: 'li', id: 'item2', html: 'List Item 2'},
{tag: 'li', id: 'item3', html: 'List Item 3'},
{tag: 'li', id: 'item4', html: 'List Item 4'}

than it would to express it as a compact json array?

19 Oct 2006, 6:43 AM
don't forget, for the case of grids, there is a JSONdatamodel :)

19 Oct 2006, 6:44 AM
That's not a bad idea. You could also define a renderer for the element's UpdateManager (UM) that uses a template and then just process the JSON with the template.

var Renderer = new function(){
var template = Yahoo.ext.DomHelper.createTemplate(...); // template with named parameters
this.render = function(el, response){
var obj = eval('('+response.responseText+')'); // JSON data
template.overwrite(el.dom, obj);

19 Oct 2006, 6:45 AM
yup, I use my own version of JSONDataModel, almost exclusively (so far).