socialforge/public/javascripts/baiduTemplate.js

217 lines
9.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* baiduTemplate简单好用的Javascript模板引擎 1.0.6 版本
* http://baidufe.github.com/BaiduTemplate
* 开源协议BSD License
* 浏览器环境占用命名空间 baidu.template nodejs环境直接安装 npm install baidutemplate
* @param str{String} dom结点ID或者模板string
* @param data{Object} 需要渲染的json对象可以为空。当data为{}时仍然返回html。
* @return 如果无data直接返回编译后的函数如果有data返回html。
* @author wangxiao
* @email 1988wangxiao@gmail.com
*/
;(function(window){
//取得浏览器环境的baidu命名空间非浏览器环境符合commonjs规范exports出去
//修正在nodejs环境下采用baidu.template变量名
var baidu = typeof module === 'undefined' ? (window.baidu = window.baidu || {}) : module.exports;
//模板函数放置于baidu.template命名空间下
baidu.template = function(str, data){
//检查是否有该id的元素存在如果有元素则获取元素的innerHTML/value否则认为字符串为模板
var fn = (function(){
//判断如果没有document则为非浏览器环境
if(!window.document){
return bt._compile(str);
};
//HTML5规定ID可以由任何不包含空格字符的字符串组成
var element = document.getElementById(str);
if (element) {
//取到对应id的dom缓存其编译后的HTML模板函数
if (bt.cache[str]) {
return bt.cache[str];
};
//textarea或input则取value其它情况取innerHTML
var html = /^(textarea|input)$/i.test(element.nodeName) ? element.value : element.innerHTML;
return bt._compile(html);
}else{
//是模板字符串,则生成一个函数
//如果直接传入字符串作为模板,则可能变化过多,因此不考虑缓存
return bt._compile(str);
};
})();
//有数据则返回HTML字符串没有数据则返回函数 支持data={}的情况
var result = bt._isObject(data) ? fn( data ) : fn;
fn = null;
return result;
};
//取得命名空间 baidu.template
var bt = baidu.template;
//标记当前版本
bt.versions = bt.versions || [];
bt.versions.push('1.0.6');
//缓存 将对应id模板生成的函数缓存下来。
bt.cache = {};
//自定义分隔符可以含有正则中的字符可以是HTML注释开头 <! !>
bt.LEFT_DELIMITER = bt.LEFT_DELIMITER||'<%';
bt.RIGHT_DELIMITER = bt.RIGHT_DELIMITER||'%>';
//自定义默认是否转义,默认为默认自动转义
bt.ESCAPE = true;
//HTML转义
bt._encodeHTML = function (source) {
return String(source)
.replace(/&/g,'&amp;')
.replace(/</g,'&lt;')
.replace(/>/g,'&gt;')
.replace(/\\/g,'&#92;')
.replace(/"/g,'&quot;')
.replace(/'/g,'&#39;');
};
//转义影响正则的字符
bt._encodeReg = function (source) {
return String(source).replace(/([.*+?^=!:${}()|[\]/\\])/g,'\\$1');
};
//转义UI UI变量使用在HTML页面标签onclick等事件函数参数中
bt._encodeEventHTML = function (source) {
return String(source)
.replace(/&/g,'&amp;')
.replace(/</g,'&lt;')
.replace(/>/g,'&gt;')
.replace(/"/g,'&quot;')
.replace(/'/g,'&#39;')
.replace(/\\\\/g,'\\')
.replace(/\\\//g,'\/')
.replace(/\\n/g,'\n')
.replace(/\\r/g,'\r');
};
//将字符串拼接生成函数,即编译过程(compile)
bt._compile = function(str){
var funBody = "var _template_fun_array=[];\nvar fn=(function(__data__){\nvar _template_varName='';\nfor(name in __data__){\n_template_varName+=('var '+name+'=__data__[\"'+name+'\"];');\n};\neval(_template_varName);\n_template_fun_array.push('"+bt._analysisStr(str)+"');\n_template_varName=null;\n})(_template_object);\nfn = null;\nreturn _template_fun_array.join('');\n";
return new Function("_template_object",funBody);
};
//判断是否是Object类型
bt._isObject = function (source) {
return 'function' === typeof source || !!(source && 'object' === typeof source);
};
//解析模板字符串
bt._analysisStr = function(str){
//取得分隔符
var _left_ = bt.LEFT_DELIMITER;
var _right_ = bt.RIGHT_DELIMITER;
//对分隔符进行转义支持正则中的元字符可以是HTML注释 <! !>
var _left = bt._encodeReg(_left_);
var _right = bt._encodeReg(_right_);
str = String(str)
//去掉分隔符中js注释
.replace(new RegExp("("+_left+"[^"+_right+"]*)//.*\n","g"), "$1")
//去掉注释内容 <%* 这里可以任意的注释 *%>
//默认支持HTML注释将HTML注释匹配掉的原因是用户有可能用 <! !>来做分割符
.replace(new RegExp("<!--.*?-->", "g"),"")
.replace(new RegExp(_left+"\\*.*?\\*"+_right, "g"),"")
//把所有换行去掉 \r回车符 \t制表符 \n换行符
.replace(new RegExp("[\\r\\t\\n]","g"), "")
//用来处理非分隔符内部的内容中含有 斜杠 \ 单引号 处理办法为HTML转义
.replace(new RegExp(_left+"(?:(?!"+_right+")[\\s\\S])*"+_right+"|((?:(?!"+_left+")[\\s\\S])+)","g"),function (item, $1) {
var str = '';
if($1){
//将 斜杠 单引 HTML转义
str = $1.replace(/\\/g,"&#92;").replace(/'/g,'&#39;');
while(/<[^<]*?&#39;[^<]*?>/g.test(str)){
//将标签内的单引号转义为\r 结合最后一步,替换为\'
str = str.replace(/(<[^<]*?)&#39;([^<]*?>)/g,'$1\r$2')
};
}else{
str = item;
}
return str ;
});
str = str
//定义变量,如果没有分号,需要容错 <%var val='test'%>
.replace(new RegExp("("+_left+"[\\s]*?var[\\s]*?.*?[\\s]*?[^;])[\\s]*?"+_right,"g"),"$1;"+_right_)
//对变量后面的分号做容错(包括转义模式 如<%:h=value%>) <%=value;%> 排除掉函数的情况 <%fun1();%> 排除定义变量情况 <%var val='test';%>
.replace(new RegExp("("+_left+":?[hvu]?[\\s]*?=[\\s]*?[^;|"+_right+"]*?);[\\s]*?"+_right,"g"),"$1"+_right_)
//按照 <% 分割为一个个数组,再用 \t 和在一起,相当于将 <% 替换为 \t
//将模板按照<%分为一段一段的,再在每段的结尾加入 \t,即用 \t 将每个模板片段前面分隔开
.split(_left_).join("\t");
//支持用户配置默认是否自动转义
if(bt.ESCAPE){
str = str
//找到 \t=任意一个字符%> 替换为 ‘,任意字符,'
//即替换简单变量 \t=data%> 替换为 ',data,'
//默认HTML转义 也支持HTML转义写法<%:h=value%>
.replace(new RegExp("\\t=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?'':baidu.template._encodeHTML($1),'");
}else{
str = str
//默认不转义HTML转义
.replace(new RegExp("\\t=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?'':$1,'");
};
str = str
//支持HTML转义写法<%:h=value%>
.replace(new RegExp("\\t:h=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?'':baidu.template._encodeHTML($1),'")
//支持不转义写法 <%:=value%>和<%-value%>
.replace(new RegExp("\\t(?::=|-)(.*?)"+_right,"g"),"',typeof($1)==='undefined'?'':$1,'")
//支持url转义 <%:u=value%>
.replace(new RegExp("\\t:u=(.*?)"+_right,"g"),"',typeof($1)==='undefined'?'':encodeURIComponent($1),'")
//支持UI 变量使用在HTML页面标签onclick等事件函数参数中 <%:v=value%>
.replace(new RegExp("\\t:v=(.*?)"+_right,"g"),"',typeof($1)==='undefined'?'':baidu.template._encodeEventHTML($1),'")
//将字符串按照 \t 分成为数组,在用'); 将其合并,即替换掉结尾的 \t 为 ');
//在iffor等语句前面加上 '); ,形成 ');if ');for 的形式
.split("\t").join("');")
//将 %> 替换为_template_fun_array.push('
//即去掉结尾符生成函数中的push方法
//如if(list.length=5){%><h2>',list[4],'</h2>');}
//会被替换为 if(list.length=5){_template_fun_array.push('<h2>',list[4],'</h2>');}
.split(_right_).join("_template_fun_array.push('")
//将 \r 替换为 \
.split("\r").join("\\'");
return str;
};
})(window);