var things = [{text: "Hello"}, {text: "World"}];
with(HTML) {
var html = div({
id: "foo",
content: a({
href: "#",
content: ["test", span("bar")]
})
}) +
div({
className: "baz",
content: map(things, function (thing) {
return p(thing.text)
})
});
alert(html)
document.write(html)
}Yes, I know, with is very evil but it is cool in this situation.
Here is the full source. I hacked it up in 30 minutes and it is in bad need for a cleanup, but otherwise it seems to work alright.
var HTML = (function () {
function encode(text) {
text = text.replace(/&/g, "&", "g");
text = text.replace(/</g, "<", "g");
text = text.replace(/>/g, ">", "g");
text = text.replace(/"/g, """, "g");
text = text.replace(/'/g, "'", "g");
return text;
}
function renderAttr(attr) {
if(!attr) return '';
var html = '';
for(var name in attr) {
var value = attr[name];
if(name === "className") name == "class";
if(name === "content") continue;
html += ' '+name+'="'+encode(value)+'"'
}
html.encoded = true;
return html
}
function makeTag (name) {
return function (paras, content) {
if(arguments.length < 2) {
content = [];
}
if(typeof content === "string") content = [content]
var attr = {};
if(typeof paras === "string") {
content = [encode(paras)];
} else if(paras == null) {
content = [];
} else if(paras.content) {
var c = paras.content;
delete paras.content;
return arguments.callee(paras, c);
} else if(paras.length > 0) {
content = paras;
} else {
attr = paras;
}
var empty = content.length === 0 ? true : false;
var html = '<'+name+renderAttr(attr)+(empty ? '/' : '')+'>';
if(!empty) {
html += content.join("");
html += ''+name+'>';
}
return html;
}
}
function map(enumerable, fn) {
var result = [];
for(var i = 0, len = enumerable.length; i < len; ++i) {
result.push(fn(enumerable[i]))
}
return result;
}
var tags = ["div", "a", "p", "span"]
var HTML = {
map: map,
encode: encode
};
map(tags, function (name) {
HTML[name] = makeTag(name)
});
return HTML;
})();

6 comments:
I've got something similar in Chiron. It looks like:
tag("div", {id:"foo"}, [
tag("a", {href:"#"}, [
"test",
tag("span", {}, "bar")
])
])
Cool, did you put in support for conditionals, loops, etc.?
I'm currently looking for a templating system that I can easily use on the client and the server with the problem that I cannot read non JS files on the server.
Nifty :)
@Malte Take a look on these 2:
http://jemplate.net/
http://www.kuwata-lab.com/tenjin/
I was using Jemplate for a while, it works fine generally, but has couple of drawbacks like templates should be compiled by external script, and sub-optimal performance because of translating from small internal DSL. For the same reason its pretty feature-full, supports all kinds of loops/conditionals, macroses, etc.
Tenjin uses JavaScript as DSL, so it should be very fast, thats all I know about it though.
Here's one i wrote, it has a few browser bug fixes in it:
http://www.cactusjs.com/browser/trunk/DOM/tag.js
sometimes you just want to add content to the current page, so you don't need to generate HTML. You just have to generate a DOM element tree like this :
$('myform').appendChild(buildom(
['FORM', {action:'http://www.google.com/search', method:'post'},
['LABEL', 'Search',
['INPUT', {name:'q', type:'text'}],
['BUTTON', {type:'submit'}]]]));
here is buildom() : http://github.com/slim/waraq/blob/master/js/json2dom.js
@Adam: Thanks for the link. Looks interesting
@Slim: Thanks for hint. I was specifically shooting for a solution that is not using the DOM because I use this on the server and on the client.
Post a Comment