function infraTabelaDinamica(idTabela, idHidden, bolAlterar, bolRemover){
  
  var me = this;
  this.tbl = infraGetElementById(idTabela);
  this.hdn = infraGetElementById(idHidden);
  this.ths = this.tbl.getElementsByTagName("th");
  this.alterar = null;
  this.remover = null;
  this.flagRemover = bolRemover;
  this.flagAlterar = bolAlterar;
  this.gerarEfeitoTabela = false;
  this.colunaAcoes = 0;
  this.exibirMensagens = true;
  
  
  var dadosIniciais = this.hdn.value;
  this.hdn.value = '';

  this.lerCelula = function(celula){
    var ret = null;
    var div = celula.getElementsByTagName('div');
    if (div.length==0){
      ret = celula.innerHTML;
    }else{
      ret = div[0].innerHTML;
    }
    return ret.infraReplaceAll('<br>','<br />');
  }
  
  this.adicionar = function(arrColunas){
    var i, j, strLinha, objLinha, arrLinha, numColunas, arrCol, strDados;
    
    numColunas = me.ths.length;
    
    
    for(i=0;i<arrColunas.length;i++){
      if (arrColunas[i] == null){
        arrColunas[i] = 'null';
      }
    }
    
    
    //Se tem dados sobre outras linhas e a linha atual tem ID
    if (me.hdn.value != '' && arrColunas[0] != 'null'){	  	
    	
      //Procura por uma linha com o mesmo ID
      for(i=0;i<me.tbl.rows.length;++i){
        //alert('[' + String(infraTrim(me.lerCelula(me.tbl.rows[i].cells[0]))) + ']=[' + String(infraTrim(arrColunas[0]))+ ']');
    		if (String(infraTrim(me.lerCelula(me.tbl.rows[i].cells[0])))==String(infraTrim(arrColunas[0]))){

    		  //alert('aqui');
    		  //Se não é permitida alteração
    		  if (!me.flagAlterar){
    		    if (me.exibirMensagens){
    		      alert('Este item já foi adicionado.');
    		    }
    		    return;
    		  }
    		  
    		  //Monta dados do item para localizar no hidden
    		  strLinha = ''; 
          for(j=0;j<me.tbl.rows[i].cells.length-me.colunaAcoes;j++){
            if (j>0){
              strLinha = strLinha.concat('±');
            }
            var celula = me.lerCelula(me.tbl.rows[i].cells[j]);
            strLinha = strLinha.concat(celula);
          }
          
          //alert("Linha:" + strLinha + "\nHidden:[" + me.hdn.value + "]");
          
          me.removerLinhaHidden(strLinha);
          
          //Monta nova linha hidden
    		  strLinha = ''; 
          for(j=0;j<arrColunas.length;j++){
            if (j>0){
              strLinha = strLinha.concat('±');
            }
            strLinha = strLinha.concat(arrColunas[j]);
          }
          me.adicionarLinhaHidden(strLinha);

          //Atualiza tabela
          for(j=0;j<me.tbl.rows[i].cells.length-me.colunaAcoes;j++){
            
      	    if (me.ths[j].align!=''){
      	      alinhamento = 'text-align:'+me.ths[j].align;
      	    }
            
            if (arrColunas[j]=='null'){
              me.tbl.rows[i].cells[j].innerHTML = '<div style="visibility:hidden;'+ alinhamento + '">null</div>';
            }else{
              me.tbl.rows[i].cells[j].innerHTML = '<div style="'+ alinhamento +'">'+arrColunas[j]+'</div>';
            }
          }
          
          if (me.exibirMensagens){
            alert('Item alterado.');
          }
          
    		  return;
    		}
    	}
    }
    
   
    //objLinha = me.tbl.insertRow(me.tbl.rows.length);
    objLinha = me.tbl.insertRow(1);
    
    arrCol = [];
    strDados = '';
    
  	//INCLUI LINHA
  	if (me.gerarEfeitoTabela){
  	  objLinha.onmouseover=function(){this.className='infraTrSelecionada'};
  	}

  	var trs = me.tbl.getElementsByTagName('tr');
  	
    var trClass = 'infraTrClara';
    
    for(i=1;i<trs.length;i++){
      
      trs[i].className = trClass;
      
      if (trClass=='infraTrEscura'){
        trClass = 'infraTrClara';
        if (me.gerarEfeitoTabela){
          trs[i].onmouseout=function(){this.className='infraTrEscura'};
        }
      }else{
        trClass = 'infraTrEscura';
        if (me.gerarEfeitoTabela){
          trs[i].onmouseout=function(){this.className='infraTrClara'};
        }
      }
    }
    
    
    //insere demais dados
    for (i=0;i<numColunas-me.colunaAcoes;i++){
  	  arrCol[i] = objLinha.insertCell(i);
   	  arrCol[i].style.display = me.ths[i].style.display;
  	  arrCol[i].className = 'infraTd';
  	  if (arrColunas[i]!='null'){
  	    var alinhamento = '';
  	    if (me.ths[i].align!=''){
  	      alinhamento = 'style="text-align:'+me.ths[i].align+';"';
  	    }
  	    arrCol[i].innerHTML = '<div ' + alinhamento + '>'+arrColunas[i]+'</div>';
  	  }else{
  	    arrCol[i].innerHTML = '<div style="visibility:hidden">null</div>';
  	  }

  	  if (i>0){
  	    strDados += '±';
  	  }
  	  strDados += arrColunas[i];
    }
  

    if (me.colunaAcoes==1){
      var colAcoes = objLinha.insertCell(numColunas-1);
      colAcoes.align='center';
      colAcoes.vAlign='top';    
    }
      
    
    //insere coluna de ações
    if (me.flagAlterar || me.flagRemover){
      if (me.colunaAcoes==1){
        if ( me.flagAlterar && arrColunas[0] != null){
          me.adicionarAcaoAlterar(colAcoes);
          me.adicionarEspaco(colAcoes);
        }
        
        if ( me.flagRemover ){
          me.adicionarAcaoRemover(colAcoes);
        }
      }
    }
    me.adicionarLinhaHidden(strDados);
    infraAtualizarCaption(me.tbl);
  }

  this.recarregar = function(){
    var dados = me.hdn.value;
    me.limpar();
    me.inicializar(dados);
  }
  
  this.limpar = function(){
    me.hdn.value = '';
    
    var numLinhas = me.tbl.rows.length;
    var numLinhaInicial = 0;

    if (INFRA_XHTML == 0){
      numLinhas--;
      numLinhaInicial = 1;
    }
    
    for(var i=0;i<numLinhas;i++){
      me.tbl.deleteRow(numLinhaInicial);
    }
  }
  
  this.inicializar = function (dados){
    
    var numColunas = me.ths.length;

    if (numColunas==0){
      alert('Cabeçalho da tabela não encontrado. ['+me.tbl.id+']');
      return;
    }
    
    if (infraTrim(me.ths[numColunas-1].innerHTML.toLowerCase()) != 'ações'){
      me.colunaAcoes = 0;
    }else{
      me.colunaAcoes = 1;
    }
  
    if (dados!=''){  
      var arrLinhas = dados.split('¥');
  	  for(var j=0;j<arrLinhas.length;j++){
  	    var arrColunas = arrLinhas[j].split('±');
  	    me.adicionar(arrColunas);
  	  }
    }
  }

  if (window.attachEvent) { //Limpar as referências do IE
    window.attachEvent("onunload", function(){
      me.tbl = null;
      me.hdn = null;
      me.ths = null;
      me.alterar = null;
      me = null;
      
    });
    
  }
  
  this.adicionarAcaoAlterar = function(coluna){
    var imgAlterar = document.createElement('img');
    imgAlterar.src = '/infra_css/imagens/alterar.gif';
    imgAlterar.title = 'Alterar Item';
    imgAlterar.caption = 'Alterar Item';  
    //imgAlterar.className = 'infraImgNormal';
    imgAlterar.onclick = function(){
      me.alterarLinha(this.parentNode.parentNode.rowIndex);
    }
    coluna.appendChild(imgAlterar);
  }
  
  this.adicionarEspaco = function(coluna){
    var imgEspaco = document.createElement('img');
    imgEspaco.src = '/infra_css/imagens/espaco.gif';
    coluna.appendChild(imgEspaco);
  }
  
  this.adicionarAcaoRemover = function(coluna){
    var imgRemover = document.createElement('img');
    imgRemover.src = '/infra_css/imagens/remover.gif';
    imgRemover.title = 'Remover Item';
    imgRemover.caption = 'Remover Item';  
    imgRemover.onclick = function(){
      me.removerLinha(this.parentNode.parentNode.rowIndex);
    }
    coluna.appendChild(imgRemover);
  }
  
  this.removerLinhaHidden = function(linha){
    //Remove dados anteriores
    var temp = infraRemoverFormatacaoXML(linha);
    
    var arrDados = me.hdn.value.split('¥');
    var tmp = '';
    for(var i=0;i<arrDados.length;i++){
      if (arrDados[i] != temp){
        if (tmp != ''){
          tmp += '¥';
        }
        tmp += arrDados[i];
      }
    }
    me.hdn.value = tmp;
  }
  
  this.adicionarLinhaHidden = function(linha){
    var dados = me.hdn.value;
    if (dados.length>0){
      dados = dados.concat('¥');
    }
    dados = dados.concat(linha);  
    me.hdn.value = dados;
  }
  
  
  this.obterItens = function(){
  	
    var ret = Array();
    var arrLinhas = null;
    var arrColunas = null;
    var i;
    var s = infraTrim(me.hdn.value);
  	
    if (s!=''){	  	
    	arrLinhas = s.split('¥');
    	for(i=0; i<arrLinhas.length;i++){
    		arrColunas = arrLinhas[i].split('±');	  			  		
    		ret[i] = arrColunas;
    	}
    }	
  	return ret;
  }
  
  this.alterarLinha = function(rowIndex){
    var i;
    var arrLinha = Array();
    numColunas = me.tbl.rows[rowIndex].cells.length - 1;
    for(i=0;i<numColunas;i++){
       arrLinha[i] = me.lerCelula(me.tbl.rows[rowIndex].cells[i]);
    }
    if (me.alterar!=null){
      me.alterar(arrLinha);
    }  
  }
  
  this.removerLinha = function(rowIndex){
    var numColunas = 0;
    
    if (me.remover!=null){
      
      var arrLinha = Array();
      numColunas = me.tbl.rows[rowIndex].cells.length - 1;
      for(i=0;i<numColunas;i++){
         arrLinha[i] = me.lerCelula(me.tbl.rows[rowIndex].cells[i]);
      }
      
      if (!me.remover(arrLinha)){
        return;
      }
    }
    
    var i;
    var strLinha = '';
    numColunas = me.tbl.rows[rowIndex].cells.length - 1;
    for(i=0;i<numColunas;i++){
      if (i>0){
        strLinha = strLinha.concat('±');
      }
      var celula = me.lerCelula(me.tbl.rows[rowIndex].cells[i]);
      strLinha = strLinha.concat(celula);
    }
    
    me.removerLinhaHidden(strLinha);
    me.tbl.deleteRow(rowIndex);
    for(i=rowIndex;i<me.tbl.rows.length;i++){
      if ( me.tbl.rows[i].className =='infraTrClara'){
        me.tbl.rows[i].className='infraTrEscura';
        if (me.gerarEfeitoTabela){
          me.tbl.rows[i].onmouseout=function(){this.className='infraTrEscura'};
        }              
      }else{
        me.tbl.rows[i].className='infraTrClara';
        if (me.gerarEfeitoTabela){
          me.tbl.rows[i].onmouseout=function(){this.className='infraTrClara'};
        }              
      }      
    }
    infraAtualizarCaption(me.tbl);
  }

  this.adicionarAcoes = function(id, acoes, bolAlterar, bolRemover) {
    
    if (me.colunaAcoes==0){
      alert('Coluna de ações não encontrada.');
      return;
    }
    
    numLinhaInicial = 0;
    if (INFRA_XHTML == 0){
      numLinhaInicial = 1;
    }

    
    var linha = null;
    for(var i=numLinhaInicial;i<me.tbl.rows.length;i++){
      
      if (String(me.lerCelula(me.tbl.rows[i].cells[0])) == String(id)){
        linha = i;
        break;
      }
    }
    
    if (linha==null){
      //alert('ID '+id+' não encontrado.');
      return;
    }
    
    var numColunaAcoes = me.tbl.rows[linha].cells.length-1;
    var colAcoes = me.tbl.rows[linha].cells[numColunaAcoes];

    if (acoes!=undefined && acoes != ''){
      var imgs = colAcoes.getElementsByTagName("img");
      
      var div = document.createElement('div');
      div.style.display='inline';
      div.innerHTML = acoes;
      
      if (imgs.length>0){
        colAcoes.insertBefore(div,imgs[0]);
      }else{
        colAcoes.appendChild(div);  
      }
  
      
      var imgs = colAcoes.getElementsByTagName("img");
      
      for(var i=0; i<imgs.length;i++){
        imgs[i].className = '';
        imgs[i].setAttribute("border","0");
      }
    }

    if (bolAlterar!=undefined && bolAlterar){
      me.adicionarAcaoAlterar(colAcoes);
    }
    
    if (bolRemover!=undefined && bolRemover){
      me.adicionarAcaoRemover(colAcoes);
    }
  }

  this.inicializar(dadosIniciais);
}

