** Script atualizado para versão 1.1, clique aqui para ver os detalhes **
Desenvolvendo uma solução de sistema de gerência para o Dep. Comercial do ComuniWeb recebi inúmeros pedidos de “mas não pode aparecer os nomes dos clientes quando vou digitando?”. Ok não foi tão lindo e poético assim, na verdade o que acontecia era que o auto-complete padrão do IE causava uma confusão enorme nos usuários (usuário é usuário né?).
Me vi então cara a cara com um problema, como resolver este problema? Precisava que um script ao tempo que a pessoa digitava fizesse uma busca no banco para retornar a lista de clientes e o seu vendedor, isso tudo num browser. Se o tmepo hoje fosse alguns meses atrás (não muitos) eu falaria “impossível, estamos falando de web, nao delphi ou VB!”. Alás que surgiu o xmlHttpRequest e tudo mudou…
Fui então a busca de vários exemplos de auto-complete ou “google-suggest” (vantagens de se dominar a tecnologia…) e achei várias soluções que utilizavam diferentes métodos, porém nenhuma que utilizasse AJAX (salvo o próprio Google…). Confiem em mim quando alguém quer tornar um arquivo javascript ilegivel, essas pessoas conseguem, e o google o fez com toda categoria, variaveis de uma letra só e todos estoque de armas…
Portanto comecei com o arroz com feijão:
<input name="string" id="string" onkeyup="sendAjaxReq(this.value)" type="text" />
A idéia era bem simples, a cada tecla uma requisição AJAX era feita, um arquivo PHP fazia a busca no banco e retornava um arquivo XML com a lista de resultados, algo como:
<root> <item id="286" label="temos"></item> <item id="288" label="ter"></item> <item id="332" label="tecnol%F3gico%2C"></item> </root>
foi simples o bastante converter esta lista em um div flutuante com uma unordered list (UL) e mostrar ela junto ao campo. Portanto o príncipio já estava la, você digita e clicando no item efetua a escolha… nada amigável né?
Faltava então buscar uma solução como a usada pelo google utilizando as setas (up e down) para navegar entre os resultados e usar o ENTER ou TAB para fazer a escolha. Para isso me apoiei em um script que já havia encontrado pela web, só para pegar a semantica.
Com isso terminei com um script que fazia a busca no banco, navegava por teclado ou mouse e enfim.. funcionava. quando terminei esta implementação já achei X novas oportunidades de utiliza-lo novamente decidi então tornar o script mais genérico de forma a utilizar ele de forma mais simples, e é isso que vocês podem conferir e utlizar.
Exemplo: veja aqui
Download do arquivo (com exemplos): dmsAutoComplete.zip
Espero que seja útil, pelomenos para algumas pessoas.
Known bugs: No firefox na primeira vez que a lista é populada ela aparece toda em uma linha só, sem quebra de linhas.
This post is also available in: Inglês
Rafael, peguei seu script no blog e funcionou corretamente no meu servidor. Porém, quando eu tento fazer um auto-completar para buscar em um BD, ele não exibe nenhum resultado.
Para testar, fiz uma coisa simples. Conexão com BD, busca nomes dos usuários do site e a variável $ostring recebe valores:
include(“conexao.php”) //funciona corretamenet
$query = “select nome from usuarios”;
$result = mysql_query($query);
while($palavra = mysql_fetch_array($result))
{ $ostring = $palavra[“nome”]; }
Somente adicionei esse código e não alterei nada, mas não está listando nada. Testados no IE e Firefox, nenhum resultado.
Obrigado.
correção do código anterior:
while($palavra = mysql_fetch_array($result))
{ $ostring = $ostring . ” ” . $palavra[“nome”]; }
//recebe o texto já guardado na variavel $ostring + valor do array
Caro felipe
Para mostrar os resultados de uma pesquisa no BD, para cada linha do banco você deve repetir o processo de anexar um novo
item à lista como abaixo
$item = $xmlDoc->createElement(\’item\’);
$item = $root->appendChild($item);
$item->setAttribute(\’id\’,$key);
$item->setAttribute(\’label\’,rawurlencode($label));
No seu código, faça o seguinte
while($palavra = mysql_fetch_array($result))
{
$item = $xmlDoc->createElement(\’item\’);
$item = $root->appendChild($item);
$item->setAttribute(\’id\’,$key);
$item->setAttribute(\’label\’,rawurlencode($palavra[”nome”]));
}
e substitua $key pelo valor da sua chave primaria no banco.
Qualquer dúvida estamos ai
muito bacana
Rafael, eu to tentando executar (localhost) o seu script usando o pacote Wamp= Windows+apache+mysql, mas não está funcionando.
Eu nunca trabalhei com xml nem ajax… vc poderia mi explicar como eu faço pra colocar esse esquema de auto-complete pra funcionar?
Obrigado,
Adriano,
Este script não tem nenhum resquisito em especial, apenas a biblioteca DOM (http://www.php.net/manual/en/ref.dom.php);
Me mande por email (rafael@rafaeldohms.com.br) os detalhes do que esta acontecendo, erros e etc que te dou uma força.
Rafael, achei o problema. O codigo php não eh executado na minha maquina qdo a tag inicio do php começa soh com "<?"
Encontrei uma limitação no script, por isso to trabalhando na versão 1.1 dele.
Caso alguem já queira adiantar, para poder utilizar mais de um AC em cada página, va no arquivo .js e substituia AC por me em todas as linhas de 222 até 230.
Vou concertar alguns outros bugs em relação ao Firefox e lanço a nova versão
Soluções de autocompletar existe algumas que funcionam da forma como você criou. Mas é legal a iniciativa. Mas eu vou dar uma olhada no teu código e ver se posso contribuir com alguma coisa.
Realmente acabei encontrando algumas referências quando terminei o script. Mas mesmo assim aceitei como um desafio e decidi ver de onde vinha o problema e como formular a melhor solução.
Ainda tenho alguns bugs pra resolver, mais em termos de layout, e o script venho muito a calhar com os sistemas que gerencio, em menos de 5 minutos conisgo adicionar a função a uma página e ter ela funcionando, quem programa sabe como é bom isso.
Sugestões e melhorias são sempre bem vindas Benjamin, obrigado!
Nove versão deste script publicada, veja neste post os detalhes da versão 1.1:
http://blog.rafaeldohms.com.br/2006/08/09/dmsautocomplete-v11/pt/
Rafael, como poderia ser feito para usar o sistema de auto complete, em mais de um campo, com consulta a banco de dados, em tabelas diferentes?
Adriano,
verifique a atualização do script v1.1, nele fiz alterações para permitir mais de um autocomplete por pagina.
Desta forma você teria 2 arquivos de consulta PHP digamos um chamado searchuser.php e outro searchcliente.php cada um recebe uma string, busca no banco e retorna o resultado.
No seu formulário voce teria dois campos, digamos user e cliente e logo no fim voce instanciaria dois autocompletes, em variaveis diferentes e com targets diferentes, exemplo:
var AC = new dmsAutoComplete(‘user’,’acDiv’);
AC.ajaxTarget = ‘searchuser.php’;
var ACC = new dmsAutoComplete(‘cliente’,’acDiv’);
ACC.ajaxTarget = ‘searchcliente.php’;
Pronto, vc tem dois autocompletes rodando na página. Lembro que isso só vale para a versão 1.1, portanto repita o doewnload e certifique que esta com a versão certa.
Qlqr coisa pode mandar por email as duvidas q te ajudo.
Rafael,
gostei muito do seu script, porem, nao consigo filtar a consulta no banco. Como poderia fazer isso, pois soh consigo trazer todos os registros sem filtro pelas iniciais digitadas.
Cleodon,
No outro tópico onde falo da versão 1.1 do script eu respondi um comentario como o seu, voce precisa incluir uma condição “where” na sua qyery que busque somente os campos que começãm com o que foi digitado, veja um exemplo:
$query = “select palestran from palestra WHERE palestran LIKE ‘”.$_POST[string].”%’”;
o % em SQL significa coringa, com isso ele retorna tudo que começa com string.
Implantei este script buscando os registros do banco de dados e está redondo… Porém estou precisando colocar uma barra de rolagem na div que imprime os resultados.
To utilizando overflow:auto; no css e a barra aparece blz e funciona 100% no firefox, mas no IE (pra variar), ela não funciona. Quando clica nela ela some.
Alguém pode dar um help aí?
Desde já agradeço.
Até
Rafael… eu baixei o arquivo zipado… e tentei executalo mas não funciona… mesmo eu não tendo alterado nenhuma virgula!
No exemplo do seu site ele funciona normal… tentei fuçar no código mas naum achei solução não!
ele simplesmente naum demonstra nenhuma reação, é como se fosse só um campo text comum.
mas o sistema é bom! pena que naum tenha funcionado aqui!
Marcel,
Acredito que o problema possa estar na configuração do servidor, ou no caminho relativo aos arquivos, algo como o script não esta se encontrando, se puder me envie mais informações por email, ou use o firebug do firefox para debugar o script.
Obrigado
Olá Rafael achei esse código o maximo, mas estou quebrando a cabeca em uma coisa, eu estou tentando que ele me traga de uma tabela do banco de dados nao só uma palavra e sim tudo que esta dentro da tabela. por exemplo, eu tenho um tabela com o id, nome e telefone, mas se eu coloco o autocompletar para buscar o nome ele só tras um dos nomes, por exemplo “Carlos da Silva”, eu coloco a letra “c” e só me vem “Carlos” e gostaria que vinhece o nome completo, tem como vc me dar uma ajuda? Ah também poderia me dizar como tirar a janela alert do javascript quando vc escolhe um nome.
Ah, sem querer abusar, mais uma coisinha, tem com dizar ao codigo para ele nao diferenciar do maiusculo do minusculo.
Agradeco desde já, um abraco.
Rivair,
Obrigado!
Bem quanto ao minisculo e maisculo, esta adaptaçao deve ser feita no arquivo PHP que retorna os resultado, na busca no banco de dados pra ser exato, o que vai com o arquivo e apenas um exemplo de uso.
Mesma coisa para os varios campos que voce descreveu, o script trabalha com id e label, mas este label pode ser algo como “fulano (ful@ano.com) – 16/12” ou qualquer informaçao que voce desejar retornar.
A funçao do alert esta logo abaixo da declaraçao do script e pode ser adequada ao seu uso, editando o javascript.
Sinta-se livre para explorar o script.
Olá Rafael, valeu mesmo pela luz, a resposta estava na minha cara e eu nao tinha visto, fico te devendo uma, e de novo parabéns pelo script está me quebrando um galhao.
T+ Rivair
Olá Rafael!
Muito bom o Scritp, mas não funcionou aqui no server, nem com Ruindows (php 4.x e 5.x) e no Linux (php 4).
Ambos possuem o domXML habilitado!
O estranho é que ao digitar as iniciais aparece uma pequena caixinha, comose fosse aparecer algo, asm não aparece nada!
Monitorando as requisições, não parece que está sendo enviada …
Por um acaso saberia informar o que pode estar errado?
Um abraço e parabéns pelo artigo!
Então, não sei se acjuda, a única mensagem que tenho é:
Erro: xmlRes has no properties
Arquivo-fonte: http://192.168.1.3/ajax/dmsAutoComplete.js
Linha: 218
Igor,
Isso significa que o PHP não tá retornando nada. Faz o seguinte executa o arquivo php diretamente, passando “?string=a” e ve se ele retorna algum erro ou alguma coisa, já vai te dá 80% das dicas q vc precisa pra ver oq esta ocorrendo.
Qlqr coisa me encaminha o resultado que dou uma olhada.
Abraço!!
Olá Rafael,
Então, fiz o que falei e consegui resolver o problema.
Vou colocar aqui os passos:
1) chamei diretamente o arquivo http://localhost/ajax/dms/dmsAC.php?string=re
E recebi a seguinte mesnagem de erro:
Erro no processamento de XML: caracteres inúteis após um elemento do documento
Posição: http://localhost/ajax/dms/dmsAC.php?string=re
Número da linha 2, Coluna 1:Notice: Undefined index: string in c:\arquivos de programas\apache group\Apache\arquivos\ajax\dms\dmsAC.php on line 50
^
2) Fui até a linha 50 do arquivo dmsAC.php e troquei:
if ($_POST[‘string’] != ”){
por:
if ( isset($_POST[‘string’]) && $_POST[‘string’] != ”){
3) Funcionou!
É isto aí, muito obrigado !!!
Ahh sim,
Esqueci de falar que só funcionou no php 5.x!
No 4.x ele reclama que não existe a função createelement(), apesar de existir e estar hailitado o DOM:
domxml
DOM/XML enabled
DOM/XML API Version 20020815
libxml Version 20623
HTML Support enabled
XPath Support enabled
XPointer Support enabled
É isto aí,
Um abraço
Olá Rafael,
Estou migrando seu código para PHP 4.x, porém parece que o .js também tem uma incompatibilidade, já que ao digitar a no campo aparece uma listagem com tudo null …
Veja o teste em http://www.comp.ufscar.br/~igorvc/dms2/example.htm
Bem, vou ver se tento debugar e ver onde está a incompatibilidade!
Assim que eu terminar a migração, postarei aqui as modificações, daí mais gente poderá utilizar!
Um abraço
Ae pessoal, fiz o que deu e postei isso la no forum de AJAX.
o caminho é esse quem quizer ver o “for”, pois aqui tentei e nada de conseguir, então!!!
http://ajaxonline.com.br/forum/viewtopic.php?t=35
Cara, o seu exemplo funcionou perfeitamente — com o PHP5, e SEM ‘php.ini’.
Assim que renomeei o php.ini-recommended, o script deixou de funcionar.
Não achei nada sobre ‘como ativar o DOM’, e tem outro porém: todos os meus outros scripts estão em PHP4 (mysql_), e seria um trabalhão passá-los todos pro PHP5.
Vou esperar pra ver o que o Igor consegue com o PHP4, mas enquanto isso… Como faço pra ativar o DOM no PHP5 depois de renomear o php.ini…? o_O
Guilherme,
Verifica uma coisa no PHP5, algumas (ou todas) versões estão vindo com o “short_tags” OFF, isso significa que <? não funciona, somente <?php. Isso pode explicar. Quanto ao DOM ele já esta habilitado por padrão no PHP5.
Para fazer o script funcionar em PHP4 é bem simples, só substituir todos DOM por strings de XML mesmo, montar o XML na mão. Ou usar classes de PHP populares.
Ôpa! Fiz esta versão pelo ‘método lusitano’, e agora está funcionando no PHP4! =)
Estava matutando sobre ‘como fazer o barato case-INsensitive’…
Isso mais tarde vai puxar uma coluna d’um MySQL.
Bem, mais uma vez agredeço de montão a sua força, e depois te mando um e-mail mostrando onde pretendo usar o seu snippet! ; )
Um forte abraço de novo, e muito obrigado pela força!
Xii rapaz, acho que o seu script de processar os comentários comeu algumas coisas do que postei… Hahahah
Bom, depois te mando ele! ; )
Olá Rafael!!
Cara tou começando agora na area do Ajax e ainda não vi o php5, gostaria que se possivel vc me desse uma mão e colocasse como que se faz para fazer a pesquisa no BD, tou apanhando demais, eu vi o que vc postou para o Felipe Rômulo Silva mais não consegui pegar, depois do while, como que fica a “$ostring”??, fiz o que vc postou mais não funcionou com o select não, acho que o que eu deve estar errado.
Fica assim, um abraço pra vc!!
Francis Bento Marques
Repare que os acentos ainda produzem erro… Eles não são auto-completados
Francis,
Me envie o seu código por email para que eu possa analisar
Legal, Gostei muito.
Beleza Rafael?
Me diz uma coisa, se eu quiser utilizar um WebService para retornar as informações, eu já tenho um que retorna um XML no formato que vc desenhou, só que o método precisa ser invocado, como eu faria isto?
Valeu!
Raphael
Raphael,
Existe uma variavel do script que voce pode mudar a URL para o que desejar. Seria algo como:
AC.ajaxTarget = ‘sua_url/servico’;
Entendeu?
abraço!
Valeu Rafael, vou fazer alguns testes ainda, mas na primeira tentativa ele não rodou com webservices, pois o método precisa ser invocado.
Mas vou ver com mais paciência hoje a tarde.
T
Cara, vou ser bem sincero, voce me ajudou muito =) vlw mesmo. Exatemante disso que eu estava precisando =)
Ronaldo,
Me mostre sua query SQL é ela que vai definir o retorno
Parabéns pelo script, não quebrou um galho meu, mas sim uma árvore.
obrigado!
Para pegar valores de um BD fiz o seguinte while (assim como mostra um exemplo acima )
Porém qualquer coisa que eu digite ele me traz todos os registros do banco.
alguém já fez com BD ?
obrigado
while($palavra = pg_fetch_array($result))
{
$key = $palavra[‘codigo’];
$item = $xmlDoc->createElement(‘item’);
$item = $root->appendChild($item);
$item->setAttribute(‘id’,$key);
$item->setAttribute(‘label’,rawurlencode($palavra[‘nome’]));
$ostring = $ostring . ” ” .$palavra[‘nome’] ;
}
$query = “SELECT * FROM teste ORDER BY nome ASC” ;
$result = pg_query($conn,$query);
coloquei (*) sendo que os campos sao:
codigo(int) nome(varchar) email(varchar)
obrigado pela atenção !
Ronaldo,
É preciso que a query busque as palavras de acordo com o que ela recebe, voce precisa incluir ai algum requisito WHERE, tipo:
SELECT * FROM teste WHERE nome LIKE ‘”.$_POST[‘string’].”%’ ORDER BY nome ASC
Com isso ele vai procurar por nome onde o nome começe com a string passada.
Muito obrigado Dohms !
E olha que voce já havia dito isto acima ehehehe.
Funcionou uma beleza, mas fiz o seguinte. Comentei uma linha para que ele nao repetisse as palavras digitadas!
foreach($results as $key=>$label) {
if (class_exists(‘DOMDocument’)){
//Cadastrar na lista
//Add to list
$item = $xmlDoc->createElement(‘item’);
// $item = $root->appendChild($item); comentada por ronaldo
$item->setAttribute(‘id’,$key);
$item->setAttribute(‘label’,rawurlencode($label));
//rawurlencode evita problemas de charset
//rawurlencode avoids charset problems
}else{
$xmlDoc .= ”;
}
}
legal ..
Eu rodei o script da forma que veio e deu certinho agora eu não consigo colocar ele pra buscar no BD como vc falou no post abaixo:
=====================================================
Rafael Dohms on 14 Jul 2006 at 11:18 #
Caro felipe
Para mostrar …
No seu código, faça o seguinte….
while($palavra = mysql_fetch_array($result))
{
$item = $xmlDoc->createElement(\’item\’);
$item = $root->appendChild($item);
$item->setAttribute(\’id\’,$key);
$item->setAttribute(\’label\’,rawurlencode($palavra[”nome”]));
}
e substitua $key pelo valor da sua chave primaria no banco.
Qualquer dúvida estamos ai
=================================================
Substitui $key por $id como falou, comentei a linha string do texto grande e coloquei o while dai deste post so que não aparece nada.
Teria como vc me enviar um exemplo com uma busca no banco de dados em uma tabela retornando os valores de um campo?
Te agradeço pela ajuda desde já,
Abraço
Márcio
Olá, estive testando o código, gostei muito.
Mas estou com um problema, o Código não roda no IE.
No firefox está tudo normal. Estou usando com ASP.
Abraço
André,
Você tem mais alguma informação, vou fazer alguns testes depois vejo se identifico algum problema.
abraço
Grande Rafael, agradeço sua colaboração com a comuidade php/ajax, por oferecer seu código para nós, usei e aprovei com grande sucesso, porém não estou conseguindo colocar que funcione com acentos as palavras, veja na prática no meu site.
http://www.amarelasdf.com/autocomplete/plus
trata-se de um site de anúncios.
Como se faz com POSTGRES, Acessando o banco.? poederia ajuda-me ? estou precisando muito.
Obrigado pela atenção. .
nossa parabens viu muito otima essa sua dica um super valeu
Não tem como você re-fazer o código, mas totalmente adaptado para buscar as informações no banco de dado, solucioaria muito os problemas…
Olá Rafael, blz?
Adaptei o script pra meu uso com o banco de dados e tudo mais.
A única coisa que to quebrando a cabeça é pra não ficar aparecendo o alert, mas apenas qdo dou enter emcima de um item da lista ficar digitado.
Consegui tirar o alert, mas qdo dou enter no item da lista o input fica em branco. obs: isso acontece deixando o alert ou sem.
Sabe como faço pra resolver isso?
Desde já agradeço e parabenizo-lhe pelo script, muito bom mesmo.
Abs.
Alisson!
Alisson,
Infelizmente faz muito tempo que atualizei com este codigo e nao me lembro se isto era possivel na epoca portanto acredito que não esta incorporado no codigo.