﻿

/*
 *  Transformer, for string templating
 *
 */
if ( !jgn )
    var jgn = {};

jgn.Transformer = function(source, template, result, data, objref)
{
    // hold the template in javascript
    this.script = null;

    // hold the raw template
    this.template = null;
    
    // hold the generated string
    this.result = null;

    // a shortcut method
    this.render = function(source, info, result, data, objref)
    {
        this.compile(source, info);
        this.transform(result, data, objref);
    }

    this.getTemplate = function(source, info)
    {
        if ( source == "element" )
        {
            var el = document.getElementById(info);
            if ( !el )
                return;
            info = el.innerHTML;
        }
        else if ( source == "file" )
        {
            $.ajax({
                type: "GET",
                url: info,
                async: false,
                success: function(t) {
                    info = t;
                }
            });
        }
        
        return info;
    }

    // take the raw template string, and transform it to javascript
    this.compile = function(source, info)
    {
        this.template = this.getTemplate(source, info);
        
        var lines = [];
        var lineCount = 1;
        
        var endTags = null;
        var startTags = null;
        
        if ( this.template == null )
            this.template = "";

        startTags = this.template.split("<$");
        if ( startTags.length == 1 )
        {
            addScript(lines, startTags[0], false);
        }
        else
        {
            for ( var sidx = 0; sidx < startTags.length; sidx ++ )
            {
                endTags = startTags[sidx].split("$>");

                if ( endTags.length == 1 )
                {
                    addScript(lines, endTags[0], false);
                }
                else
                {
                    for ( var eidx = 0; eidx < endTags.length; eidx ++ )
                    {
                        addScript(lines, endTags[eidx], ( eidx == 0 ));
                    }
                }
            }
        }

        this.script = "";
        for ( var i = 0; i < lines.length; i ++ )
            this.script += lines[i] + "\r\n";
        return this.script;
    }

    // a private helper method that takes a string, and add it to the javascript
    function addScript(lines, line, isJS)
    {
        if ( isJS )
        {
            if ( line.charAt(0) == "=" )
            {
                line = "__result__ += " + line.substring(1);
            }
        }
        else
        {
            line = line.replace(/\"/g, "\\\"");
            line = line.replace(/\n/g, "\\n");
            line = line.replace(/\r/g, "\\r");
            line = "__result__ += \"" + line + "\";";
        }
        
        lines.push( line );
    }

    // if rootObjRef is provide, for example: "my"
    // then the objects in the template can be referenced by "my" instead of the default "data"
    this.transform = function(display, data, rootObjRef)
    {
        if ( this.script == null )
        {
            alert("template is not loaded");
            return;
        }

        if ( rootObjRef != null && rootObjRef != "" )
            eval("var " + rootObjRef + " = data;");

        var __result__ = "";
        eval(this.script);

        if ( display )
        {
            var dp = document.getElementById(display);
            if ( dp )
                dp.innerHTML = __result__;
        }
        
        this.result = __result__;
        return __result__;
    }

    this.getString = function(data, rootObjRef)
    {
        return this.transform(null, data, rootObjRef);
    }
    
    // default behavior
    if ( source+"" != "" && template+"" != "" && result+"" != "" && data != null )
    {
        this.render(source, template, result, data, objref);
    }
}

