Neste artigo vamos criar um slider de imagens utilizando apenas JavaScript e CSS3, sem nenhuma biblioteca. O resultado final é um script de aproximadamente 160 linhas e menos de 3kb minificado. Poderia ser menor do que isso, mas nosso código vai ser extensível e 100% válido em uma verificação JSLint.
Um plugin jQuery é basicamente um código que pode ser aplicado em um ou mais elementos do DOM. Para justificar sua existência, um plugin precisa ser, principalmente, flexível.
O objetivo final é podermos instanciar nosso plugin com a seguinte chamada:
Antes de tudo vamos precisar de um pequeno trecho de CSS que garantirá o estilo básico do nosso slider.
Não vou explicar muito as declarações acima já que o nosso foco principal é o código JavaScript. O mais importante é que toda a parte de animação, responsável pelas transições entre imagens, é feita via CSS3, representando um belo ganho de performance:
Pensando um pouco na composição do código do nosso plugin, vamos criar dois objetos: um que será responsável pelo plugin em si e outro para representar cada slider instanciado na página. O próximo passo, então, é criar duas funções construtoras para nossos objetos:
JSlider é o objeto do nosso plugin que armazenará um ou mais objetos JSliderStage.
O objeto JSlider possui um único método, init, responsável por inicializar nosso plugin e os objetos do tipo stage. Este método receberá um único parâmetro, o seletor no qual aplicaremos o plugin.
Não existem classes em JavaScript, tudo é um objeto. No entanto, com o uso de prototypes, conseguimos criar objetos que servem como modelos. Ao adicionar um método ao prototype de um objeto, todas as instâncias que compartilham o mesmo prototype automaticamente herdam este novo método.
Agora chegou a hora de estruturarmos o objeto responsável pelo slider em si. Vamos, antes de tudo, montar uma lista das funcionalidades a serem implementadas.
- inicialização, listando as imagens encontradas no seletor;
- construção do “palco”, definindo as dimensões de acordo com a maior foto;
- construção do “trilho” e carregamento das imagens;
- construção e inicialização da navegação entre imagens e
- carregamento de uma nova página.
O palco “esconde” boa parte do trilho que armazena as imagens, exibindo apenas a imagem atual. Ao clicar nos botões de navegação, o usuário desloca esse trilho no eixo X.
querySelectorAll
O método querySelectorAll, nativo do JavaScript, tem funcionamento parecido com um seletor jQuery, podendo receber tanto um id como uma classe. Primeiro verificamos se foi encontrado algum elemento e depois instanciamos os objetos JSliderStage para cada elemento encontrado.
1. Inicialização
A função de inicialização é responsável por configurar os valores padrões de algumas variáveis e listar as imagens disponíveis no elemento pai. Caso não exista nenhuma imagem, nosso plugin cancela qualquer execução.
2. Palco
Para construir o palco precisamos definir uma largura e uma altura máxima, baseada nas maiores imagens – é isso que o método getPageDimensions faz.
O método createStage adiciona ao DOM os elementos necessários para nosso palco e executa dois outros métodos: um para carregar o trilho e outro para carregar as imagens. Por fim, iniciamos a navegação com o método initNavigation.
createElement
Este método da API JavaScript permite a criação de elementos que depois podem ser inseridos na árvore do DOM. É recomendado, por questões de performance, finalizar toda e qualquer manipulação antes de adicionar o elemento ao DOM.
appendChild
O método appendChild adiciona um elemento criado a outro já existente na árvore do DOM. É semelhante aos métodos append/appendTo do jQuery.
3. Trilho
Nosso trilho é um elemento DIV com uma lista (UL) contendo as imagens do slider. A largura do DIV corresponde à largura da maior imagem, enquanto que a largura da lista representa a soma da largura de todas as imagens. Dessa forma, através do nosso CSS lá do início, a lista de imagens fica “escondida” atrás da DIV principal do trilho.
4. Navegação
Finalizando nosso slide, precisamos implementar a navegação entre imagens. O método initNavigation cria, caso necessário, os botões de anterior e próximo.
Já o método gotoPage é responsável por carregar a imagem correta e habilitar/desabilitar os botões de navegação de acordo com a imagem atual.
escopo
No método createNavigationButton armazenamos o objeto this na variável self. Isso é necessário porque precisamos referenciar o escopo anterior quando associamos a navegação no evento de clique dos links. Se tivéssemos utilizado diretamente o this, estaríamos referenciando o escopo do clique, o que não era nosso objetivo. Além de self, é comum encontrar nomes como instance e that em variáveis que armazenam o escopo atual de um método.
classList
A propriedade classList permite a manipulação de classes em um elemento do DOM. Podemos consultar, remover a adicionar novas classes.
TODO
É claro que o código final é bem simples, mas a ideia principal era mostrar que nem sempre precisamos utilizar jQuery em nossas aplicações, mesmo com o jQuery disponível na estrutura do projeto.
Finalizando, algumas melhorias que ficam de dever de casa para vocês:
- temporizador para trocar imagens, sendo configurável na inicialização do plugin
- suporte a browsers mais antigos, mantendo a funcionalidade
- carregamento de qualquer conteúdo nos slides, não só imagens
- navegação via teclado
- exibir miniaturas navegáveis
- escrever testes com Jasmine
Código completo do plugin
Nosso plugin em ação no jsFiddle