Mootools – Options

Através dos conceitos de reutilização de código, as funções JavaScript de hoje contém opções e mais opções para o usuário definir (ou não). Verificar cada uma dessas opções manualmente dá muito trabalho, mas a Mootools nos ajuda. Vamos ver o suporte dessa incrível biblioteca, através da classe Options.

O que faz?

A classe Options define as opções passadas pelo usuário para alguma classe. Essa definição é feita sobrescrevendo os valores padrão (caso esses sejam definidos pelo usuário) e os mantendo quando nenhuma opção correspondente é passada.

Lógico, nada muito espetacular. Isso poderia ser feito através da função $merge, da própria Mootools. Mas há mais que isso. Além de definir opções, a classe Options também vasculha-as em busca de opções que comecem com “on”, e automaticamente adicionam-as como um evento, caso a classe Events esteja implementada. É mais que apenas um $merge disfarçado…

Implementando

Mais uma vez, antes de podermos utilizar essa classe extra, devemos implementá-la em nossa classe. Novamente, utilizamos o método Class.implement.

Caso você queira utilizar o suporte a eventos, também implemente a classe Events, na mesma declaração.

myClass.implement(new Options, new Events);

Definindo Opções

Antes de tudo, é necessário definir as opções que serão utilizadas por padrão. Essas opções padrão devem estar em this.options, sendo this a nossa classe.

var SlideShow = new Class({
	"options": {
		"slides": [],
		"startSlide": 0
	},
	"initialize": function() {}
});

Para fazer a “escolha” das opções, basta utilizar o método Options.setOptions, levando como parâmetro as opções que devem sobrescrever as opções padrão. Após a chamada ao método, todas as opções estarão disponíveis em this.options. Se o usuário definir opções que não estão definidas como padrão, elas também serão adicionadas.

var SlideShow = new Class({
	"options": {
		"slides": [],
		"startSlide": 0
	},
	"initialize": function(options) {
		this.setOptions(options);
	}
});
var mySlideShow = new SlideShow({
	"slides": [$("slide-1"), $("slide-2")],
	"wrap": true
});
mySlideShow.options["startSlide"]; // 0
mySlideShow.options["wrap"]; // true, também foi adicionada

Definindo Eventos

Não há diferença quanto a adicionar opções comuns ou eventos, os dois são adicionados da mesma maneira.

var mySlideShow = new SlideShow({
	"slides": [$("slide-1"), $("slide-2")],
	"wrap": true,
	"onStart": function() {}
});

No caso de eventos, não é necessário definir uma opção padrão, já que os eventos são chamados apenas se estiverem definidos, não causando erros. Caso você considere necessário, pode-se usar Class.empty como padrão. Class.empty é apenas uma função vazia, apenas para não precisarmos nos preocupar em definir algo a ser executado.

var SlideShow = new Class({
	"options": {
		"slides": [],
		"startSlide": 0,
		"onStart": Class.empty
	},
	"initialize": function(options) {
		this.setOptions(options);
		this.fireEvent("onStart", this.options.startSlide, 10);
	}
});

Assim como as outras classes, a própria biblioteca faz grande uso de Options. É o espírito da reutilização, tanto na própria biblioteca quanto para os desenvolvedores. Até a próxima!

20 de janeiro, 2008

Mootools – Eventos

Uma função que executa quando algo começa, outra chamada quando alguma coisa termina, quando se começa o processamento ou quando… bem, você pode escolher. A Mootools permite isso, através da classe Events. Você pode implementar eventos para serem chamados quando você quiser dentro de suas funções, e é isso que mostrarei nesse post.

A classe Events permite que você defina eventos para suas próprias classes. Esses eventos podem ser chamados a qualquer momento, e também podem ser criados quantos eventos forem necessários.

Um evento pode receber qualquer nome, mas considera-se uma boa prática criar eventos que comecem com “on”, como “onClick”, “onStart”, “onEnd”… O “on” é requerido apenas se você desejar utilizar eventos juntamente com a classe Options (pretendo escrever sobre ela também).

Implementando

Para podermos utilizar a classe Events, primeiro é necessário implementá-la na classe em que se deseja utilizá-la. Isso é feito através do método Class.implement. Veja:

var SlideShow = new Class({
	"initialize": function() {}
});
SlideShow.implement(new Events);

Chamando Eventos

Após a implementação, ainda temos que fazer as chamadas aos eventos. Para isso, utilizamos o método Events.fireEvent, que agora pode ser chamado do escopo da classe, ou seja, this.fireEvent. Esse método recebe os seguintes parâmetros:

  • type: O tipo do evento (“onClick”, “onDrag” ou qualquer outro)
  • args: Argumentos a serem passados à função. Pode ser apenas um argumento ou um array contendo vários.
  • delay: Tempo, em milissegundos, que o evento deve esperar para ser disparado.
var SlideShow = new Class({
	"initialize": function() {
		this.fireEvent("onStart", null, 10);
	},
	"nextSlide": function() {
		this.currentSlide += 1;
		this.fireEvent("onChangeSlide", this.currentSlide, 10);
	}
});

Definindo Eventos

Para definir funções a serem executadas em determinado evento, utilizamos o método Events.addEvent. O método recebe como parâmetros o tipo do evento e a função que deve ser executada.

var mySlideShow = new SlideShow();
mySlideShow.addEvent("onStart", showSplashScreen);

Note que os eventos podem ser adicionados tanto na definição da classe quanto em uma de suas instâncias, como fizemos acima.

Eventos podem ter muita utilidade, e a própria biblioteca também faz bastante uso deles, como acontece nas classes Ajax e Fx. Basta ter criatividade. Até a próxima!

12 de janeiro, 2008

Documentando Scripts com ScriptDoc

Você já pensou em documentar seus scripts dentro deles mesmos em um formato padrão e ainda poder utilizar essa documentação no seu editor, contando até com auto-completar? Se você usa o Aptana, o ScriptDoc lhe provê esses recursos.

O Code Assist

Ferramentas que facilitam a vida do desenvolvedor não faltam no Aptana. O Code Assist é uma delas. Quando você digita o nome de algum objeto (document, por exemplo), ele mostra todos os métodos e propriedades disponíveis, permitindo que você complete o código sem precisar digitá-lo por inteiro. Isso também funciona para funções comuns, quando se começa a digitar seu nome.

Usando o Code Assist

Além de completar seu código, o Code Assist ainda mostra as informações sobre o método, como parâmetros, retorno, descrição e compatibilidade (no caso de métodos do JavaScript ou DOM) através de uma tooltip. Essa mesma tooltip também aparece quando se digitam os parênteses de alguma função, mostrando seus parâmetros e suas descrições.

Tooltips do Code Assist

Também é possível usar o Code Assist com seus próprios scripts, ou seja, usar toda essa facilidade juntamente com as classes, métodos e funções que você escreveu. Para usar o Code Assist com seus códigos, é necessário documentá-los através do ScriptDoc, mais uma ferramenta do Aptana.

O ScriptDoc

A documentação através do ScriptDoc funciona com blocos de comentário dentro do próprio código JavaScript, seguindo um padrão definido. Basicamente, um bloco de documentação deve ser assim:

/**
* Descrição do Código
*/

Esse bloco deve ser incluído logo acima da função que se deseja documentar, e ela será automaticamente vinculada à esse bloco de documentação pelo parser do Aptana. A primeira linha, para todos os blocos de documentação (exceto na descrição de arquivos), deve ser uma pequena descrição da classe, método ou atributo. Nas linhas seguintes podem ser incluídas tags que adicionem mais informações sobre o código.

/**
* Cria um elemento HTML
* @param {String} tagName Nome da tag a ser criada
* @return {Object} Retorna a tag criada
*/
function createHTMLElement(tagName) { }

O ScriptDoc permite várias tags, as duas usadas acima são apenas para um exemplo simples. Há uma lista compreensiva de tags na documentação do Aptana, tanto on-line quanto off-line. Veja o resultado da função documentada:

Code Assist de Função Documentada

A descrição de arquivos também pode ser feita de maneira bem semelhante, através da tag @projectDescription, e outras que também podem ser usadas no restante da documentação.

/**
* @projectDescription Descrição do Arquivo
* @author Autor
* @version 1.0
*/

Usando arquivos .sdoc

Caso você não queira que sua documentação fique diretamente no script, apenas ocupando espaço desnecessário, ela pode ser colocada em um arquivo externo, de extensão .sdoc.

Para que esse tipo de documentação funcione, é necessário criar um arquivo com o mesmo nome do script, mas com a extensão .sdoc, fazendo com que o Aptana reconheça o arquivo como sendo documentação do script.

No arquivo .sdoc, pode-se escrever a documentação normalmente, assim como seria no script. Há apenas uma modificação a ser feita: deve ser incluída a tag @id para cada bloco de documentação, e deverá haver uma tag correspondente no script (somente a tag @id). Veja um exemplo do arquivo .sdoc:

/**
* Cria um elemento HTML
* @id createHTMLElement
* @param {String} tagName Nome da tag a ser criada
* @return {Object} Retorna a tag criada
*/

E também um exemplo do script:

/**
 * @id createHTMLElement
 */
function createHTMLElement(tagName) { }

No início de ambos os arquivos também pode ser inclusa a tag @namespace, que definirá um objeto que englobará todas as funções e atributos do script. Se incluíssemos @namespace HTML em nossos exemplos, poderíamos usar tanto createHTMLElement quanto HTML.createElement. É claro que não funcionaria no script, a menos que assim quiséssemos.

É por isso que a cada dia mais gosto do Aptana, apesar de ser extremamente pesado (Aptana + WMP não dá certo). Adicionando mais tags pode-se criar uma documentação ótima para seus scripts, e de uma maneira muito simples. Também há planos de um gerador HTML para a documentação ScriptDoc, basta esperar. Pra quem não conhece o Aptana, vale o teste. Aproveitem, e até a próxima!

06 de janeiro, 2008

Mootools – Classes

A programação orientada a objetos facilita, e muito, a vida do desenvolvedor. Podemos utilizar o mesmo código em vários lugares, para diferentes situações, modificando e estendendo apenas o que for necessário, sem precisar reescrever código. A Mootools, além de todas as outras funcionalidades, contém um sistema de criação de classes muito bem-pensado. Vamos ver como escrever classes utilizando esse sistema, assim como extendê-las e herdá-las.

Por que Classes?

Classes têm algumas vantagens sobre funções independentes. Podemos modificar e reusar suas funcionalidades sem precisar modificar o código original, criar objetos que armazenam informações dentro de seu próprio escopo e também utilizar métodos relacionados ao objeto. Além disso, com classes é possível utilizar menos código em mais situações.

Um bom exemplo da implementação de classes é a própria Mootools. Boa parte do que há na biblioteca é baseado em classes, estendendo-as, modificando-as e herdando-as. Funções não são muito utilizadas pela Mootools, pois o poder da utilização das classes é muito maior.

Definindo Classes

Para definir classes com a Mootools, utilizamos o construtor Class. O construtor leva como parâmetros os métodos e atributos da classe, através de uma literal de objeto.

var Vehicle = new Class({
	"initialize": function(features) {
		// Salvando as características no escopo do objeto
		this.features = features;
		this.position = 0;
	},
	"goForward": function(distance) {
		this.position += distance;
	},
	"goBackward": function(distance) {
		this.position -= distance;
	}
});

Na classe acima, definimos três métodos: initialize, goForward e goBackward. O método initialize deve estar presente em cada definição de classe, por ser o método que é chamado quando a classe é instanciada.

Após termos criado nossa classe, podemos instanciá-la sempre que necessário.

var myVehicle = new Vehicle({"color": "red"});
// Utilizando os métodos do objeto
myVehicle.goForward(100);
// Acessando propriedades
myVehicle.position; // 100

Estendendo Classes

Como em outras linguagens orientadas a objeto, as classes podem ser estendidas para criar funcionalidades mais específicas. No caso da classe Vehicle, podemos estendê-la para criar tipos de veículos específicos, como carros e motos. Para isso, usamos o método Class.extend, levando como parâmetro os novos métodos e propriedades que a classe deve conter.

var Car = Vehicle.extend({
	// O novo método de inicialização
	"initialize": function(features) {
		// Inicializamos a classe pai dentro da classe atual
		this.parent(features);
		this.wheels = 4;
		this.gear = 0;
	},
	"gearUp": function() {
		if(this.gear < this.features.gears) this.gear++;
	},
	"gearDown": function() {
		if(this.gear > -1) this.gear--;
	}
});
var Motorcycle = Vehicle.extend({
	"initialize": function(features) {
		this.parent(features);
		this.wheels = 2;
		this.gear = 0;
	},
	"gearUp": function() {
		if(this.gear < this.features.gears) this.gear++;
	},
	"gearDown": function() {
		if(this.gear > 0) this.gear--;
	}
});

Através do código acima, criamos duas novas classes baseadas em Vehicle, Car e Motorcycle, cada uma com suas características específicas, mas herdando os métodos da classe pai.

Assim como podemos criar tipos específicos de veículos, também podemos criar tipos específicos de carros e motos, bastando estender essas duas classes. Não há limite para extensões.

Além de estender outras classes, também é possível estender a própria classe, implementando novos métodos. Note que não é necessário recriar o método Class.initialize, já que não o modificamos, apesar de ser possível se necessário.

var Car = Car.extend({
	"horn": function() {
		this.soundHorn = true;
	}
});

Implementando Novos Métodos

Ao estender classes, o método Class.extend cria uma nova cópia da classe, não alterando-a de maneira alguma. Isso é facilmente percebido, já que, em nosso exemplo, myVehicle.gearUp não funciona, pois a classe não foi modificada quando criamos as outras extensões.

Para modificar a classe sem criar uma cópia sua e sem precisar modificar código algum, a Mootools usa o método Class.implement, recebendo como parâmetros os métodos e propriedades a serem implementados.

Modificando o último exemplo, poderíamos trocar Car.extend para Car.implement, eliminando a cópia desnecessária que criamos.

Car.implement({
	"horn": function() {
		this.soundHorn = true;
	}
});

Vale lembrar que utilizando Class.implement não temos acesso ao método this.parent, já que não estamos criando uma outra classe, somente implementando propriedades. Nesse caso, não há classe pai.

O uso de classes permite muito mais do que reutilização de código. Poupa-se tempo tanto no desenvolvimento quanto no uso do código e esse uso torna-se muito mais intuitivo, já que aproxima a programação de objetos reais. Por essas e outras que sou adepto dessa maravilhosa biblioteca. Até a próxima!

01 de janeiro, 2008

ClientSide: Mostre seu Código!

Agora os desenvolvedores client-side (JavaScript, XHTML, CSS, XML e derivados) contam com mais uma fonte de informação, o ClientSide, lançado pelo Élcio, do fechaTag há alguns dias atrás.

O site é focado em “ler sobre código, ler código e colaborar”, segundo o próprio Élcio. Não há muitos posts até o momento, mas o que já foi postado, tanto pelo Élcio quanto por outros colaboradores, é um conteúdo selecionado, e de boa qualidade.

Gostei muito da política do site, bastante rígida quanto à seleção de conteúdo. Teremos uma boa referência se ela for cumprida. O cadastro e postagem são abertos a qualquer um, basta enviar bom conteúdo.

Já assinei o feed e me inscrevi. Falta acertar todos os dados do cadastro, e logo estarei postando algum conteúdo, talvez até exclusivo (se me vier alguma idéia). Se quiser, também sinta-se livre para cadastrar-se e começar a postar.

23 de dezembro, 2007