function kTmp(template){     
  this.nl2br=function(v){ return v.replace("\n","<br>"); }
  this.nl2br=function(v){ return v.replace("\n","<br>"); }
  

  this.re_match=new RegExp("\([\$|@|\?|\!|\^]){(.*?)\}","");
  this.re_names=new RegExp("([a-zA-Z_][a-zA-Z_\.0-9]*)","g");
  this.items=new Array();
  
  this.doVars=function(v){
    return v.replace(this.re_names,"datas.$1").replace(/\.datas/g,"");
  };

  this.compile=function(template){
    var i=0;
    var h,m,inner,data;
    var forstack=new Array();
    var fori=0;
    var pos;
    
    template=template.replace(/<_textarea/g,"<textarea").replace(/<\/_textarea/g,"</textarea");
    
    while(1){
      pos=template.search(this.re_match);
      if(pos==-1){
        if(template.length>0) this.items[i++]={type: 0, data: template };
        break;
      }else{
        if(pos>0) this.items[i++]={type: 0, data: template.substr(0,pos) };
        m=template.match(this.re_match);
        if(m[1]=='$'){
          h=m[2].split('/');
          h[0]=this.doVars(h[0]);
          this.items[i++]={type: 1, data: h};  // variable
        }else if(m[1]=='@'){ 
          if(m[2]==''){
            this.items[i++]={type: 3, data: forstack[--fori] }; // endfor
          }else{ 
            forstack[fori++]=i;
            h=m[2].split('/');
            h[0]=this.doVars(h[0]);
            h[1]=this.doVars(h[1]);
            this.items[i++]={type: 2, data: h}; // foreach
          }
        }
        else if(m[1]=='?'){
          if(m[2]=='') this.items[i++]={type: 5}; // endif
          else this.items[i++]={type: 4, data: this.doVars(m[2]) }; // if
        }
        else if(m[1]=='!'){
          this.items[i++]={type: 6}; // else        
        }else if(m[1]=='^'){
          this.items[i++]={type: 7, data: m[2]};
        }
        template=template.substring(pos+m[0].length,template.length);
      }
    }
  };
     
  this.generate=function(datas,p){
    var html="";
    var ifstack=new Array();
    var ifind=0;
    var val;
    var h;
    for(var i=0;i<this.items.length;i++){
      switch(this.items[i].type){
        case 0: // text
          html+=this.items[i].data;
        break;
        case 1: // var
          // alert("val="+this.items[i].data[0]+";");
          eval("val="+this.items[i].data[0]+";");
          for(var j=1;j<this.items[i].data.length;j++) eval("val=this."+this.items[i].data[j]+"(val);");              
          html+=val;
        break;
        case 2: // foreach
          eval(this.items[i].data[1]+"=0;if("+this.items[i].data[0]+".length>0) h=1; else h=0;");
          if(h==0) do i++; while(this.items[i].type!=3);
          
        break;
        case 3: // endfor
           eval("if(++"+this.items[this.items[i].data].data[1]+"<"+this.items[this.items[i].data].data[0]+".length) i=this.items[i].data;");
        break;
        case 4: // if
          eval("if("+this.items[i].data+") ifstack[ifind]=1; else ifstack[ifind]=0;");
          if(ifstack[ifind]==0){
            h=0;
            while(true){
              i++;
              if(this.items[i].type==4) h++;
              else if(this.items[i].type==5){ 
                if(h>0) h--; else break;
              }
              else if(this.items[i].type==6 && h==0) break;
            }
            i--;
          }
          ifind++;
        break;
        case 5: // endif
          ifind--;
        break;
        case 6: // else  
          if(ifstack[ifind-1]==1){
            h=1;
            while(h>0){
              i++;
              if(this.items[i].type==4) h++;
              else if(this.items[i].type==5) h--;
            }
            i--;
          }
        break;
        case 7: // embed
          if(p) html+=p.gen(this.items[i].data,datas);
        break;
      }
    }
    return html;
  }
  
  if(template) this.compile(template);
};

function kTmpArray(t){
  this.template=t;
  this.newLineStr="THIS_IS_A_NEW_LINE_THAT_SOMETIMES_HAPPENS";
  this.items=new Array(); 
  this.re=new RegExp("_\{(.*?)\}(.*?)_\{\}","");
  
  this.compile=function(template){
    template=template.replace(/[\n|\r]/g,this.newLineStr);  
    var elms;
    while((elms=this.re.exec(template))!=null){
      this.items[elms[1]]=new kTmp(elms[2].replace(new RegExp(this.newLineStr,"g"),"\n"));   
      template=template.substring(template.search(this.re)+elms[0].length,template.length);
    }                       
  }
  
  this.gen=function(name,datas){
    if(datas==null) datas={};
    return this.items[name].generate(datas,this);
  }
  
  if(this.template) this.compile(this.template);
}

if(kHTTP){
  function kTmpAjax(url){
    var tmp=new kTmp();
    var ajax=new kHTTP.ajax(url,function(d){tmp.compile(d);},0,0,false); 
    delete ajax;
    return tmp;
  }
  function kTmpArrayAjax(url){
    var tmp=new kTmpArray();
    var ajax=new kHTTP.ajax(url,function(d){tmp.compile(d);},0,0,false); 
    delete ajax;
    return tmp;
  }
}

