1

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 using Ruby myself).

EDIT: Found something interesting:

http://jsonml.org/

Look at their examples! Brilliant!

Jim Ferrans
  • 30,582
  • 12
  • 56
  • 83
never_had_a_name
  • 90,630
  • 105
  • 267
  • 383
  • Just search around for the questions that look for ways to build websites with Javascript alone. These seems to pop up quite often. – Yi Jiang Aug 29 '10 at 04:23
  • possible duplicate of [HTML Templates in Javascript? Without coding in the page?](http://stackoverflow.com/questions/3585573/html-templates-in-javascript-without-coding-in-the-page) – Daniel Vandersluis Aug 29 '10 at 05:51
  • I don't get the purpose of using a Javascript templating system... either you'll cut off users without Javascript enabled or you'll have to do everything twice... – Daniel Vandersluis Aug 29 '10 at 05:57
  • E4X is kind of the opposite of what you're asking for, but it makes everything an object: http://en.wikipedia.org/wiki/ECMAScript_for_XML – Ken Aug 29 '10 at 06:19
  • @daniel. the javascript engine will work on the server side, translating it to xhtml. its just a wrapper, won't get affected if users turn of javascript on their browsers. – never_had_a_name Aug 29 '10 at 12:46

2 Answers2

1

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); 
Daniel O'Hara
  • 13,307
  • 3
  • 46
  • 68
0

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.

naikus
  • 24,302
  • 4
  • 42
  • 43
  • It's not the same thing. It's just like writing HTML but you don't have to be as explicit (no ending tag etc). But I mean just to use json for it instead of xml. – never_had_a_name Aug 29 '10 at 04:26