segunda-feira, novembro 13, 2006

Fazendo uma requisição assíncrona simples, com JQuery

Com o advento do ajax nós programadores estamos sempre utilizando essa ferramenta para um adicional em nossos sistemas. Seja carregando dados para preencher um dropdown, seja para carregar uma página inteira, as requisições assíncronas, junto do bom e velho “carregando...” viraram rotina em nossas vidas.

Tendo toda essa importância é claro que a JQuery não poderia não ter um módulo só para ajax. Vamos entender um pouco desse módulo da JQuery, e saber como incrementar nossa produtividade com ele.


Para essa nossa brincadeirinha vamos imaginar uma situação em que precisamos pegar as cidades de um estado escolhido por nosso usuário. Essa é uma situação bastante comum nos dias atuais. O usuário escolhe um Estado, nós carregamos as cidades daquele estado, e o usuário, então, escolhe a cidade.


Para isso, vou fazer um arquivo em php bem simples. Como o server-side foge do escopo deste post, vou colocar as cidades e estados como arrays mesmo.

Sendo assim, teremos 4 arquivos, a saber: ajax.js (nosso javascript), css.css (folha de estilos do nosso html), get_xml.php (gerador do xml no servidor) e teste.html (o nosso html para o exemplo).


Para realizar nossa chamada assíncrona com JQuery temos várias opções, que variam conforme sua necessidade. Vamos a algumas:

$.ajax( prop ) -> essa recebe um hash como parametro. Devemos especificar no hash as propriedades necessárias à requisição.

Ex.:


$.ajax( {type: “post”,
url: “teste.php”,
data: “parametro1=valor1¶metro2=valor2”,
success: function (result){ alert(“resultado da requisição: “+result);},
error: functin (){alert(“não deu para completar a requisição”);}
});

$.get( url, params, callback) -> uma chamada padrão do tipo “GET”. Params é um hash com pares atributo/valor para passar como parâmetros da url.


$.post( url, params, callback) -> como $.get(), mas este faz uma requisição do tipo “POST”.



Bom, já sabemos como utilizar, agora vamos ao nosso pequeno exemplo.

Começemos pelo HTML:


<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title> Teste ajax jquery </title>
<script type="text/javascript" src="jquery.js"></script>

<script type="text/javascript" src="ajax.js"></script>
<link type="text/css" href="css.css" rel="stylesheet" />
</head>
<body>

<div id="content">
<h3>Teste do ajax com jquery</h3>

<form name="form1" action="pega_valores.php">
<fieldset>
<legend>Escolha um estado abaixo:</legend>
<label for="estado">Estado:</label>
<select name="estado">

<option selected="selected">Escolha um estado</option>
<option value="sp">São Paulo</option>
<option value="rj">Rio de Janeiro</option>
<option value="mg">Minas Gerais</option>

</select>
<br />
<label for="cidade">Cidade:</label>

<select name="cidade">
<option selected="selected">Escolha uma cidade</option>

</select>
</fieldset>
</form>
<div id="loading" class="loading_hide">
Carregando...
</div>
</div>

</body>
</html>



Este é uma página simples, com um formulário com dois dropdowns e um div que será nosso "carregando...". Veja que não utilizamos nenhum evento dentro do html. Então estamos com lógica separada de conteúdo. Ótimo.

Vamos agora à nossa folha de estilos:


/* css.css */

fieldset {
border: 1px solid green;
}

legend {
color: #999;
}

#loading {
background: red;
color: white;
font-weight: bolder;
padding: 2px;
position: absolute;
left: 0;
top: 0;
}

.loading_hide {
display: none;
}




Aqui não tem muito segredo. Algumas cores, uma borda, e lá no final, a declaração que esconde o nosso "Carregando...".

Vamos ver como ficou nosso arquivo de geração de xml no servidor, em php:


<?php
$arr_cidades = array("sp" => array("São Paulo",
1 => "São Caetano",
2 => "Santo Amaro",
3 => "Santos"
), "rj" => array(
1 => "Rio de Janeiro",
2 => "Campos",
3 => "Niterói"
), "mg" => array(
1 => "Belo Horizonte",
2 => "Contagem",
3 => "Ouro preto",
4 => "Diamantina",
5 => "Poços de caldas"
)
);
if( !isset($_GET['estado']))
{
die("Erro, tente outra vez");
}
$str_estado = $_GET['estado'];
$arr_resultado_cidades = $arr_cidades[$str_estado];
header("Content-type: text/xml");
echo "<?xml version='1.0' ?>";
echo "<estado val='" . $str_estado . "'>";

foreach ( $arr_resultado_cidades as $int_index => $str_cidade)
{
echo "<cidade cdg='" . $int_index . "'>" . $str_cidade . "</cidade>";
}

echo "</estado>";
?>


Aqui também nada demais. Talvez seja até simplório demais, mas como php não é a nossa intenção neste post, fiz assim mesmo, simplificado.

Agora o que realmente faz a coisa funcionar. Nosso arquivo javascript. O script está bem comentado, então acho que não teremos muitos problemas. Veja que nosso script tem menos de 50 linhas. Se acha muito, tente fazer isso no braço e verá como ficará. :)

Nosso script:


//ajax.js
window.onload = start;

function start(){
var form1 = $("form[@name=form1]");//nosso form
var estados = form1.find("select[@name=estado]");//select dos estados

//chama a função loadCities quando o valor do select é modificado
$(estados[0]).change( function (){
loadCities( this.value);
});
}

function loadCities( estado ){
var url = "get_xml.php";
$("#loading").show("slow");//mostra o carregando...

$.get( url , {"estado": estado} , setCities);
//ajax em jquery, quando por get, use $.get(), quando por post, use $.post()
//os parametros são a url, os parametros da url, e a função callback. Se vc não fornecer os parametros da url e o segundo parametro da função
//for uma outra função, essa passa a ser a de callback.
//veja http://jquery.com/docs/AJAXModule/
}

function setCities(xmlCidades){
var cidades =$("form[@name=form1]").find("select[@name=cidade]");
xml_cidades = $("estado", xmlCidades);

cidades.empty();//tira os elementos 'antigos' do select
var oldOption = $(document.createElement("option"));//option com o valor 'Escolha uma cidade'
oldOption.append("Escolha uma cidade");//passamos o valor
//inserimos o option antigo no select
cidades.append(oldOption).change(function(){
form1.submit();
});//na hora que escolher a cidade, dispara o submit do form. O poder do encadeamento.

//colocamos as cidades no dropdown
xml_cidades.find("cidade").each( function(){
//graças ao encadeamento, criamos um elemento gastando apenas uma linha (tudo bem, quebrada para melhorar a leitura).
var nOption = $( document.createElement( "option" ) )
.val( $( this ).attr( "cdg" ) )
.append( this.childNodes[0].nodeValue );

cidades.append(nOption);
});
$("#loading").hide("slow");//esconde o carregando...
}


Simples, não?

Agora temos um dos processos mais utilizados hoje em dia, em apenas alguns minutos de códigos.

Então é isso, aproveite a biblioteca e crie outras brincadeiras, mas não esqueça de mostrar pra gente hein? :)

Até a próxima.

Marcadores: , ,

domingo, novembro 05, 2006

Efeito hover com JQuery

Dias atrás eu falei sobre a biblioteca JQuery. Hoje vou postar um exemplo bastante útil para a maioria de nós: o efeito hover em elementos que não o permitem com css puro.

Primeiramente, eu estou postando esse exemplo influenciado pela função aplicarHover(), postada pelo Jean Carlo no seu blog.

Mas mãos a obra.

Primeiro, vamos utilizar um html simples, só pra servir de referência. Queremos um efeito Hover em todas as div's com a classe comments.

O HTML:

<h3 class=”comments_title”>
comentário simples
</h3>

<div class=”comments”>
Este é apenas um comentário.
</div>


Temos então uma estrutura de comentários no HTML e queremos aplicar nesses comentários um efeito que faça trocar a cor de fundo, borda e fonte na hora que o mouse estiver sobre o elemento.

Vamos ao CSS:

h3.comments_title {
color: #82A5CB;
}

.comments {
border: 1px solid silver;
background: #E6E6E6;
color: #666;
}

.comments_hover {
border: 1px solid #6E85AF !important;
background: #B4D0F8 !important;
}

Acima temos as regras para os elementos 'normais' e os que estiverem sob a seta do mouse (comments_hover). Note o !important nas declarações do comments_hover. Isso é necessário, pois não vamos 'trocar' de classes, vamos apenas inserir e remover a classe hover, e como ela tem declarações já feitas antes, para evitar conflitos colocamos o !important.

Vamos agora ao javascript para nosso exemplo:

<!--primeiro carregamos a biblioteca JQuery -->

<script type=”text/javascript” src=”jquery.latest.js”>
</script>


<!-- agora o código que vai fazer a troca de classes conforme a mudança de estado -->

<script type=”text/javascript”>
window.onload = inicia;
function inicia(){
$(“div.comments”).mouseover(function (){
$(this).addClass(“comments_hover”);
}).mouseout(function (){
$(this).removeClass(“comments_hover”);
});
}
</script>

Pronto! Só isso tudo! Simples ou não? E o melhor: divertido. :)

Se você quiser trabalhar diferente, pode criar uma função que receba como parâmetros os tipos de elementos e a classe do estado hover, e fazer a mudança a partir daí. Por exemplo:


function setHover(elementTp, classHover){
$(elementTp).mouseover(function (){
$(this).addClass(classHover);
}).mouseout(function (){
$(this).removeClass(classHover);
});
}


então você pode usar pra fazer o efeito hover onde quiser. Veja:


setHover(“quote.livros”, “livros_hover”);

Isso vai fazer acontecer a mudança no estado over em todos os elementos quote com classe livros, adicionando/tirando a classe livros_hover

Legal, não?

Vemos que aos poucos tarefas antes bastante complexas ou demoradas ficam fáceis e as já fáceis e ágeis ficam ainda mais fáceis e ágeis com JQuery.

É isso então, vamos ver mais alguns bons exemplos de diversão com javascript e a JQuery em breve.
Até lá.

Marcadores: , ,

quarta-feira, novembro 01, 2006

JQuery: por que programar em javascript precisa ser divertido

Recentemente, quando entrei no mundo do ajax, tive contato com uma grande quantidade de frameworks. Antes eu fazia tudo na mão, até porque não fazia muita coisa: era uma troca de classes, um evento onclick, etc. Nesse contato com diversos frameworks eu me encantei com o Prototype, que era utilizado por vários outros que eu havia conhecido (script.aculo.us, mooFx, Rico, etc).

Passei a usar o Prototype em meus programas. Mas com o passar do tempo eu fui notando uma deficiência na documentação dele. Nesse período conheci o motivo deste post: a biblioteca JQuery. De cara, eu já me apaixonei pelo fato de o site da JQuery ter muita coisa falando sobre como utilizar a biblioteca, e como a falta de documentação era minha decepção com o prototype, eu resolvi testar a JQuery. Por conta daquele teste eu estou utilizando JQuery até hoje em minhas aplicações.

Mas vamos ao que interessa: afinal de contas, o que é essa tal de JQuery?
Como o próprio criador sugere: “JQuery é um novo tipo de biblioteca javascript. Não é um framework enorme, 'inflado' que promete ser o melhor em AJAX – nem é apenas um jogo de melhorias complexas e desnecessárias – JQuery foi projetado para mudar a forma como você escreve em javascript.”

JQuery é uma biblioteca que considera que “programar em javascript precisa ser divertido”. E realmente proporciona diversão a quem utilizá-la. Escrever seus códigos em javascript, como já deve ter notado, é uma terefa repetitiva. Para todo elemento que vamos pegar escrevemos uma quantidade enorme (e desnecessária) de código. JQuery elimina essas tarefas repetitivas, simplificando ao máximo a programação em javascript.

Neste momento você deve estar se perguntando: “Ora Charles, mas prototype também faz isso. Por que preciso utilizar a JQuery?”. Pois peço só mais um pouco de paciência. Já entenderá o porquê. Mas já pra matar um pouco a curiosidade, vou lhe dar um pequeno exemplo, utilizando JQuery. Vamos pegar todos os elementos “div” com a classe 'hiddenComments', adicionar a eles a classe 'showedComments', e então mostrá-los, devagar:



$(“div.hiddenComments”).addClass(“showedComments”).show(“slow”);


Simples, não? Vamos fazer com prototype?



$A(document.getElementsByClassName(“hiddenComments”)).each(function (div){
Element.removeClassName( div, “hiddenComments”);
Element.addClassName(div, “showedComments”);
Element.show(div);
});


Ainda simples, mas mais complicado não é?

Pois bem. Vamos adiante. Vou lhe explicar algumas vantagens da biblioteca JQuery, e, ao final, você terá subsídio suficiente para decidir entre ficar com prototype, que não é má escolha, e ficar com JQuery, que, na minha opinião, é a melhor escolha.

Sintaxe de seleção:
JQuery suporta a sintaxe de seleção de elementos utilizada pelas CSS de versão 1 a 3, e o básico da sintaxe XPath.

Tamanho:
JQuery tem aproximadamente 15Kb. Perfeita para aplicações que precisam utilizar pouca banda.

Compatibilidade:
JQuery é cross-browser, trabalha em, praticamente, todos os browsers atuais com suporte a javascript. São eles (os mais utilizados): Internet Explorer 5.5+, Firefox 1.0+, Safari 1.3+ e Opera 8.5+.
Outra compatibilidade muito importante: ela permite que você use o prototype também. Você só precisa incluir ele na página antes de incluir a JQuery.

Documentação:
JQuery tem uma documentação de sua API que é uma mão na roda. Muito boa. Completíssima. Você pode encontrá-la em http://jquery.com/api/. Essa é a documentação no formato texto, apesar de ser um dos formatos texto mais elegantes que já vi. Mas você também pode utilizar uma documentação auxiliar, a Visual JQuery (http://www.visualjquery.com/). É uma documentação visual, muito legal, e que quebra o galho na hora de procurar alguma coisa que você não sabe ao certo o que é. Além disso, o site ainda disponibiliza vários tutoriais e links para sites que ensinam a usar a biblioteca, além de um mapa gráfico dela.

Métodos encadeáveis:
Essa é uma grande vantagem de se trabalhar com JQuery. Todos os métodos da biblioteca retornam um objeto JQuery. Assim você pode encadear ações de forma a ter um código mais limpo. Por isso conseguimos, no exemplo acima, fazer tudo o que fizemos em apenas uma linha de código.

Plugins:
No site da biblioteca você poderá encontrar uma infinidade de plugins, bem como uma pequena explicação sobre como criar seu próprio plugin. Há plugins de todos os tipos. Exemplo disso é o JQuery Slideshow, o checkbox (que troca os checkboxes html por outros, muito mais bonitos), entre outros. Eu consegui contar (com a ajuda da própria biblioteca) 103 plugins, divididos entre as categorias “User Interface”, “JQuery Navigation”, “JQuery Forms” e “JQuery Extension”.

Humm! Muito legal, hein! Agora vamos brincar um pouco, por que ninguém é de ferro:

Vamos validar uns formulários?

Então pega ai:

O formulário:

<form>
<label for=”nome”><input id=”nome” type=”text” /><br />
<label for=”email”><input id=”email” type=”text” /><br />
<input type=”submit” value=”enviar” /><br />
</form>

A validação:

//usamos a função $(), com sintaxe simples mesmo. usamos o encadeamento para já passar um onsubmit junto da seleção do elemento
$("form").submit( function(e){
e.stopPropagation();
e.preventDefault();
if(validar(this) == false){
this.submit();
}else{
return false;
}
});

function validar ( el ){
//transformamos o elemento puro em objeto jquery
el = $(el);
//alert(el.find("input[@type=text]").size());
//find procura o elemento fornecido dentro do objeto jquery. Aceita sintaxe xpath e css
el.find( "input[@type=text]" ).each( function (){

//this chega pra gente como objeto HTMLObject, temos que fazê-lo um objeto jquery
var field = $(this);

if( field.val() == "") {

//com o encadeamento (concatenacao) podemos mudar a borda do campo vazio, e então
//criar um span de erro depois dele.
field.css({ border:"1px solid red" }).after("Preenchimento obrigatório");

field.keyup(function(){
$(this).css({border: "1px groove black"});
$("span.error").remove();//destruímos
});
return false;
}
});
return true;
}


Pronto!
Um validador de formulários, feito em uns 5 minutos. E então?
Lógico que isso também pode ser feito rápido assim com prototype também, mas já é um exemplo para você ver como funciona a JQuery no mundo real.

Com Prototype, javascript fica fácil. Com JQuery, javascript além de fácil, fica divertido.

Gostou? Então segue alguns links para você se divertir:
JQuery - http://jquery.com
JQuery blog – http://jquery.com/blog
Visual JQuery – http://visualjquery.com/
Tutoriais JQuery - http://jquery.com/docs/Tutorials/
Documentação JQuery - http://jquery.com/docs/
O criador da JQuery - http://ejohn.org/

Marcadores: , ,