While developing a simple rest service I needed a simple web interface.
While a full-featured dojo is quite heavy, if you use dojo mobile without importing any dijit stuff you can speed up things a lot. And if you use an http cache for static contents thing will even get better!
I choose dojo mobile 1.7 because it has a nice Grid+Store implementation.
Grid+Store is a toy that renders the json output of an url into an html table or list. When the url response changes, the page is updated.
Moreover the Grid/List can bind each row to an action, so that if you click on a item, you’ll be directed to another page. In my case the main view shows a list of file, and clicking on one file you will see it’s attributes (size & co).
So, when clicking on a file I needed to issue an ajax request retrieving file info from the server.
Dojo implements this using the “callback” tag.
ex.
The previous html is generated by a json string like the following, so with dojo Store you can dynamically build a list with actions connected to each item.
{ 'item' : {
'label' : 'file.txt',
'moveTo' : 'fileView',
'callback' : 'function() {renderfile("/path/to/file.txt");}'
}
}
In dojo 1.7 the callback stuff is broken, so after looking on dojo trac, I found and apply a patch. Still no way, but at least I got an error – while before the patch the callback parameter was simply ignorated.
The error was something like
Object "renderfile('/path/to/file.txt')" has no method apply
The apply() method is a js method that a function must have. Better: if a js object hasn’t the apply() method, then it’s not a function!
Using js console I found that the callback argument was interpreted as a string, and not as a function.
So I start investingating on the json I used to populate the grid. And I noted that the issue was related to the quote sign around the callback function.
In fact json encloses in string only strings, not numbers or functions. But the json was generated by the server, using python simplejson library. For that lib, a js function is a string, so it’s encosed in quote.
The solution was to find the place where the function was called in dojo, and add a test: if the object supposed to contain a method is a string, then you evaluate the string to a method.
>>>lang.js
+if (typeof(scope[method].apply) == "undefined" ) {
+ scope[method] = eval(scope[method]);
+}
return scope[method].apply(scope, arguments || []);
>>>ViewController.js
+if (src.callback && typeof(src.callback.apply) == "undefined") {
+ src.callback = eval(src.callback);
+}
w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, src.callback && src, src.callback);