function Tplate(htmlsrc,datasrc,sep1,sep2) {
 if(!sep1)this.sep1='{';else this.sep1=sep1;if(!sep2)this.sep2='}';else this.sep2=sep2;this.sepl=this.sep1.length;
 if(this.sepl!=this.sep2.length)alert('Different separator lengths');this.dat=eval(datasrc);this.el=document.getElementById(htmlsrc);
 this.tx=this.el.innerHTML;this.tx1=this.tx.indexOf('<!--');this.tx2=this.tx.lastIndexOf('-->');this.instr=this.tx.substr((this.tx1+4),(this.tx2-this.tx1-4));
 this.go=function(ndt){if(ndt)this.dat=eval(ndt);this.el.innerHTML=this.tx.substr(0,this.tx1)+this.interp(this.instr,this.dat)+this.tx.substr(this.tx2+3);} 
 this.get=function(ary){var ct=ary.length;var dt=this.dat;for(i=0;i<ct;i++){dt=dt[ary[i]];if(typeof(dt)=="undefined")return false;}return unescape(dt);}
 this.interp=function(tx,data,ctr) {
 var r=this.enz(tx);var outp=r[0];if(r[2]==-1){alert(r[1]);}else{if(r[1]){switch(r[1].charAt(0)){
 case '@' : var ct=data.length;if(ct){for(var i=0;i<ct;i++){outp+=this.interp(r[1].substr(1),data[i],i);}}else{var i=0;for(var x in data){outp+=this.interp(r[1].substr(1),data[x],i++);}}break;
 case '%' : var en=r[1].indexOf("%",1);var v=r[1].substring(1,en);if(data[v].length==null||data[v].length>0)outp+=this.interp(r[1].substr(en+1),data[v],v);break;	
 case '/' : var en=r[1].indexOf("/",1);if(ctr%2==0)outp+=this.interp(r[1].substring(1,en),data[v],i);
 else outp+=this.interp(r[1].substr(en+1),data[v],i);break;	
 case '?' : var en=r[1].indexOf("?",1);var v=r[1].substring(1,en);
 if(r[2].substr(0,1)=='|'){var t=this.enz(r[2]);r[2]=t[2];if(data[v]&&(data[v]!='%a0')&&(data[v]!='0'))outp+=this.interp(r[1].substr(en+1),data,ctr);
 else outp+=this.interp(t[1],data,ctr);}else{if(data[v]&&(data[v]!='%a0')&&(data[v]!='0'))outp+=this.interp(r[1].substr(en+1),data,ctr);}break;	
 case '!' : var en=r[1].indexOf("!",1);var v=this.interp(r[1].substring(1,en),data,ctr);
 if(r[2].substr(0,1)=='|'){var t=this.enz(r[2]);r[2]=t[2];if(eval(v))outp+=this.interp(r[1].substr(en+1),data,ctr);
 else outp+=this.interp(t[1],data,ctr);}else{if(eval(v))outp+=this.interp(r[1].substr(en+1),data,ctr);}break;	
 case '*' : var en=r[1].indexOf("*",1);var v=this.interp(r[1].substring(1,en),data,ctr);
 if(r[2].substr(0,1)=='|'){var t=this.enz(r[2]);r[2]=t[2];if(eval(v))outp+=this.interp(r[1].substr(en+1),data,ctr);
 else outp+=this.interp(t[1],data,ctr);}else{if(eval(v))outp+=this.interp(r[1].substr(en+1),data,ctr);}break;	
 case '$' : if(r[1].charAt(1)=="["){var ary=[];while(r[1].charAt(1)=="["){var en=r[1].indexOf("]",1);ary[ary.length]=r[1].substring(2,en);
 r[1]=r[1].substr(en);}outp+=unescape(this.get(ary));}else{if(data[r[1].substr(1)]!='%a0'){outp+=unescape(data[r[1].substr(1)]);}}
 break;	
 case '+' : var ct=data.length;var sm=0;for(var i=0;i<ct;i++){sm+=parseInt(eval(this.interp(r[1].substr(1),data[i],i)));}outp+=sm;break;
 case '=' : outp+=eval(this.interp(r[1].substr(1),data,ctr));break;
 case '#' : outp+=ctr;break;
 case 'b' : outp+=fst_nl2br(this.interp(r[1].substr(1),data,ctr));break;
 case 'd' : outp+=fst_date(this.interp(r[1].substr(1),data,ctr));break;
 case 't' : outp+=fst_date(this.interp(r[1].substr(1),data,ctr),true);break;
 case 'm' : outp+=fst_cur2(this.interp(r[1].substr(1),data,ctr));break;
 case '.' : break;
 default : alert('Syntax error: '+r[1]);}}if(r[2])outp += this.interp(r[2],data,ctr);}return outp;}
 this.enz=function(tx){tx=unescape(tx);var l=tx.length; var r=[]; var beg=tx.indexOf(this.sep1);
 if(beg>-1){r[0]=tx.substring(0,beg); var lvl=1; var tmp=beg+this.sepl;
 while(lvl>0&&tmp<l){var st2=tx.indexOf(this.sep1,tmp); var en2=tx.indexOf(this.sep2,tmp);
 if(st2<0){if(en2<0){return [tx,'No clause end',-1];}else{lvl--; tmp = en2+this.sepl;}}
 else{if(st2>en2){lvl--; tmp=en2+this.sepl;}else{lvl++; tmp=st2+this.sepl;}}}
 return [tx.substring(0,beg),tx.substring(beg+this.sepl,tmp-this.sepl),tx.substring(tmp)];}
 else{return [tx.substring(tmp),'',''];}}}