Jump to content

klonder

Members
  • Content count

    969
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by klonder


  1. Olá a todos!

    Estou há 3 dias pesquisando sobre como assinar digitalmente um arquivo pdf com Python, porém nenhuma proposta funcionou no Python 3.8.

     

    O meu problema consiste no seguinte:

    Crio contratos no word e salvo no formato PDF em uma pasta.

    O que eu preciso é criar um aplicativo em Python que abra um arquivo pdf já criado e assine-o digitalmente através de um Certificado Digital pfx. Essa assinatura deveria ser inserida no final de cada documento. Já tentei várias ferramentas, porém nenhuma funcionou no Python 3.8. Alguém tem conhecimento sobre o assunto, utiliza, ou saberia dar alguma dica? Obrigado!


  2. Aproveitando o exemplo acima, deixo outra possibilidade para controle de eventos focusIn/focusOut. Com o método focusChanged signal of QApplication, foi necessário fazer algumas adaptações, mas deixei o código comentado para facilitar a referência:

     

    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QComboBox, QLineEdit, QCompleter
    from PyQt5.QtCore import QSize, Qt, QSortFilterProxyModel, QStringListModel
    
    class Ui_Autocomplete(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.setGeometry(300, 200, 800, 600)
            self.setWindowTitle('Autocomplete com combobox')
      
            self.cboxEstado = QComboBox(self)
            self.cboxEstado.move(50, 50)
            self.cboxEstado.addItem("Acre")
            self.cboxEstado.addItem("Amazonas")
            self.cboxEstado.addItem("Amapá")
            self.cboxEstado.addItem("Pará")
            self.cboxEstado.addItem("Rondônia")
            self.cboxEstado.addItem("Roraima")
            self.cboxEstado.addItem("Tocantins")
    
            self.cboxEstado.addItem("Distrito Federal")
            self.cboxEstado.addItem("Goiás")
            self.cboxEstado.addItem("Mato Grosso")
            self.cboxEstado.addItem("Mato Grosso do Sul")
    
            self.cboxEstado.addItem("Alagoas")
            self.cboxEstado.addItem("Bahia")
            self.cboxEstado.addItem("Ceará")
            self.cboxEstado.addItem("Maranhão")
            self.cboxEstado.addItem("Piauí")
            self.cboxEstado.addItem("Pernambuco")
            self.cboxEstado.addItem("Paraíba")
            self.cboxEstado.addItem("Rio Grande do Norte")
            self.cboxEstado.addItem("Sergipe")
    
            self.cboxEstado.addItem("Paraná")
            self.cboxEstado.addItem("Rio Grande do Sul")
            self.cboxEstado.addItem("Santa Catarina")
    
            self.cboxEstado.addItem("Espírito Santo")
            self.cboxEstado.addItem("Minas Gerais")
            self.cboxEstado.addItem("São Paulo")
            self.cboxEstado.addItem("Rio de Janeiro")
            
            self.cboxEstado.setEditable(True)
            self.cboxEstado.completer().setCompletionMode(QCompleter.PopupCompletion)
            self.cboxEstado.completer().setFilterMode(Qt.MatchContains)
            self.cboxEstado.completer().setCaseSensitivity(QtCore.Qt.CaseInsensitive)
            #self.cboxEstado.focusOutEvent = self.pedeuFoco
            QtWidgets.qApp.focusChanged.connect(self.on_focusChanged)
            
            self.leRegiao = QLineEdit(self)
            self.leRegiao.move(250,50)
            self.leRegiao.resize(200, 22)
    
            
        def on_focusChanged(self, old, now):
            if now == self.leRegiao:
                self.leRegiao.setText(self.cboxEstado.currentText())
    
            if old == self.cboxEstado:
                occur = 0
                for i in range(len(self.cboxEstado)):
                    if self.cboxEstado.currentText() == self.cboxEstado.itemText(i):
                        occur = occur+1
                if occur == 0:
                    self.leRegiao.setText("")
                    self.cboxEstado.lineEdit().setFocus()
                    self.cboxEstado.lineEdit().selectAll()
                #else:
                    #Retira o cursor do widget
                    #QComboBox.focusOutEvent(self.cboxEstado,event)
    
                
        #def pedeuFoco(self,event):
            #occur = 0
            #for i in range(len(self.cboxEstado)):
                #if self.cboxEstado.currentText() == self.cboxEstado.itemText(i):
                    #occur = occur+1
            #if occur == 0:
                #self.cboxEstado.lineEdit().setFocus()
                #self.cboxEstado.lineEdit().selectAll()
            #else:
                ##Retira o cursor do widget
                #QComboBox.focusOutEvent(self.cboxEstado,event)
            
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        mainWin = Ui_Autocomplete()
        mainWin.show()
        sys.exit(app.exec_())

     

     

     

     


  3. Olá a todos(as)!

    Estava há 3 dias pesquisando sobre como resolver um problema que estava enfrentando em meu sistema, que consistia no seguinte:

    Implantar um Combobox com dados vindos do banco. Esse combobox deveria ser editável e apresentar os valores em seu popup suspenso. À medida em que o usuário fosse digitando, o autocomplete faria a busca em todos os valores já cadastrados e mostraria os compatíveis (procedimento até então comum em qualquer autocomplete). Todavia, o combobox só poderia perder o foco caso o texto inserido fosse exatamente igual a um dos valores existentes no popup, ou seja, não poderia ser  inserido nada que já não estivesse cadastrado anteriormente e presente na lista de valores.

    Após muito pesquisar, cheguei a um resultado muito satisfatório que compartilho com vocês, visto que varri a internet inteira à procura desse código e não encontrei em lugar nenhum. PyQt5 é extremamente pobre em tutoriais, principalmente em português.

     

    Segue o código que poderá ajudar quem precise:

    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QComboBox, QLineEdit, QCompleter
    from PyQt5.QtCore import QSize, Qt, QSortFilterProxyModel, QStringListModel
    
    class Ui_Autocomplete(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.setGeometry(300, 200, 800, 600)
            self.setWindowTitle('Autocomplete com combobox')
      
            self.cboxEstado = QComboBox(self)
            self.cboxEstado.move(50, 50)
            self.cboxEstado.addItem("Acre")
            self.cboxEstado.addItem("Amazonas")
            self.cboxEstado.addItem("Amapá")
            self.cboxEstado.addItem("Pará")
            self.cboxEstado.addItem("Rondônia")
            self.cboxEstado.addItem("Roraima")
            self.cboxEstado.addItem("Tocantins")
    
            self.cboxEstado.addItem("Distrito Federal")
            self.cboxEstado.addItem("Goiás")
            self.cboxEstado.addItem("Mato Grosso")
            self.cboxEstado.addItem("Mato Grosso do Sul")
    
            self.cboxEstado.addItem("Alagoas")
            self.cboxEstado.addItem("Bahia")
            self.cboxEstado.addItem("Ceará")
            self.cboxEstado.addItem("Maranhão")
            self.cboxEstado.addItem("Piauí")
            self.cboxEstado.addItem("Pernambuco")
            self.cboxEstado.addItem("Paraíba")
            self.cboxEstado.addItem("Rio Grande do Norte")
            self.cboxEstado.addItem("Sergipe")
    
            self.cboxEstado.addItem("Paraná")
            self.cboxEstado.addItem("Rio Grande do Sul")
            self.cboxEstado.addItem("Santa Catarina")
    
            self.cboxEstado.addItem("Espírito Santo")
            self.cboxEstado.addItem("Minas Gerais")
            self.cboxEstado.addItem("São Paulo")
            self.cboxEstado.addItem("Rio de Janeiro")
            
            self.cboxEstado.setEditable(True)
            self.cboxEstado.completer().setCompletionMode(QCompleter.PopupCompletion)
            self.cboxEstado.completer().setFilterMode(Qt.MatchContains)
            self.cboxEstado.completer().setCaseSensitivity(QtCore.Qt.CaseInsensitive)
            self.cboxEstado.focusOutEvent = self.pedeuFoco
    
            self.leRegiao = QLineEdit(self)
            self.leRegiao.move(250,50)
            self.leRegiao.resize(200, 22)
    
        def pedeuFoco(self,event):
            occur = 0
            for i in range(len(self.cboxEstado)):
                if self.cboxEstado.currentText() == self.cboxEstado.itemText(i):
                    occur = occur+1
            if occur == 0:
                self.cboxEstado.lineEdit().setFocus()
                self.cboxEstado.lineEdit().selectAll()
            else:
                #Retira o cursor do widget
                QComboBox.focusOutEvent(self.cboxEstado,event)
            
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        mainWin = Ui_Autocomplete()
        mainWin.show()
        sys.exit(app.exec_())

     

     


  4. Boas galera!

    Vou deixar aqui um código que acabei de criar de um método que recebe a data de nascimento em formato de string e retorna a idade. Eu tinha esse código em JAVA, fiz umas melhorias e adaptei para Python, para o novo sistema que estou desenvolvendo.

    Deixo aí para quem precisar e também para minhas pesquisas futuras:

    O método retorna a idade no padrão: AAa | AAa MMm | AAa MMm DDd, exemplos: 38a | 38a 14m | 38a 14m 5d

    Deixei o parâmetro "tipo" podendo receber "a", "m", "d" apenas para facilitar a referência a "anos", "meses" e "dias", mas sintam-se à vontade para alterar depois!

    Boa sorte!

    from datetime import datetime,date
    
    
    def calcularIdade(self,dtYYYYMMDD,tipo):
            #dtYYYYMMDD: string de data no formato YYYY-MM-DD (exemplo: padrão SQL)
            #tipo: Pode receber "a","m","d" -> a: retorna YYa | m: retorna YYa MMd | d: retorna YYa MMm DDd
    
            dtDN = datetime.strptime(dtYYYYMMDD, '%Y-%m-%d').date()
            dtHoje = date.today()
    
            anoNasc = int(dtDN.strftime('%Y'))
            anoHoje = int(dtHoje.strftime('%Y'))
            mesNasc = int(dtDN.strftime('%m'))
            mesHoje = int(dtHoje.strftime('%m'))
            diaNasc = int(dtDN.strftime('%d'))
            diaHoje = int(dtHoje.strftime('%d'))
            dtNiver = datetime.strptime(str(anoHoje)+"-"+str(mesNasc)+"-"+str(diaNasc), '%Y-%m-%d').date()
    
            diffAnos = anoHoje-anoNasc
            diffMeses = mesHoje-mesNasc        
            diffDias = diaHoje-diaNasc
    
            if dtHoje<dtNiver:#Ainda não fez aniversário esse ano!
                diffAnos = anoHoje-anoNasc-1#Corrigindo o ano, pois ainda não fez aniversário
                diffMeses = 12+diffMeses#Corrigindo os meses/diffMeses é negativo!!!
    
            if diaHoje < diaNasc:#O mês ainda não virou
                diffMeses = diffMeses-1                        
                #Para o cálculo dos dias, é importante avaliar uma série de variáveis: Mês com 28,20,30 ou 31 dias
                mes_anterior_31d = [1,2,4,6,9,11]
                mes_anterior_30d = [5,7,8,10,12]
                if mesHoje in mes_anterior_31d:
                    diffDias = (31-diaNasc)+diaHoje
                elif mesHoje in mes_anterior_30d:
                    diffDias = (30-diaNasc)+diaHoje
                else:
                    if anoHoje%4 == 0:#Cálculos para anos bissextos
                        diffDias = (29-diaNasc)+diaHoje
                    else:#Anos não bissextos
                        diffDias = (28-diaNasc)+diaHoje
    
            if tipo == "a":
                return str(diffAnos)+"a"
            elif tipo == "m":
                return str(diffAnos)+"a "+str(diffMeses)+"m "
            else:
                return str(diffAnos)+"a "+str(diffMeses)+"m "+str(diffDias)+"d"

    Exemplo de chamada:

    print(self.calcularIdade("1981-09-11","d"))

     


  5. Após muita, muita pesquisa, vou deixar um código de um template com 3 colunas verticais, sendo que a coluna do meio responde ao tamanho da janela e as laterais podem responder ao tamanho ou serem fixas (vai do gosto do desenvolvedor). Há também a possibilidade de alterar rapidamente a posição entre as colunas laterais, bastando alterar o float de cada uma delas, sem mexer na marcação.

    Motivo do post: Pode ser que ajude alguém com o mesmo problema. Postarei também para minhas consultas futuras.

    Motivo 2: O site do Maujor tem um bom exemplo (https://www.maujor.com/tutorial/qqer-ordem-3colunas.php), porém não consegui manter as colunas laterais fixas. Além disso, para alterar as colunas de lugar é necessário fazer contas, mexer com números, distância dos widths, etc. Não é complexo, mas considerei o código abaixo mais simples, pois basta alterar os floats conforme descrito abaixo. Deixo a referência do site a quem interessar.

    Motivo 3: Ainda no site do Maujor (https://www.maujor.com/layout3col.shtml) há esse exemplo que quase atendeu o meu problema, porém é muito complexo e a maneira que encontrei também considerei mais fácil (já utilizei muito esse esquema em projetos anteriores, porém complica na responsividade).

    Motivo 4: Principal referência que resolveu todos os meus problemas: https://www.richardbarros.com.br/css/css-truques-para-dominar-a-propriedade-float. Esse site foi a "Eureka" para eu deixar exatamente conforme eu queria.

     

    Segue o código:

     

    CSS:

    <style>
    #navGlobal {
    	height:400px;
    }
    #navEsquerda {
        float:left;
        width:250px;/*Está em pixels, mas poderia deixar em porcentagem: ex: 20% */
        background:#FFF;
        height:100%;
    }
    #navDireita {
        /*margin-left:var(--margemEsquerda); Opcional*/
        word-break: break-all; word-wrap: break-word;
    	height:100%;
    }
    #navLinks {
        float:right;
        width:200px;/*Está em pixels, mas poderia deixar em porcentagem: ex: 20% */
        height:100%;
        background:#CCC;    
    }
    #navConteudo {
    	overflow:auto;
    	height:100%;
    	background:#EFEFEF;
    }
    </style>

     

    HTML:

    <div id="navGlobal">
    	<div id="navEsquerda">Menu</div>
    	<div id="navDireita">
    		<div id="navLinks">Links</div>
    		<div id="navConteudo">Conteúdo do meu site</div>
    	</div>
    </div>

    Nos comentários do código, informei o que alterar para manter as colunas laterais fixas ou em porcentagem, bem como para trocá-las de lugar uma lateral com o outra.

    Deixei cores vibrantes como modelo para o usuário alterar depois.

    Abraços a todos(as).


  6. Para resolver acentos no tcpdf, no header e no footer, basta utilizar utf8_encode no texto. Também serve para o código html que retorna da variável.

     

    Ex: utf8_encode('<< MEU TÍTULO >>')

     

    Abaixo um exemplo para a função Footer, para permitir a palavra "Página" na frase "Página x de y".

    public function Footer() {
    $this->SetY(-15);
    $this->SetFont('helvetica', 'I', 8);
    $this->Cell(0, 10,
                utf8_encode('Página'). $this->getAliasNumPage() . ' de ' .
                $this->getAliasNbPages(), 0, false, 'C', 0, '',
                0, false, 'T', 'M');
    }

    Se seu código HTML estiver dentro de uma variável do PHP, como por exemplo $html, basta aplicar a mesma rotina:

    $html = utf8_encode($html);
    $pdf->WriteHTMLCell(192,0,9,'',$html,0,1);

     


  7. Desenvolvo em Java. Tenho sistema pronto para Gerenciamento de Home Care. Gera XML nos padrões TISS, tenho conhecimento de muita coisa relacionada a ANS, guias TISS, XML, XLS. Esse sistema gera prescrições, orçamentos, aditivos, etc.

    Poderia adaptar perfeitamente para clínicas. Ficaria show de bola!

    Caso queira uma demonstração:

    https://youtu.be/PJ3LAtjAmzk


  8. Tentei incluir a máscara a seguir em um POST meu antigo, porém está fechado para novas respostas:

     

    Todavia, para futuras consultas minhas e também para ajudar outras pessoas, venho deixar uma máscara interessante que acabei de terminar em JavaScript.

    Ficou muito menor que a do POST acima:

    <script type="text/javascript">
    var iCount1;
    var trava = false;
    
    function MaskDown(e) {    
        if (trava == false) {
            iCount1 = e.value.length;
            trava = true;
        }
    }
    
    function MaskUp(e,mascara) {
        if (trava) {
            var textoLimpo = e.value.substr(0,iCount1+1).replace(/[\/\:\-\.]/g,"");
            var texto = "";
            
            var iM = 0;
            var iT = 0;
            while (iM < mascara.length) {
                if (iT < textoLimpo.length) {                
                    if (mascara.substr(iM,1) == "#") {
                       texto += textoLimpo.substr(iT,1);
                       iT++;
                    } else {
                        texto += mascara.substr(iM,1);
                    }            
                }
            iM++;           
            }
        e.value = texto;
        trava = false;
        }    
    }
    </script>

    Para funcionar, basta incluir em suas tags input os eventos, como demonstrado a seguir:

    <input type="text" id="tfData" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'##/##/####')" placeholder="dd/mm/aaaa" style="width:80px" />
    <br /><input type="text" id="tfHora" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'##:##')" placeholder="hh:mm"  style="width:50px"/>
        

    À medida que o usuário vai digitando, o valor campo vai sendo formatado. Pode ser usado para CPF, CEP, RG, dentre outros...

     

    Divirtam-se!

    • +1 1

  9. Fiz uma correção no código e esse problema foi corrigido (já corrigi no post acima). Ocorria em algumas situações dependendo da posição do ID. Agora o código acima está funcionando perfeitamente! Só que está funcionando do jeito que está...

    Eu gostaria de saber se seria possível fazer de outra forma, como:

     

    ol_OUTRASDESPESAS.RemoveAll(ol_T)

     


  10. Olá a todos!

    Pesquisei em vários locais, inclusive aqui no fórum, e não encontrei nenhuma resposta sobre a seguinte situação:

    Tenho um TreeTableView que carrega vários itens vindos do Banco de Dados. De acordo com a característica de cada item, eles são divididos em nós previamente especificados (são apenas estes nós pré-estabelecidos).

    Exemplo dos Nós: Materiais, Medicamentos, Taxas, Aluguéis...

     

    Em um determinado momento, preciso imprimir essa TreeTableView, excluindo algumas linhas que são desnecessárias. Quanto à impressão está tudo ok.

    Mas, para ganhar tempo, eu preciso excluir várias linhas de uma vez dessa TreeTableView, apertando o Shift e clicando/selecionando todas as linhas que deverão ser excluídas.

     

    Antes de postar o método que encontrei, vou detalhar como estou fazendo:

    Quando abro a TreeTableView, os dados originados do Banco de Dados são salvos em um ObservableList<itens> ol_OUTRASDESPESAS. Esse ObservableList é então processado e a TreeTableView é criada com cada item em seu nó específico. Preciso então imprimir essa TreeTableView, mas para isso, em alguns casos, preciso excluir várias linhas ao mesmo tempo.

     

    O que estou fazendo:

    Crio uma ObservableList transitória (ol_TEMP) com todas as linhas que estão selecionadas. Criei um laço for que percorre todos os itens da ol_OUTRASDESPESAS e um laço interno que percorre todos os itens da ol_TEMP. Dentro desses laços verifico se existe um ID dentro de ol_TEMP que seja igual ao id de ol_OUTRASDESPESAS. Se os IDs forem iguais, eu excluo o item de ol_OUTRASDESPESAS.

     

    private void excluirItem_OutrasDespesas() {
    	ObservableList<TreeItem<objOutrasDespesas>> ol_T = FXCollections.observableArrayList(ttvOutrasDespesas.getSelectionModel().getSelectedItems());
    	//Percorrendo todos os itens do ol_OUTRASDESPESAS. Se o item atual estiver na lista de excluídos, excluir.
        for (int j = 0; j<ol_T.size(); j++) {
                    for (int i = 0; i<ol_OUTRASDESPESAS.size(); i++) {
                        if (Objects.equals(ol_OUTRASDESPESAS.get(i).getId(), ol_T.get(j).getValue().getId())) {
                            //System.out.println("Removendo: "+ol_OUTRASDESPESAS.get(i).getItem());
                            ol_OUTRASDESPESAS.remove(i);
                        }
                    }
                }
        estruturaBasica();
    }

    estrutura() é apenas uma chamada ao método para reconstruir a TreeTableView.

     

    Essa foi a maneira que encontrei para excluir os itens selecionados, porém não creio que seja a melhor. Sei que em Java existe o método removeAll, porém não consegui aplicar nesse caso.

    A minha dúvida é a seguinte: Existe outra opção melhor do que essa? Consigo evitar todos esses loops necessários para excluir todos os itens selecionados?


  11. Olá a todos(as)! Esse é um assunto bastante discutido, porém não encontrei nenhum tópico com um código menor do que esse que desenvolvi e venho compartilhar com vocês (servindo também para minhas consultas futuras).

     

    Venho deixar um código para máscara (qualquer tipo, com praticamente quaisquer símbolos) em TextField. Nesse caso estou postando para CPF, mas o código pode ser facilmente alterado:

    tfCPF.lengthProperty().addListener((ObservableValue<? extends Number> observableValue, Number number, Number number2) -> {
                String mascara = "###.###.###-##";
                String alphaAndDigits = tfCPF.getText().replaceAll("[\\-\\.]","");
                StringBuilder resultado = new StringBuilder();
                int i = 0;
                int quant = 0;
    
                if (number2.intValue() > number.intValue()) {
                    if (tfCPF.getText().length() <= mascara.length()) {
                        while (i<mascara.length()) {
                            if (quant < alphaAndDigits.length()) {
                                if ("#".equals(mascara.substring(i,i+1))) {
                                    resultado.append(alphaAndDigits.substring(quant,quant+1));
                                    quant++;
                                } else {
                                   resultado.append(mascara.substring(i,i+1));
                                }
                            }
                        i++;    
                        }
                        tfCPF.setText(resultado.toString());
                    }
                    if (tfCPF.getText().length() > mascara.length()) {
                        tfCPF.setText(tfCPF.getText(0,mascara.length()));
                    }    
                } 
            });
    

    Obviamente cada usuário terá uma intenção (deixar apenas números, ou apenas letras, ou números e letras em locais pré-estabelecidos), por isso não adicionei essas condições no código acima. Isso poderá facilmente ser feito com expressões regulares ou com outro tipo de validação.

     

    Para alterar o tipo de máscara, basta alterar o formato da máscara e os caracteres nas variáveis:

    String mascara = "###.###.###-##";
    String alphaAndDigits = tfCPF.getText().replaceAll("[\\-\\.]","");
    

    É isso! Espero que seja útil para alguém! Abraços!


  12. Opa, beleza...

     

    Pessoal, vou então demonstrar mais uma maneira de como criar campos dinamicamente, voltando ao createElement, mas agora incluindo um script em PHP para mostrar como pegar os dados:

     

    Javascript + Formulário em HTML:

    <html>
    <head>
    <script type="text/javascript">
    var qtdeCampos = 0;
    
    function addCampos() {
    var objPai = document.getElementById("campoPai");
    //Criando o elemento DIV;
    var objFilho = document.createElement("div");
    //Definindo atributos ao objFilho:
    objFilho.setAttribute("id","filho"+qtdeCampos);
    
    //Inserindo o elemento no pai:
    objPai.appendChild(objFilho);
    //Escrevendo algo no filho recém-criado:
    document.getElementById("filho"+qtdeCampos).innerHTML = "<input type='text' id='campo"+qtdeCampos+"' name='campo[]' value='Campo com id: "+qtdeCampos+"'> <input type='button' onClick='removerCampo("+qtdeCampos+")' value='Apagar campo'>";
    qtdeCampos++;
    }
    
    function removerCampo(id) {
    var objPai = document.getElementById("campoPai");
    var objFilho = document.getElementById("filho"+id);
    
    //Removendo o DIV com id específico do nó-pai:
    var removido = objPai.removeChild(objFilho);
    }
    </script>
    </head>
    <body>
    <form name="form1" action="pegardados.php" method="post">
    <div id="campoPai"></div>
    <input type="button" value="Adicionar campos" onclick="addCampos()">
    <br><br><input type="submit" value="Enviar">
    </form>
    </body>
    </html>
    

    Página pegardados.php:

    Recuperando os valores que foram enviados pelo form:
    
    <?php
    if(isset($_POST["campo"])) {
        echo "Os campos que você adicionou são:<br><br>";
        
        // Faz loop pelo array dos campos:
        foreach($_POST["campo"] as $campo) {
            echo $campo."<br>";
        }
    }else{
    	echo "Você não adicionou dados em nenhum campo!";
    }
    ?>
    
    • +1 1

  13. Realmente pessoal... no Internet Explorer funcionou muito bem... mas eu não havia testado no Firefox Mozilla. No FF ele realmente apaga o valor dos campos que já foram preenchidos anteriormente, ao adicionar outro campo.

     

    Fiquei hoje o dia inteiro pensando em como resolver essa situação, tanto para o IE quanto para o FF.

    Consegui desenvolver um código que está funcionando bem em Javascript, mas não tive como testar ainda com a linguagem server-side. Quem testar, por gentileza, poste o ocorrido aqui, ok? Vamos melhorar esse código quantas vezes necessário até que não haja nenhum bug. Conto com a participação de vocês!

     

    O código abaixo já está comentado:

    <html>
    <head>
    <script type="text/javascript">
    //Total máximo de campos que você permitirá criar em seu site:
    var totalCampos = 10;
    
    //Não altere os valores abaixo, pois são variáveis controle;
    var iLoop = 1;
    var iCount = 0;
    var linhaAtual;
    
    
    function AddCampos() {
    var hidden1 = document.getElementById("hidden1");
    var hidden2 = document.getElementById("hidden2");
    
    //Executar apenas se houver possibilidade de inserção de novos campos:
    if (iCount < totalCampos) {
    
    //Limpar hidden1, para atualizar a lista dos campos que ainda estão vazios:
    hidden2.value = "";
    
    //Atualizando a lista dos campos que estão ocultos.
    //Essa lista ficará armazenada temporiariamente em hidden2;
    for (iLoop = 1; iLoop <= totalCampos; iLoop++) {
            if (document.getElementById("linha"+iLoop).style.display == "none") {
                    if (hidden2.value == "") {
                            hidden2.value = "linha"+iLoop;
                    }else{
                            hidden2.value += ",linha"+iLoop;
                    }
            }
    }
    //Quebrando a lista que foi armazenada em hidden2 em array:
    
    linhasOcultas = hidden2.value.split(",");
    
    
            if (linhasOcultas.length > 0) {
                    //Tornar visível o primeiro elemento de linhasOcultas:
                    document.getElementById(linhasOcultas[0]).style.display = "block"; iCount++;
                    
                    //Acrescentando o índice zero a hidden1:
                    if (hidden1.value == "") {
                            hidden1.value = linhasOcultas[0];
                    }else{
                            hidden1.value += ","+linhasOcultas[0];
                    }
                    
                    /*Retirar a opção acima da lista de itens ocultos: <-------- OPCIONAL!!!
                    if (hidden2.value.indexOf(","+linhasOcultas[0]) != -1) {
                            hidden2.value = hidden2.value.replace(linhasOcultas[0]+",","");
                    }else if (hidden2.indexOf(linhasOcultas[0]+",") == 0) {
                            hidden2.value = hidden2.value.replace(linhasOcultas[0]+",","");
                    }else{
                            hidden2.value = "";
                    }
                    */
            }
    }
    }
    
    function RemoverCampos(id) {
    //Criando ponteiro para hidden1:        
    var hidden1 = document.getElementById("hidden1");
    
    //Pegar o valor do campo que será excluído:
    var campoValor = document.getElementById("arq"+id).value;
            //Se o campo não tiver nenhum valor, atribuir a string: vazio:
            if (campoValor == "") {
                    campoValor = "vazio";
            }
    
        	if(confirm("O campo que contém o valor:\n» "+campoValor+"\nserá excluído!\n\nDeseja prosseguir?")){
                    document.getElementById("linha"+id).style.display = "none"; iCount--;
                    
                    //Removendo o valor de hidden1:
                    if (hidden1.value.indexOf(",linha"+id) != -1) {
                            hidden1.value = hidden1.value.replace(",linha"+id,"");
                    }else if (hidden1.value.indexOf("linha"+id+",") == 0) {
                            hidden1.value = hidden1.value.replace("linha"+id+",","");
                    }else{
                            hidden1.value = "";
                    }
            }
    }
    </script>
    </head>
    <body>
    <form name="form1" action="paginaPHPouASP" method="post">
    
    <script type="text/javascript">
    //Escrevendo o código-fonte HTML e ocultando os campos criados:
    for (iLoop = 1; iLoop <= totalCampos; iLoop++) {
            document.write("<span id='linha"+iLoop+"' style='display:none'>Arquivo "+iLoop+": <input type='text' id='arq"+iLoop+"' name='arq"+iLoop+"'> <input type='button' value='Remover' onclick='RemoverCampos(\""+iLoop+"\")'></span>");
    }
    </script>
    
    <input type="button" value="Adicionar campos" onclick="AddCampos()">
    <br><br>Atenção!!! No código fonte, altere o "text" do campo abaixo para "hidden":
    <br><br><input type="text" name="hidden1" id="hidden1">
    <br>Esse campo do tipo "hidden" irá passar a id dos campos que foram criados. Na página ASP ou PHP (ou outra linguagem server-side) você poderá dar um split para recuperar o valor dos campos que foram passados!
    
    
    <input type="hidden" name="hidden2" id="hidden2">
    </form>
    
    </body>
    </html>

  14. -- Tópico editado e movido --

    Devido à grande quantidade de dúvidas, achei prudente mover esse tópico do Laboratório de Scripts para o fórum principal. Muitos usuários não souberam como recuperar os dados em PHP e isso foi devido à falha minha, por eu não ter postado antes o script em PHP (entretando mostrei um exemplo no post #13 a seguir).

     

    Peço sinceras desculpas pelo transtorno.

     

    Movido:

    JavaScript/DHTML: Laboratório de Scripts :seta: JavaScript/DHTML: Fórum principal

     

    --Tópico original--

    Olá pessoal!

     

    Uma aplicação interessante do JavaScript é a criação de campos input (text, hidden, button, dentre outros) dinamicamente, ou seja, o usuário entra no seu site e pode, conforme a situação, criar ou apagar campos pré-existentes.

     

    Isso é muito utilizado em sistemas de e-mails, ou outros sistemas de "uploads", no qual é exibido um campo "texto" e um botão com o valor "Adicionar campo" (por exemplo), para que o usuário possa upar mais de um arquivo de cada vez.

     

    Muitas vezes, esses sistemas não possuem a opção de "Apagar campo", mas isso é uma característica do sistema, que procurei não repetir no código abaixo. Logo, o código que estou disponibilizando a seguir, contém, na frente de todo campo "texto" recém-criado, um botão para apagá-lo, caso não seja mais necessário.

     

    Por fim, adicionei um campo "hidden" (que está, apenas para título de demonstração, como "text") que enviará via POST, para a página PHP ou ASP por exemplo, uma string contendo quais os campos foram realmente enviados. Desse modo, fica mais fácil controlar no script ASP ou PHP o nome das variáveis que forem sendo criadas.

     

    Observação: Não tive tempo de testar no Firefox. No IE7 e Opera 9.52 ocorreu tudo bem!

     

    Para testar o script (corrigido), basta copiar todo o código a seguir e colar em seu editor HTML preferido:

     

    <html>  <head>	<title>java script: Adicionar e remover campos dinamicamente!</title>  <script language="JavaScript" type="text/javascript">   /*Script desenvolvido por: klonderPostagem exclusiva em: http://www.forum.imasters.com.brLiberado para uso e modificação.*///Não altere esses valores!var iCount = 0;var iCampos = 1;var hidden1; //Definindo quantos campos poderão ser criados (máximo);var iCamposTotal = 5; //Função que adiciona os campos;function addInput() {   if (iCampos <= iCamposTotal) { 	hidden1 = document.getElementById("hidden1"); 		//Criando uma variável que armazenará as informações da linha que será criada.	//Os campos estão sendo colocados no interior de uma div, pois a linha contém muitos elementos;	//Basta excluir a div, para excluir todos os elementos da linha;	var texto = "<div id='linha"+iCount+"'><input type='text' name='texto"+iCount+"' id='texto"+iCount+"' value='Meu texto "+iCount+"'><input type='button' value='Apagar campo' onClick='removeInput("linha"+iCount+"")'></div>";	    	//Capturando a div principal, na qual os novos divs serão inseridos:	var camposTexto = document.getElementById('camposTexto');   	camposTexto.innerHTML = camposTexto.innerHTML+texto;  	//Escrevendo no hidden os ids que serão passados via POST;	//No código ASP ou PHP, você poderá pegar esses valores com um split, por exemplo;		if (hidden1.value == "") {			document.getElementById("hidden1").value = iCount;		}else{			document.getElementById("hidden1").value += ","+iCount;		}iCount++;iCampos++;}   }   //Função que remove os campos;function removeInput(e) {   var pai = document.getElementById('camposTexto');   var filho = document.getElementById(e);   hidden1 = document.getElementById("hidden1");   var campoValor = document.getElementById("texto"+e.substring(5)).value;   var lastNumber = hidden1.value.substring(hidden1.value.lastIndexOf(",")+1);   if(confirm("O campo que contém o valor:n» "+campoValor+"nserá excluído permanentemente!nnDeseja prosseguir?")){		var removido = pai.removeChild(filho);		//Removendo o valor de hidden1:		if (e.substring(5) == hidden1.value) {			hidden1.value = hidden1.value.replace(e.substring(5),"");		}else if(e.substring(5) == lastNumber) {			hidden1.value = hidden1.value.replace(","+e.substring(5),"");		}else{			hidden1.value = hidden1.value.replace(e.substring(5)+",","");				}	iCampos--;	}}</script> </head>  <body>  <form  name="my_form" id="my_form" action="" method="post">  <input type="button" value="Criar campo texto" name="add_input" id="add_input" onClick="addInput();">  <div id="camposTexto"></div><br><br>Ajuste o campo abaixo para "hidden" no código-fonte.<br>O valor passado será utilizado na página ASP ou PHP, por exemplo, servindo de controle dos ids passados:<br><input type="text" name="hidden1" id="hidden1" value=""></form>  </body>  </html>

    Abraços a todos!

    • +1 1
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.