(function(){
var rsplit = function(string, regex) {
var result = regex.exec(string),retArr = new Array(), first_idx, last_idx, first_bit;
while (result != null)
{
first_idx = result.index; last_idx = regex.lastIndex;
if ((first_idx) != 0)
{
first_bit = string.substring(0,first_idx);
retArr.push(string.substring(0,first_idx));
string = string.slice(first_idx);
}
retArr.push(result[0]);
string = string.slice(result[0].length);
result = regex.exec(string);
}
if (! string == '')
{
retArr.push(string);
}
return retArr;
},
chop = function(string){
return string.substr(0, string.length - 1);
},
extend = function(d, s){
for(var n in s){
if(s.hasOwnProperty(n)) d[n] = s[n]
}
}
EJS = function( options ){
options = typeof options == "string" ? {view: options} : options
this.set_options(options);
if(options.precompiled){
this.template = {};
this.template.process = options.precompiled;
EJS.update(this.name, this);
return;
}
if(options.element)
{
if(typeof options.element == 'string'){
var name = options.element
options.element = document.getElementById( options.element )
if(options.element == null) throw name+'does not exist!'
}
if(options.element.value){
this.text = options.element.value
}else{
this.text = options.element.innerHTML
}
this.name = options.element.id
this.type = '['
}else if(options.url){
options.url = EJS.endExt(options.url, this.extMatch);
this.name = this.name ? this.name : options.url;
var url = options.url
//options.view = options.absolute_url || options.view || options.;
var template = EJS.get(this.name /*url*/, this.cache);
if (template) return template;
if (template == EJS.INVALID_PATH) return null;
try{
this.text = EJS.request( url+(this.cache ? '' : '?'+Math.random() ));
}catch(e){}
if(this.text == null){
throw( {type: 'EJS', message: 'There is no template at '+url} );
}
//this.name = url;
}
var template = new EJS.Compiler(this.text, this.type);
template.compile(options, this.name);
EJS.update(this.name, this);
this.template = template;
};
/* @Prototype*/
EJS.prototype = {
/**
* Renders an object with extra view helpers attached to the view.
* @param {Object} object data to be rendered
* @param {Object} extra_helpers an object with additonal view helpers
* @return {String} returns the result of the string
*/
render : function(object, extra_helpers){
object = object || {};
this._extra_helpers = extra_helpers;
var v = new EJS.Helpers(object, extra_helpers || {});
return this.template.process.call(object, object,v);
},
update : function(element, options){
if(typeof element == 'string'){
element = document.getElementById(element)
}
if(options == null){
_template = this;
return function(object){
EJS.prototype.update.call(_template, element, object)
}
}
if(typeof options == 'string'){
params = {}
params.url = options
_template = this;
params.onComplete = function(request){
var object = eval( request.responseText )
EJS.prototype.update.call(_template, element, object)
}
EJS.ajax_request(params)
}else
{
element.innerHTML = this.render(options)
}
},
out : function(){
return this.template.out;
},
/**
* Sets options on this view to be rendered with.
* @param {Object} options
*/
set_options : function(options){
this.type = options.type || EJS.type;
this.cache = options.cache != null ? options.cache : EJS.cache;
this.text = options.text || null;
this.name = options.name || null;
this.ext = options.ext || EJS.ext;
this.extMatch = new RegExp(this.ext.replace(/\./, '\.'));
}
};
EJS.endExt = function(path, match){
if(!path) return null;
match.lastIndex = 0
return path+ (match.test(path) ? '' : this.ext )
}
/* @Static*/
EJS.Scanner = function(source, left, right) {
extend(this,
{left_delimiter: left +'%',
right_delimiter: '%'+right,
double_left: left+'%%',
double_right: '%%'+right,
left_equal: left+'%=',
left_comment: left+'%#'})
this.SplitRegexp = left=='[' ? /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/ : new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') ;
this.source = source;
this.stag = null;
this.lines = 0;
};
EJS.Scanner.to_text = function(input){
if(input == null || input === undefined)
return '';
if(input instanceof Date)
return input.toDateString();
if(input.toString)
return input.toString();
return '';
};
EJS.Scanner.prototype = {
scan: function(block) {
scanline = this.scanline;
regex = this.SplitRegexp;
if (! this.source == '')
{
var source_split = rsplit(this.source, /\n/);
for(var i=0; i
*
*/
EJS.config = function(options){
EJS.cache = options.cache != null ? options.cache : EJS.cache;
EJS.type = options.type != null ? options.type : EJS.type;
EJS.ext = options.ext != null ? options.ext : EJS.ext;
var templates_directory = EJS.templates_directory || {}; //nice and private container
EJS.templates_directory = templates_directory;
EJS.get = function(path, cache){
if(cache == false) return null;
if(templates_directory[path]) return templates_directory[path];
return null;
};
EJS.update = function(path, template) {
if(path == null) return;
templates_directory[path] = template ;
};
EJS.INVALID_PATH = -1;
};
EJS.config( {cache: true, type: '<', ext: '.ejs' } );
/**
* @constructor
* By adding functions to EJS.Helpers.prototype, those functions will be available in the
* views.
* @init Creates a view helper. This function is called internally. You should never call it.
* @param {Object} data The data passed to the view. Helpers have access to it through this._data
*/
EJS.Helpers = function(data, extras){
this._data = data;
this._extras = extras;
extend(this, extras );
};
/* @prototype*/
EJS.Helpers.prototype = {
/**
* Renders a new view. If data is passed in, uses that to render the view.
* @param {Object} options standard options passed to a new view.
* @param {optional:Object} data
* @return {String}
*/
view: function(options, data, helpers){
if(!helpers) helpers = this._extras
if(!data) data = this._data;
return new EJS(options).render(data, helpers);
},
/**
* For a given value, tries to create a human representation.
* @param {Object} input the value being converted.
* @param {Object} null_text what text should be present if input == null or undefined, defaults to ''
* @return {String}
*/
to_text: function(input, null_text) {
if(input == null || input === undefined) return null_text || '';
if(input instanceof Date) return input.toDateString();
if(input.toString) return input.toString().replace(/\n/g, 'Option Default Description
type
'<'
type of magic tags. Options are '<' or '['
cache
true in production mode, false in other modes
true to cache template.
').replace(/''/g, "'");
return '';
}
};
EJS.newRequest = function(){
var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
for(var i = 0; i < factories.length; i++) {
try {
var request = factories[i]();
if (request != null) return request;
}
catch(e) { continue;}
}
}
EJS.request = function(path){
var request = new EJS.newRequest()
request.open("GET", path, false);
try{request.send(null);}
catch(e){return null;}
if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
return request.responseText
}
EJS.ajax_request = function(params){
params.method = ( params.method ? params.method : 'GET')
var request = new EJS.newRequest();
request.onreadystatechange = function(){
if(request.readyState == 4){
if(request.status == 200){
params.onComplete(request)
}else
{
params.onComplete(request)
}
}
}
request.open(params.method, params.url)
request.send(null)
}
})();