/**
 * Copyright (c) 2006, Yusuke Inuzuka<yuin@inforno.net>(http://inforno.net)
 *
 * License :
 *     Articstic License 2.0
 *
 * Lyase.View :
 *     This class is a part of javascript framework "Lyase"(under making...)
 *     This class requires prototype.js(http://prototype.conio.net/)
 *
 * Description :
 *
 *     Lyase.View provides simple way to embed javascript codes
 *     within any plain text.
 *
 * Usage and examples :
 *
 *     using text
 *     -------------
 *     var template = "The value of x is:<%= context.x%>";
 *     document.write(Lyase.View.render({text:template}, {x : 10}));
 *
 *     using innerHTML
 *     -------------
 *     //in HTML
 *     <textarea id="template" style="display:none">
 *         The value of x is:<%= context.x%>
 *     </textarea>
 *     //code
 *     document.write(Lyase.View.render({element:"template"}, {x : 10}));
 *
 *     using a template file
 *     -------------
 *     //in /template.jhtml
 *     The value of x is:<%= context.x%>
 *     //code
 *     document.write(Lyase.View.render({file:"/template.jhtml"}, {x : 10}));
 *
 *     Of course, you can embed more complex codes.
 *     //in HTML, with prototype.js
 *     <textarea id="template" style="display:none">
 *         <% context.list.each(function(pair){%>
 *                    The value of <%= pair.name %> is: <%= pair.value%>
 *         <% }) %>
 *     </textarea>
 *     //code
 *     document.write(Lyase.View.render({element:"template"},
 *         {list :[{name : "x", value : 10}, {name : "y", value : 20}]}));
 *
 *
 * Recognized Tags :
 *
 *     <% javascript code %>
 *     <%= javascript expression %>
 *     <%\* comment *\%>(\ is meaning of /)
 */
var Lyase = {};
Lyase.View = {
    _cache : {},
    parse : function(template, id) {
        var self = Lyase.View,parsed = ["var __out=[],render = Lyase.View.render;"]
        var tokens = template.split("[%");
        for(var i = 0, l = tokens.length; i<l; i++) {
            var token = tokens[i];
            if(token.indexOf("%]") == -1){
                parsed.push(self._string(token));
                continue;
            }
            var parts = token.split("%]");
            parsed.push(self[(parts[0].charAt(0) == "=")?"_value":"_code"](parts[0]));
            parsed.push(self._string(parts[1]));
        }
        parsed.push("return __out.join('');");
        var templateFunc = new Function("context", parsed.join(""));
        if(id) self._cache[id] = templateFunc;
        return templateFunc;
    },

    render : function(options, values) {
        var self = Lyase.View, template, id;
        if(options.text) return self.parse(options.text, null)(values);
        if(options.element){
            var element = $(options.element);
        }
        id = (options.file) ? options.file : element.id;
        if(self._cache[id]){
            return self._cache[id](values);
        }
        if(options.element) {
            template = self._elementTemplate(element);
        }else {
            //template = (new Ajax.Request(options.file,{asynchronous : false})).transport.responseText;
            //template = (new Ajax.Request(options.file,{asynchronous : false, method:'get'})).transport.responseText;
            template = self._get( options.file );
        }
        return self.parse(template, id)(values);
    },

    _elementTemplate : function(element) {
        var template = element.innerHTML;
        if(element.tagName.toLowerCase() != "textarea") {
            // modified by m.o. undepend on prototype.js
            template = template.split("<!--[CDATA[")[1].split("]]-->")[0];
        }else if(template.indexOf("&lt;") != -1) {
             template = Lyase.View._unescapeHTML(template);
            // modified by Masakazu O. to make undepent on prototype.js
            // textarea unsupported, use div
        }
        return template.replace(/\n|\r/g, "");
    },

    _string : function(string) {
        return ["__out.push('",string.replace(/\n|\r/g,"").replace(/'/g, "\\'"),"');"].join("");
    },

    _value    : function(string) {
        return ["__out.push(",string.replace(/\n|\r/g,"").substring(1),");"].join("");
    },

    _code     : function(string) {
        string = string.replace(/\n|\r/g,"");
        if(string.charAt(string.length-1) != ";") string += ";";
        return string;
    },

    // Masakazu O. added below
    _get : function( url ){
        var req;
        if (window.XMLHttpRequest) {
            req = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (req) {
            req.open("GET", url, false);
            req.send("");
            return req.responseText;
        }else{
            return '';
        }
    },

    _unescapeHTML : function(html) {
        var div = document.createElement('div');
        div.innerHTML = html.replace(/<\/?[^>]+>/gi, '');
        return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
    }
}
