As a reality check of
my proposal for skins in Helma 2
, I so far came up with the following prototype. The idea seems to work quite nicely already with current builds of Helma 2. I thought E4X could make implementing these kinds of mocha objects very easy, but I was surprised that it really turned out that way in practice.
function handle_get() {
// first prototype for the next incarnation of mocha objects
// the render function, providing the magic
var render = function(view) {
// loop
var toLoop = view..*.(@loop.toSource() != '<></>');
for (var item in toLoop) {
var dataName = toLoop[item].@loop.toString();
delete toLoop[item].@loop;
var data = eval(dataName);
var stamp = toLoop[item].toString();
for (var i in data) {
var stencil = stamp.replace(
eval("/%% "+dataName+"\\$\\.(.+) %%/g"),
'{ '+dataName+'['+i+'].$1 }'
);
stencil = stencil.replace(
eval('/"'+dataName+'\\$/g'),
'"'+dataName+'['+i+']'
);
stencil = stencil.replace(
eval('/"%% (.*)\\$'+dataName+'(.*) %%"/g'),
'{ $1'+i+'$2 }'
);
toLoop.parent().insertChildBefore(
toLoop[item],
eval(stencil)
);
}
delete toLoop[item].parent().*[toLoop[item].childIndex()];
}
// lookup
var toLookup = view..*.(@lookup.toSource() != '<></>');
for (var item in toLookup) {
delete toLookup[item].@lookup;
var lookedup = '('+toLookup[item].children()[0]+')';
toLookup[item].setChildren(lookedup);
}
// check
var toCheck = view..*.(@check.toSource() != '<></>');
for (var item in toCheck) {
if (eval(toCheck[item].@check.toString()))
delete toCheck[item].@check;
else
toCheck[item] = '';
}
return view;
}
// an example skin
var myview = <table border="1">
<tr check="topics">
<th lookup="true">Topic Name</th>
<th lookup="true">Comment Count</th>
</tr>
<tr loop="topics" class="%% 'rowcolor'+ ($topics % 2) %%">
<td>%% topics$.name %%</td>
<td check="topics$.count == 0" lookup="true">
No comments yet</td>
<td check="topics$.count == 1" lookup="true">
%% topics$.count %% comment</td>
<td check="topics$.count > 1" lookup="true">
%% topics$.count %% comments</td>
</tr>
<tr check="!topics">
<td colspan="2" align="center" lookup="true">
This list is empty</td>
</tr>
</table>;
// the example data
var topics = [
{name : 'Peter', count : 0},
{name : 'Wolf', count : 2},
{name : 'John', count : 1},
{name : 'Andy', count : 8}
];
// rendering the list
var listtable = render(myview.copy());
// rendering the empty table
topics = null;
var emptytable = render(myview.copy());
// assembling the page
var page = <html><body>{ listtable }<hr/>{ emptytable }</body></html>;
// writing the page source to the reponse buffer
res.contentType = "text/html";
res.write(page.toSource());
}
Resulting in the following output:
(Topic Name) | (Comment Count) |
---|---|
Peter | (No comments yet) |
Wolf | (2 comments) |
John | (1 comment) |
Andy | (8 comments) |
(This list is empty) |
19.12.2005, 10:28