var Template = Class.create({
//Initialization method
initialize: function(template, pattern) {
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
},
//Formatting method, from a java perspective, it is actually better to call it format :)
evaluate: function(object) {
//Check whether the toTemplateReplacements method is defined, if so call
/ /In the entire Prototype framework, only the Hash object defines this method
if (object && Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
//Here gsub is a method in the String object. It can be simply thought of as replacing all parts of the string that match pattern
return this.template.gsub(this.pattern, function(match) {
//match[0 ] is the entire string that matches Template.Pattern
//match[1] is the character in front of the matching string
//match[2] is the part that matches the expression ${var}
//match[3] is the 'var' part of the '#{var}' expression
//If object is null, replace all ${var} expressions with ''
if (object == null) return (match[1] '');
//Get the character before the matching expression
var before = match[1] || '';
//If the previous string is '', return the matching expression directly without replacement
if (before == '\') return match[2];
var ctx = object, expr = match[3];
//This regular expression seems to be to check whether var is a legal name. I don’t understand the meaning of this regular expression yet?
var pattern = /^([^.[] |[((?:.*?[^\])?)])(.|[|$)/;
match = pattern.exec( expr);
//If var does not meet the requirements, return the previous character directly
if (match == null) return before;
//Replace the '#{var}' expression part one by one
while (match != null) {
// Don’t understand what the following check means?
var comp = match[1].startsWith('[') ? match[2].gsub('\ \]', ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
match = pattern.exec(expr);
}
/ /Return the replaced result, '#{var}' ==> 'value'
return before String.interpret(ctx);
});
}
});
//The default template matches regular expressions, in the form of #{var}, much like the EL expression in JSP
Template.Pattern = /(^|.|r|n)(#{(.*? )})/;
The above basically explained the evaluate method, but I didn’t understand some parts clearly. Those regular expressions are too difficult to understand. . . Who knows and tells me?
Look at the example below:
var myTemplate = new Template('The TV show #{title} was created by #{author}.');
var show = {title: 'The Simpsons', author: 'Matt Groening', network: 'FOX' };
myTemplate.evaluate(show);
// -> The TV show The Simpsons was created by Matt Groening.
var t = new Template('in #{lang} we also use the \#{ variable} syntax for templates.');
var data = {lang:'Ruby', variable: '(not used)'}; t.evaluate(data);
// -> in Ruby we also use the #{variable} syntax for templates.
//Custom matching pattern
var syntax = /(^|.|r|n)(<%=s*(w )s*%>)/;
//matches symbols like '<%= field %>'
var t = new Template('
Name: <%= name %>, Age: <%=age%>
', syntax);
t.evaluate( {name: 'John Smith', age: 26 } );
// ->
Name: John Smith, Age: 26
var conversion1 = {from: 'meters', to: 'feet', factor: 3.28};
var conversion2 = {from: 'kilojoules', to: 'BTUs', factor: 0.9478};
var conversion3 = {from: 'megabytes', to: 'gigabytes', factor: 1024};
var templ = new Template('Multiply by #{factor} to convert from #{from} to #{to}.');
[conversion1, conversion2, conversion3].each( function(conv){ templ.evaluate(conv); });
// -> Multiply by 3.28 to convert from meters to feet.
// -> Multiply by 0.9478 to convert from kilojoules to BTUs.
// -> Multiply by 1024 to convert from megabytes to gigabytes.