/*
    NAME:    DisplayTemplate
    AUTHOR:  Jay Allen, Textura Design
    DATE:    June 6, 2007
    VERSION: 1.0
    LICENSE: This code is licensed under the Artistic License

    SUMMARY:
    
        The DisplayTemplate object provides methods for merging variables
        into a template string.  The variables and the substrings they
        replace are represented by a Javascript object or a key/value pair
        array.  Replacement substrings are key identifiers surrounded by
        square brackets.  

    PROPERTIES:
    
        template - A string containing the template text to be evaluated.
        
        params - An object whose properties and values are key/value pairs for
                 replacement by the eval() method
        
        strict - Strict mode causes the eval() method to do its work in a
                 case-sensitive manner (see nocase to reverse). It will also
                 cause errors if the all square bracketed replacement
                 substrings in the template are not replaced or if a
                 replacement substring cannot be found for a specified
                 parameter property. Strict mode is disabled by default.
        
        nocase - Forces the eval() method to evaluate the template text and
                 param object properties case-insensitively. This is useful if
                 you want to have this type of matching in conjunction with
                 strict mode
        
        parsedString - An internal property containing the evaluated template
                       output string. For consistency, only use the toString()
                       method to access this value.
    METHODS:

        eval() -     This method does the work of replacing all of the keys
                     specified as properties of the params object with their
                     associated values.  It returns the evaluated string on
                     success and an undefined value otherwise.

        toString() - This method returns the result of the eval() method.
        
    EXAMPLE:

        // Define template string with replacement strings in square brackets
        var tmpl = 'My name is [name].  I am from [city]'

        // Define parameter object with key/value replacement pairs
        // The keys must match the replacement strings in the template
        // and do so, by default, in a case sensitive manner although
        // in this example, we'll be switching to case-insensitive matching.
        var params = {Name: "Jay", City: "New Orleans"}

        // Instantiate object with template string and paramter object
        tmplobj = new DisplayTemplate(tmpl, params)

        // We want strict mode on here to ensure that we don't make mistakes
        tmplobj.strict = 1

        // ...but we want to use variable case in our param properties
        tmplobj.nocase = 1

        // Evaluate DisplayTemplate; returns evaluated string on success
        // Method toString() can also be used for display after eval() if desired
        if (tmplobj.eval()) {
            // See before and after 
            alert(tmplobj.template)
            alert(tmplobj.toString())
        }

*/
function DisplayTemplate(template, params) {
    this.template = template
    this.params = params
    this.strict = 0          // Specifies strict mode
    this.nocase = undefined
    this.parsedString = ""
}

DisplayTemplate.prototype.toString = function() { return this.parsedString }

DisplayTemplate.prototype.eval = function() { 

    // Make sure that template and params are set
    if (this.template == undefined)
        throw new Error("DisplayTemplate template propertie not defined")
    if (this.params == undefined)
        throw new Error("Property 'params' not defined for DisplayTemplate: "+this.template)

    // Set options: Global plus optional case-insensitive flag
    var opts = "g"
    if (this.nocase == 1) opts = opts + "i";

    // Replace parameter keys with associate values
    var tmpl = this.template
    for (var name in this.params) {
        var str = name
        var replacement = this.params[str]

        if (this.strict && tmpl.indexOf("["+str+"]") < 0)
            throw new Error("Replacement key '"+str+"' not found in display template string under strict mode: "+this.template)

        var re = new RegExp("\\["+str+"\\]", opts)
        tmpl = tmpl.replace(re, replacement)
    }

    // Setting for internal toString() method
    this.parsedString = tmpl

    // Return evaluated template
    return this.parsedString
}
