Auto-completar Ajax
Autor:
Elcio Ferreira <http://elcio.com.br/ajax/autocompletar>
Algumas pessoas tem escrito perguntando como se produz um efeito semelhante ao Google Suggest. Esta série de artigos e o script que a acompanha são uma maneira de tentar responder a esta dúvida.
Exemplo do efeito desejado:
O script
Embora a idéia original seja bastante simples, o controle de eventos do teclado é bastante complexo e exige um bocado de código, além de um bom conhecimento de DOM. Além disso, é muito interessante que esse tipo de coisa seja produzida no formato de um script reaproveitável, o que exige uma série de outros conhecimentos que tornam o código complexo demais para um artigo simples.
Assim, resolvi escrever sobre algumas coisas:
- Como usar este script para implementar um recurso de auto-completar em seu site.
- Como personalizar este recurso.
- Como escrever um script como este, que trata eventos do navegador, inclusive do IE bugado.
- Como escrever código ajax usando JSON, uma das maneiras mais práticas de se fazer ajax.
- Como escrever código javascript que seja facilmente reaproveitado.
Como usar este script
Tentei construir um script que você possa reaproveitar sem ter o trabalho de entendê-lo todo. Nas partes posteriores desta série de artigos vamos entender este script passo a passo, e pretendo dar dicas de como construir código reaproveitável como este. Então vamos começar analisando o resultado, isto é, aproveitando este código numa página para ver como será a experiência de quem quiser usá-lo sem entendê-lo.
Para começar, copie para seu site os arquivos:
Em seguida inclua estes arquivos na seção head do seu HTML, assim:
<link rel="stylesheet" href="css/autocompletar.css" />
<script src="js/events.js"></script>
<script src="js/xmlhttp.js"></script>
<script src="js/autocompletar.js"></script>
Seu formulário HTML precisa ter a class autocompletar
e o campo de formulário que vai ser preenchido terá o id completeaqui
. Defina então a largura do seu campo de formulário junto com a da caixa de sugestões, no CSS:
.completeaqui,div#completando{
width:300px;
}
Fazendo a busca via Ajax, com JSON
A maneira mais simples de usar este script é fazê-lo buscar os dados do servidor via Ajax, no formato JSON. Para isto, basta fazer sua página PHP, ASP ou seja lá o que estiver usando, retornar um Array de strings formatado em JSON. (Vou falar mais de JSON na quarta parte desta série.)
Veja um exemplo disso na página python que estou usando neste tutorial: ap, fi. É esta página que meu script vai buscar.
Tendo construído uma página no servidor que retorna os dados no formato acima, basta:
window.onload=function(){
ac_registraJSON(document.forms[0],"q","busca.pt?q=")
}
Onde "busca.pt?q="
é o endereço de onde esse script vai buscar os dados. O primeiro argumento (document.forms[0]
) é o formulário que contém o campo, e o segundo ("q"
) o nome do campo.
ANEXO 1: <script src="js/events.js">
/* Tratamento de eventos crossbrowser Baseado em http://simon.incutio.com/archive/2003/11/06/easytoggle Elcio Ferreira - 2004 - http://elcio.locaweb.com.br */
function addEvent(obj, evType, fn){ if(obj.addEventListener)obj.addEventListener(evType,fn,true) if(obj.attachEvent)obj.attachEvent("on"+evType,fn) }
function getSource(e){ if(typeof e=='undefined')var e=window.event; var source=typeof e.target!='undefined'?e.target:typeof e.srcElement!='undefined'?e.srcElement:true if(source.nodeType == 3)source=source.parentNode; return source }
|
ANEXO 2:<script src="js/xmlhttp.js">
try{ xmlhttp = new XMLHttpRequest(); }catch(ee){ try{ xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ try{ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }catch(E){ xmlhttp = false; } } } |
ANEXO 3: <link rel="stylesheet" href="css/autocompletar.css" />
form.autocompletar{ position:relative; top:0; left:0; } div#completando{ position:absolute; top:1.5em; left:0px; background:white; } div#completando ul{ margin:0 1px;padding:0; border:1px solid black; list-style:none; } div#completando li{display:inline} div#completando a{ display:block; padding:1px 5px; } div#completando a:hover,div#completando li.selecionado a{ background:blue; color:white; }
|
ANEXO 4:<script src="js/autocompletar.js">
//Variáveis Globais ac_idx=0 ac_old="" ac_showing=false
//Registra o autocompletar function ac_registra(formulario,inputname,funcao){ ac_campo=formulario.elements[inputname] addEvent(ac_campo, "keyup", ac_up) addEvent(ac_campo, "keypress", ac_mudou) addEvent(ac_campo, "focus", ac_focus) addEvent(ac_campo, "blur", ac_blur) ac_pegaLista=funcao } //Registra o autocompletar com um endereço Ajax/JSON function ac_registraJSON(formulario,inputname,endereco){ ac_JSON=endereco ac_registra(formulario,inputname,ac_getJSON) }
//Função para obter o JSON function ac_getJSON(t,func){ ac_f=func xmlhttp.open("GET", ac_JSON+escape(t),true); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) ac_f(eval(xmlhttp.responseText)) } xmlhttp.send(null) }
//Monta a lista a partir de um Array function ac_fazLista(t){ ac_Lista=t var ret="<ul>" for(var i=0;i<ac_Lista.length;i++) ret+="<li"+(i==ac_idx?' class="selecionado"':'')+ "><a href='javascript:ac_completa("+i+")'>"+ ac_getHTML(ac_Lista[i])+"</a></li>" ret+="</ul>" document.getElementById("completando").innerHTML=ret }
//Obtém o texto do item da lista function ac_getText(i){return typeof(i)=="string"?i:i[1]} //Obtém o HMTL do item da lista function ac_getHTML(i){return typeof(i)=="string"?i:i[0]}
//Atualiza a lista de acordo com o conteúdo do campo function ac_mudado(){ ac_texto=ac_campo.value if(ac_old!=ac_texto)ac_idx=0 ac_old=ac_texto setTimeout('ac_pegaLista(ac_texto,ac_fazLista)',100) }
//Esconde a lista function ac_some(){ ac_showing=false try{document.getElementById("completando").style.display="none"}catch(e){} }
//Mostra a lista function ac_aparece(){ ac_showing=true try{ document.getElementById("completando").style.display="block" }catch(E){ var d = document.createElement("div"); d.setAttribute("id","completando") ac_campo.parentNode.appendChild(d) } }
//Clique no completar function ac_completa(l){ try{ ac_texto=ac_campo.value=ac_Lista[l] ac_campo.focus() setTimeout('ac_aparece()',110) ac_mudado() }catch(e){} }
//Controla o índice do item selecionado function ac_chItem(kCode){ ac_idx+=kCode-39 if(ac_idx<0)ac_idx=ac_Lista.length-1 if(ac_idx>ac_Lista.length-1)ac_idx=0 ac_mudado() }
/* Eventos no textbox: */ //KeyPress function ac_mudou(e){ if(e.keyCode==40 || e.keyCode==38 || e.keyCode==13){ if(e.keyCode!=13){ if(!ac_showing)ac_aparece() ac_chItem(e.keyCode) }else{ if(ac_Lista[ac_idx]==ac_campo.value || ac_Lista.length==0)return true if(ac_showing)ac_completa(ac_idx) else return true } if(e.preventDefault)e.preventDefault() return false } if(e.keyCode==27)ac_some() setTimeout('ac_mudado()',1) } //Tratando eventos no IE bugado function ac_up(e){ if(typeof e.target=="undefined" && (e.keyCode==40 || e.keyCode==38 || e.keyCode==8))ac_mudou(e) }
//Focus function ac_focus(e){ ac_aparece() ac_mudado() } //Blur function ac_blur(e){setTimeout('ac_some()',100)}
|
Nenhum comentário:
Postar um comentário