I wonder if there are anything like a Javascript template system that wraps HTML, so that we don't have to deal with HTML directly (yeah, i know it's a bad idea, but just out of curiosity).
So instead of writing HTML:
<body>
<div id="title">Great work!</div>
<span>My name is Peter</span>
</body>
We write in Json:
body: [
{div: [
{id: "title"},
{body: "Great work!"}
]
{span: [
{body: "My name is Peter"}
]
]
I know it looks kinda weird, but I really love the thing that everything is an object :)
Is there a such implementation for any language? (Im usi开发者_StackOverflow社区ng Ruby myself).
EDIT: Found something interesting:
http://jsonml.org/
Look at their examples! Brilliant!
I've just wrote a little example of the parser, similar to mentioned by you, using plain old JavaScript. My code is a bit dirty (as mentioned by Casey Hope, you shouldn't extend Object.prototype
) , perhaps, but it works and very easy to understand, I hope.
The function itself:
Object.prototype.toHtml = function(options)
{
//Iterates over elements
var processElements = function(obj, handler)
{
//Stores found elements
var elements = [];
for (var elem in obj)
{
//Skips all 'derived' properties
if (!obj.hasOwnProperty(elem)) continue;
//Attribute
if (elem.indexOf("_") == 0)
{
elements.push({type: "attribute", name : /^_([a-z][0-9a-z]+)$/i(elem)[1], value : obj[elem]});
}
//Internal contents
else if (elem == "contents")
{
elements.push({type: "contents", value : obj[elem]});
}
//Text node
else if (elem == "text")
{
elements.push({type: "text", value : obj[elem]});
}
//Ordinary element
else
{
elements.push({type: "element", name : elem, value : obj[elem]});
}
}
//Returns parsed elements
return elements;
}
//Internal function to deal with elements
var toHtmlInternal = function(name, elements)
{
//Creates a new element by name using DOM
var element = document.createElement(name);
//Element children and attributes
var children = processElements(elements);
for (var i = 0; i < children.length; i++)
{
switch (children[i]["type"])
{
case "element":
element.appendChild(toHtmlInternal(children[i]["name"], children[i]["value"]));
break;
case "attribute":
element.setAttribute(children[i]["name"], children[i]["value"]);
break;
case "text":
element.appendChild(document.createTextNode(children[i]["value"]));
break;
case "contents":
for (var j = 0; j < children[i]["value"].length; j++)
{
var content = children[i]["value"][j];
if (typeof content == "string")
{
element.appendChild(document.createTextNode(content));
}
else if (typeof content == "object")
{
element.appendChild(content.toHtml().firstChild);
}
}
break;
}
}
//Returns it
return element;
}
//Initial element checkment
var initial = processElements(this);
//Generic wrapper
var wrapper = document.createElement("div");
for (var i = 0; i < initial.length; i++)
{
if (initial[i]["type"] == "element")
{
wrapper.appendChild(toHtmlInternal(initial[i]["name"], initial[i]["value"]));
}
}
//Returns wrapper
return wrapper;
};
How to use:
//A simple testing template
var html = ({
//Element name is just a plain name here
body: {
//Nested element
div : {
//All attributes are prepended with underscore
_id : "title",
//Content of the element is represented by such construction
text : "Great work!"
},
span : {
text : "My name is Peter"
},
h1 : {
_class : "common",
//Elements can be defined using 'contents' notation also, so we could include text nodes
contents : ["This is my ", {a : {text: "beautiful"}} , " header"]
}
}
}).toHtml();
alert(html.innerHTML);
You should also check out haml. Its quite cool! Its not JSON but its rationale is the same. You don't have to deal with HTML.
精彩评论