Criar classes em javascript – usando a Prototype

Orientação a objetos no javascript? É possível, sim. E muito necessário, ainda mais quando lidamos com projetos de grande porte.
Okey, javascript não é uma linguagem OO (abreviação para orientação a objetos). Nem tudo da orientação a objetos em javascript é possível ser implementada; alguns dos (famosos) paradigmas da OO são impossíveis de serem atingidos por limitações técnicas (por exemplo, não existe o conceito de interface, ou métodos que possam ser sobreescritos). O que não inviabiliza o uso da OO no javascript.

Se você não conhece muito de orientação a objetos, sugiro que você procure na web ou na literatura apropriada os conceitos. Esse post falará sobre o uso da (biblioteca) Prototype na ajuda a implementar a OO.

Quem já implementou do zero uma classe em javascript sabe que a dificuldade não é grande, mas que a sintaxe é meio estranha. Por exemplo, vamos criar uma classe que abstrai um objeto Pessoa:
[update]exemplo retirado do blog do Rodrigo, nesse post aqui[/update]

<script language="javascript">
function Pessoa() {
    var nome;
    var idade;
    var email;
    this.getNome = getNome;
    this.getIdade = getIdade;
    this.getEmail = getEmail;
    this.setNome = setNome;
    this.setIdade = setIdade;
    this.setEmail = setEmail;
    this.mostraValores = mostraValores;
    function getNome() {
        return nome;
    }
    function getIdade() {
        return idade;
    }
    function getEmail() {
        return email;
    }
    function setNome(_nome) {
        nome = _nome;
    }
    function setIdade(_idade) {
        idade = _idade;
    }
    function setEmail(_email) {
        email = _email;
    }
    function mostraValores() {
        return ´Nome: ´ + nome +´ Idade: ´+ idade +´ anos Email: ´+ email;
    }
}
</script>

Para consumir essa classe:

<script language="javascript">
    var pessoa = new Pessoa();
    pessoa.setNome("Rodrigo Lazoti");
    pessoa.setIdade(26);
    pessoa.setEmail("[email protected]");
    alert(pessoa.mostraValores());
</script>

Veja que essa classe mais parece um monte de codificação estruturada agrupada, nem não há um construtor para ela.

Vou direto para a codificação de como ficaria tal classe usando a Prototype:

referenciando a prototype:

<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js" type="text/javascript"/>
var Pessoa = Class.create();
Pessoa.prototype = {
    //construtor padrão
    initialize: function(nome, idade, email) {
        this.setNome(nome);
        this.setIdade(idade);
        this.setEmail(email);
    },
    setNome: function(nome) {
        this.nome = nome;
    },
    setIdade: function(idade) {
        this.idade = idade;
    },
    setEmail: function(email) {
        this.email = email;
    },
    mostraValores: function() {
        return "Nome: " + this.nome + " Idade: "+ this.idade + " anos - Email: "+ this.email;
    }
}

Quem está acostumado com OO percebe logo de cara que, dessa forma, a semântica usada é muito mais direta e clara; você sempre se refencia aos atributos da classe usando this, e você sempre é obrigado a ter um método initialize que funciona como o construtor.
Para esclarecer o código, na primeira linha é usado um objeto Class da própria prototype e chama-se o seu método create(); a partir do retorno desse método tem-se um objeto que pode ser trabalhado como uma classe da Prorotype. Vale a pena lembrar que o código usado para consumir a classe pode ser exatamente o mesmo enquanto a interface (resumidamente, assinatura dos métodos) das mesmas forem iguais.

Agora, uma coisa bacana (peguei o exemplo lá na API da Prototype) é como extender uma classe. Imagine que você quer criar a partir da classe Pessoa, uma classe Pirata; digamos que o seu Pirata é do passado, e não tem e-mail. Mas tem um navio.
O primeiro passo é extender a classe Pessoa, da seguinte forma:

var Pirata = Class.create(Pessoa, {});

Vamos ver como ficaria o código para sobreescrever o método setEmail() e adicionar um método novo:

var Pirata = Class.create(Pessoa, {
    // sobreescreve o método que define o e-mail
    setEmail: function() {
        this.email = null;
    },
    //cria um método para salvar o nome do navio dele
    setNavio: function(navio) {
        this.navio = navio;
    }
   
});

Sugiro para quem está afim de estudar mais, primeiro olhar a documentação da API da Prototype e procurar exemplos por ae na net, e depois pegar algo que você já fez e funciona e tentar reescrever, do zero, usando orientação a objetos. É uma curva de aprendizado não muito complexa, mas é uma forma bem diferente de se programar para quem não está acostumado!

[update]e é claro que eu esqueci apenas de de falar que é necessário incluir a biblioteca prototype no seu javascript. Você pode fazer download ou referenciar a mesma que é hospedada pelo Google Code[/update]

Cookies em ASP

Dando uma quebra nos textos hard-developer do @chris, resolvi escrever um post simples e rápido sobre um assunto mais simples ainda: cookies em ASP.

Uma leitura rápida sobre:

  1. O que são cookies
  2. Porquê usar cookies?
  3. Programando
    1. Criar um Cookie
    2. Configurar um Cookie
    3. Ler um Cookie
  4.  Dicas e macetes

 

O que são cookies?


Isso são cookies.

 

"Cookies" são dados que ficam armazenados no computador do usuário em formato de texto e podem ser resgatados pelo servidor em outro momento, mesmo que o usuário saia do site e feche o navegador esses dados podem ficar armazenados.

Permitir ou não o uso de cookies é uma opção do usuário e a maioria dos navegadores por padrão aceita o uso deles.

 

Porquê usar cookies?

Usar cookies ou session? Vamos lá…

A session sempre é fechada quando o usuário não está navegando no seu site, para informações que podem ficar guardadas sempre você pode (e deve) utilizar cookies.

Por exemplo, o usuário fez um comentário no seu site, a próxima vez que ele for comentar já estará gravado no formulário o seu nome e e-mail pois estes foram armazenados em cookies quando ele executou essa ação pela primeira vez.

Escrevi aqui como fazer um sistema de login em ASP que utiliza apenas session, quando o usuário fica muito tempo sem nenhuma ação ou quando ele fecha a página ele automaticamente é deslogado, se as informações fossem gravadas através de cookies ele poderia permanecer logado.

Definir quando utilizar Cookies e Sessions depende da intenção e segurança que a aplicação que está sendo desenvolvida deve ter.

 

Programando

Agora que você já sabe como funciona e quando deve ser utilizado, vamos botar a mão na massa e descobrir como criar, ler e configurar cookies em ASP[bb] . 😀

Como criar um Cookie em ASP?

Para criar um cookie em ASP é extremamente simples, vamos ao código:

<%
Response.Cookies("usuario").item("apelido") = "Guilherme Serrano"
Response.Cookies("usuario").item("site") = "https://andafter.org"
%>

Neste caso foi armazenado um cookie chamado usuario que tem dois itens, um chamado apelido com valo de Guilherme Serrano e outro chamado site com valor de https://andafter.org

 

Como configurar um Cookie em ASP?

Cookies não tem muito o que configurar, mas você pode determinar o tempo de expiração, ou seja, até quando este cookie deve ficar armazenado no computador do usuário.

<%
Response.Cookies(“usuario”).Expires = “01/07/2008”
%>

Neste exemplo você tem uma data definida para que o cookie expire, e esta linha só serve para ilustrar como funciona pois dificilmente você determina datas fixas para um cookie expirar, né?

Então você pode usar o seguinte código:

<%
Response.Cookies(“usuario”).Expires = DateAdd("d",7,Now)
%>

Agora você definiu que o cookie usuário tem 7 dias de duração, através do DateAdd. O que você fez foi somar 7 dias "d",7 a data atual Now.

 

Como ler um Cookie em ASP?

Você gravou as informações no computador do usuário, vamos ao código para receber essas informações:

<%=Request.Cookies(“usuario”).item("apelido")%>

Simples assim, usando o exemplo anterior nesse caso você teria como retorno Guilherme Serrano. Um exemplo prático, no formulário de comentar deixar preenchido com o apelido do usuário:

<form action="comentar.asp" method="post">
<input type="text" value="<%=Request.Cookies(“usuario”).item("apelido")%>">
</form>

 

Dicas e macetes

Quando você não define data de expiração o cookir funciona como uma session (chamado cookie de sessão) e é apagado logo que o usuário sai da página.

Pense bem se é melhor usas cookies ou session, cookies não oferecem segurança: as informações gravadas podem ser acessadas a qualquer momento por qualquer usuário do computador que saiba (ou não!) o que está fazendo. Não grave senhas e dados confidenciais em cookies, se isso for necessário (nunca é, pois sempre existem outros métodos) utilize algum sistema de criptografia.

Em um sistema de login por exemplo, se o usuário estiver em um computador público ele ficará logado e a próxima pessoa que acessar o site terá acesso a conta da pessoa – para evitar isso o usuário deve ter a opção ao se logar de "lembrar de mim" ou não. 😉

Para gerar corretamente cookies que utilizam variáveis dinâmicas para o nome você precisa deixar a opção Buffer como true, pra isso insira no início da página a linha:

<%
´Torna o Buffer True
Response.Buffer = True
variavel = "apelido"
´Gera um cookie com uma variável, se o buffer não estivesse como true esse cookie não seria gerado corretamente.
Response.Cookies("usuario").item("" & variavel & "") = "Guilherme Serrano"
%>

 

Bom, se alguém tiver alguma coisa para adicionar comentem aí que eu atualizo o post, certo? 😉

Mouse pads bacanas

nVidia
Apple
Jesus Shaves

 

 

Bite Earth
Color Code
Geeky Razer Mouse Pads
Firefox
Do you Yahoo
Crazy Doesn’t even begin to cover it
Neon
 
Counter Strike
Ubuntu
AT&T
BlackKnight
Bomb!
Damn Damn
Windows Vista
Dancing Figures
i am
 
Scary
 
CFeclipse
Mac Station
Accenture
AOL Search
Circuit Print
Sustaining Our World
Dell
Ubuntu
Apple
Staples
Mac OSX
Metro Map Imprint
 
Mac Tiger
Turner Diversity
Only Computer Go Down On Me ;)
Danger Skull
 
Yahoo Mouse Mat
Surf’s up Dude!
Ezine Articles Expert Author
 
Oracle
Think Different Mouse Pad
Equations
Green Green Frog
 
 
Enrich your mobility
 
Google
Color Code Hex
Binary
Half Life
IBM
White Google

Google Maps – endereços próximos

Nesse post do começo de Maio, falei sobre como usar a API do Google Maps para colocar numa página um mapa que traça uma rota entre dois endereços.

Dando continuidade, usei aquele html como base para exemplificar como usar a API se você necessitar encontrar o endereço mais próximo de uma lista de endereços; no caso abaixo, o que fiz foi plotar na tela 3 endereços (usei como exemplo os endereços de 3 SESCs aqui da capital paulista) e, quando o usuário digitar um endereço e clicar no botão, um listener para o evento onclick do mesmo busca o endereço pela API do Google Maps, faz a comparação entre as coordenadas da latitude e longitude desse endereço com os 3 dos SESCs e, aquele que for mais perto, é usado para traçar um ponto-a-ponto.

Segue, abaixo, o código html totalmente funcional. Ele está todo comentado, e fala por si só; o funcionamento é simples. *aconselho uma lida no post ao qual me referi no começo do post, caso você não esteja familiarizado com a API do Google Maps

[update]parece que havia um problema em alguns browsers dependendo da configuração dele, com o charset utilizado (os endereços com acentuação não eram localizados). Alterei para UTF-8 e upei o html para download[/update]

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Google Maps - encontrando o endereço mais próximo</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAM3tYiYBfOKmhuRiSYzXlxRSolT9dJHhqkNrIgFq9Znypr0iOlhQeBdhVvDQuPJy4hxdG187GklHLbA" type="text/javascript"></script>
<script type="text/javascript">
    var geocoder = new GClientGeocoder();
    var map;
    var directionsPanel;
    var directions;
    var gdir = new GDirections();
    var addr = new Array(3);
    var distances = new Array(3);
   
    window.onload = function() {
        //seta o país que será usado pela API
        geocoder.setBaseCountryCode("pt_BR");
        map = new GMap2(document.getElementById(´map´), { size: new GSize(710,480) })
        map.addControl(new GLargeMapControl());
        map.setCenter(new GLatLng(-23.547779, -46.639366), 12); //centro da cidade de São Paulo
       
        //mostra o endereço de 3 Sescs no mapa
        showAddress("Sesc Paulista - São Paulo/SP", 1);
        showAddress("Rua Amador Bueno, 505 - São Paulo/SP", 2); //Sesc Santo Amaro
        showAddress("Rua Clélia, 93 - São Paulo/SP", 3); //Sesc Pompéia
        //ao clicar no botão do formulário, faz a busca
        document.getElementById("trace-route").onclick = function() {
            //tenta encontrar o endereço digitado pelo usuário
            geocoder.getLocations(
                document.getElementById("from").value,
                    function(point) {
                        //marca no mapa o endereço citado
                        add_marker(point);
                        //se existir o endereço que o usuário digitou...
                        if(point.Placemark) {
                            //cria objeto GLatLng e grava a latitude/longitude do endereço digitado pelo usuário, para uso futuro
                            var b = new GLatLng(point.Placemark[0].Point.coordinates[1], point.Placemark[0].Point.coordinates[0]);
                            /*
                            variáveis que serão usadas para comparar distâncias entre coordenadas
                            de latitude e longitude
                            */
                            var smallestDist;
                            var smallestDistId;
                            //percorre lista dos 3 endereços do SESCs
                            for(var i=0; i<3; i++) {
                                var a = new GLatLng(addr[i][1], addr[i][0]);
                                /*
                                usa método da classe GLatLng() que retorna a distância, em metros, entre
                                duas coordenadas de latitude/longitude
                                */
                                var x = a.distanceFrom(b);
                                //lógica para marcar qual a menor distância entre o endereço digitado e os 3 endereços dados
                                if(x<smallestDist || i==0) {
                                    smallestDist = x;
                                    smallestDistId = i;
                                }
                            }
                            /*
                            cria um array de dois objetos GLatLng, com as coordenadas do endereço digitado pelo
                            usuário e o endereço do ponto mais próximo a esse endereço
                            */
                            var pointsArray = [new GLatLng(addr[smallestDistId][1], addr[smallestDistId][0]), b]
                            directions = new GDirections(map); //instancia objetos
                            //usa o array de pontos para traçar a rota entre os dois endereços (ou melhor, entre as duas coordenadas)
                            directions.loadFromWaypoints(pointsArray, {"locale":"pt_BR"});
                        }
                    }
              );
        }
       
    }
   
   
    function showAddress(address, k) {
      geocoder.getLocations(
        address,
        function(point) {
            add_marker(point, k);
        }
      );
    }
   
   
   
    function add_marker(response, k) {
        if(!response.Placemark) {
            return;
        }
        place = response.Placemark[0];
        if(k) {
            //grava a latitude/longitude do endereço
            addr[k-1] = place.Point.coordinates;
        }
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
        var marker = createMarker(point, place.address, k);
        map.addOverlay(marker);
    }
   
    function createMarker(point,html, k) {
        var marker = new GMarker(point, false);
        return marker;
    }
   
</script>
</head>
<body>
<div id="map"></div>
<form action="#" method="POST">
    <fieldset>
        <label for="from">ponto de partida:</label>
        <input type="text" name="from" id="from" />
    </fieldset>
    <input type="button" class="button" id="trace-route" value="achar SESC mais próximo" />
</form>
</body>
</html>

SWFObject – inserindo flash na sua página sem complicações

Há aproximadamente 2 anos, os desenvolvedores web tiveram uma grande (ou não) dor de cabeça quando a Microsoft perdeu uma disputa judicial contra uma empresa americana, chamada Eolas, a qual patenteou – simplificando o assunto – o carregamento de um plugin em um documento hipertexto. Com isso, as versões atualizadas do IE7 de lá pra cá pedem para que o usuário clique no flash para que ele comece a ser reproduzido, causando umd esconforto na experiência do usuário.

De lá pra cá, muito já se discutiu sobre como contornar essa questão, e muitas soluções já foram expostas. As mais conhecidas se baseiam em inserir o flash via javascript (e não mais escrevendo diretamente no html as tags object e embed), e com isso a tal questão do "Clique aqui para ativar" é contornada.

No começo, usava-se muito uma biblioteca javascript chamada dynActiveX.js. Depois, uma outra chamada SWFObject ficou conhecida e foi adotada pela maior parte da comunidade de desenvolvedores (vejo por aí alguns projetos que usam um plugin da jQuery para isso. Me parece uma boa também).

Uma outra vantagem de utilizar essa forma de inserir flash no seu html é que você não precisa se preocupar com todas as formalidades que a tag object necessita, nem ter que ficara duplicando todo o código dentro da tag embed (para que os browsers gecko entendem). Ou seja, write once, work always 🙂

A versão 2.0 da SWFObject foi lançada alguns meses atrás; se você usava a 1.x, terá que mudar a forma de escrever seu código. Você pode fazer o download direto do Google Code aqui.
*aproveito e deixo a dica de ler um pouco a respeito do Google Code e da Ajax Libraries aqui

Como utilizar?

Depois de fazer download do arquivo, você pode usar esse código mínimo como exemplo:

<html>
<head>
<script type="text/javascript" src="swfobject.js"></script>
</head>
<body>
<div id="flashcontent">
  Esse btexto é substituído pelo Flash
</div>
<script type="text/javascript">
   var so = new SWFObject("movie.swf", "meuflashvideo", "400", "200", "8", "#336699");
   so.write("flashcontent");
</script>
</body>
</html>

O que é feito, basicamente, é que o javascript insere dentro da div com id="flashcontent" o código necessário para inserir o flash troca a div com o id="flashcontent" pelo código necessário para inserir o flash (obrigado @rulico pela correção, na 1.x é que funcionava dessa outra forma!).
Segundo a documentação do SWFObject, você pode parametrizar o flash da seguinte forma:

var so = new SWFObject(swf, id, width, height, version, background-color
[, quality, xiRedirectUrl, redirectUrl]);

 

Onde:

  • swf: é o caminho do arquivo .swf
  • id: id do objeto, para tratamento javascript
  • width: largura do swf
  • height: altura do swf
  • version: versão necessária do Flash Player necessária (ver a documentação oficial para mais detalhes)
  • background-color: cor de fundo do Flash, em hexadecimal

 

Existem ainda os parâmetros opcionais:

  • quality: a qualidade que deve ser usada. Por padrão, é usado o valor high
  • xiRedirectUrl: url para onde o usuário que fez o download do flash player pelo Expressinstall
  • redirectUrl: use se você quise redirecionar o usuário que não tem a versão correta do flash player para alguma página

 

Definindo outros atributos e passando variáveis

Caso seja necessário, você pode definir outros atributos usando o método setAttribute. A sintaze é a seguinte:

so.setAttribute("parametro", "valor");

Você pode passar quantos atributos quiser, é só replicar esse código.
Pode ser necessário também passar variáveis para o seu flash. Siga o seguinte código como base:

so.addVariable("nome da variável", "valor");

Qualquer coisa, vejam na documentação oficial um how-to com todos os detalhes e um FAQ bem completo a respeito 🙂

[update]Gerador de código para inserir o SWFObject (by @rulico): http://www.swffix.org/swfobject/generator/[/update]