📄 template.js
字号:
/**
* @public
* @param xmlDoc
*/
function Template(xmlDoc){
this.taglib = {};
this.putTaglib(new DefaultTag(), '*');
this.putTaglib(new XHTMLTag());
this.putTaglib(new CoreTag());
if(typeof xmlDoc == 'string'){
this.doc = Template.loadDoc(xmlDoc);
}else if(xmlDoc != null){
this.doc = xmlDoc;
}
}
Template.prototype.putTaglib = function(tl,ns){
this.taglib[ns||tl.$namespaceURI] = tl;
}
/**
* 加载文档
* @param <string>value xml url or xml string
*/
Template.loadDoc = function(value){
if(!/^\s*</.test(value)){
var doc = new Request(value).send().getResult();
if(typeof doc != 'string'){
return doc;
}else{
value = doc;
}
}
if(window.DOMParser){//code for Mozilla, Firefox, Opera, etc.
return new DOMParser().parseFromString(value,"text/xml");
}else{
var doc=new ActiveXObject("Microsoft.XMLDOM");
doc.async="false";
doc.loadXML(value);
return doc;
}
}
/**
* @public
* @param data <Object|OutputContext> 数据集合
* @param out <Writer|Document> 输出接口 至少需要一个成员函数 write(string)
*/
Template.prototype.render = function(data,out){
if(out == null && data instanceof OutputContext){
var context = data;
}else{
var context = new OutputContext(data,out);
}
context.template = this;
var ctl = context.taglib;
context.taglib = new StackMap(this.taglib);
for(var n in ctl){
context.taglib[n] = ctl[n];
}
context.output(this.doc);
}
/**
* 值栈对象
*/
function ValueStack(data){
this.context = data;
this.stack = [];
}
/**
* 压入新的上下文根
*/
ValueStack.prototype.push = function(data){
this.stack.push(this.context);
this.context = new StackMap(this.context);
for(var n in data){
this.context[n] = data[n];
}
}
/**
* 弹出顶层上下文根
*/
ValueStack.prototype.pop = function(){
this.context = this.stack.pop();
}
/**
* 在上下文对象上设置一个变量
*/
ValueStack.prototype.setVariable = function(id,value){
this.context[id] = value
}
/**
* 在上下文对象上获取一个变量
*/
ValueStack.prototype.getVariable = function(id){
return this.context[id];
}
/**
* 输出上下文对象
* @protected
* @param data <Object> 数据集合
* @param out <Writer|Document> 输出接口 至少需要一个成员函数 write(string)
*/
function OutputContext(data,out){
if(data == null){
data = {};
}
this.taglib = {};
this.valueStack = new ValueStack(data);
this.out = out;
if(out.writeln){
this.writeln = this.println = this.nativeWriteln;
}
this.depth = 0;
}
/**
* @public
*/
OutputContext.prototype.putTaglib = Template.prototype.putTaglib;
/**
* @public
*/
OutputContext.prototype.print = OutputContext.prototype.write = function(str){
this.out.write(str)
}
/**
* @public
*/
OutputContext.prototype.writeln = OutputContext.prototype.println = function(str){
this.print(str);
this.print('\r\n');
}
/**
* @private
*/
OutputContext.prototype.nativeWriteln = function(str){
this.out.writeln(str);
}
/**
* @private
*/
OutputContext.prototype.printIndent = function(str){
return ;
this.out.write("\r\n");
for(var i = 0;i<this.depth;i++){
this.out.write(" ");
}
}
/**
* 计算表达式
* @protected
*/
OutputContext.prototype.evalExpression = function(el,showError){
try{
with(this.valueStack.context){
return eval(el);
}
}catch(e){
return this.processException(e);
}
}
/**
* 处理表达式计算时发生的异常
* @protected
* @param <Error> e 异常对象
* @return <string> 异常后显示的字符串
*/
OutputContext.prototype.processException = function(e){
$log.debug('expression eval error:',e);
return '';
}
/**
* 计算boolean值
* @protected
*/
OutputContext.prototype.evalBoolean = function(str){
if(str){
switch(str.toLowerCase()){
case 'true':
return true;
case 'false':
return false;
}
try{
str = this.evalText(str);
if(str == '' || (str.toLowerCase())=='false'){
return false;
}else{
return true;
}
}catch(e){
return null;
}
}else{
return null;
}
}
/**
* 计算带表达式的字符块
* @protected
* @param <string>str 需要计算的字符块
*/
OutputContext.prototype.evalText = function(str){
var k = 0;
var result = "";
if(!str){
return str;
}
while(true){
var i = str.indexOf("${",k);
while(str.charAt(i-1) == '\\'){
result += str.substring(k,i-1);
k = i;
i = str.indexOf("${",k+1);
}
if(i>=0){
var j = str.indexOf('}',i);
var x = str.indexOf('{',i+2);
if(x>i && x<j){
for(var d = 1,j = i+2;j<str.length;j++){
var c = str.charAt(j);
if(c == '\'' || c == '\"'){//跳过字符串
while(j<str.length){
j = str.indexOf(c,j+1);
for(var n = j-1;str.charAt(n) == '\\'; n--);
if((j - n)%2==1){
break;
}
}
}else if( c == '{'){
d++;
}else if (c == '}'){
d--;
if(d == 0){
break;
}
}
}
}
if(i == 0 && j == (str.length-1)){
var el = str.substring(i+2,j);
return this.evalExpression(el);
}
if(j>0){
var el = str.substring(i+2,j);
if(str[i-1]=='!'){
result += str.substring(k,i-1);
}else{
result += str.substring(k,i);
}
try{
result += this.evalExpression(el);
}catch(e){
//TODO:
}finally{
k = j+1;
//firefox bug for function toString
//continue;
}
continue;
}else{
result += str.substring(k,str.length);
break;
}
}else{
result += str.substring(k,str.length);
break;
}
}
return result;
};
/**
* 编码 xml 字符节点
* @private
*/
OutputContext.prototype.encodeText = function(str){
return str?str.toString()
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/&/g,'&'):'';
};
/**
* 编码 xml 属性
* @private
*/
OutputContext.prototype.encodeAttribute = function(str){
return str?str.toString()
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/&/g,'&'):'';//TODO:'"
};
/**
* 分发节点输出处理
* @private
*/
OutputContext.prototype.getTaglib = function(ns){
if(ns){
return this.taglib[ns] || this.taglib['*'];
}else{
return this.taglib['*'];
}
}
/**
* 分发节点输出处理
* @private
*/
OutputContext.prototype.output = function(node){
if(node==null){return;}
var taglib = this.getTaglib(node.namespaceURI);
switch(node.nodeType){
case 1: //NODE_ELEMENT
taglib.$Element(this,node)
break;
case 3: //NODE_TEXT
taglib.$Text(this,node)
break;
case 4: //NODE_CDATA_SECTION
taglib.$CDATASection(this,node)
break;
case 5: //NODE_ENTITY_REFERENCE
this.$EntityReference(this,node)
break;
case 6: //NODE_ENTITY
taglib.$Entity(this,node)
break;
case 7: //NODE_PROCESSING_INSTRUCTION
taglib.$ProcessingInstruction(this,node)
break;
case 8: //NODE_COMMENT
taglib.$Comment(this,node)
break;
case 9: //NODE_DOCUMENT
taglib.$Document(this,node)
break;
case 10://NODE_DOCUMENT_TYPE
taglib.$DocumentType(this,node)
break;
case 11://NODE_DOCUMENT_FRAGMENT
taglib.$DocumentFragment(this,node)
break;
case 12://NODE_NOTATION
taglib.$Notation(this,node)
break;
case 2: //NODE_ATTRIBUTE
taglib.$Attribute(this,node)
break;
default:
this.println("<!-- ERROR: UNKNOW nodeType:"+node.nodeType+"-->")
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -