Archive for category Idéias
Jails – Aplicação Flickr
Publicado por javiani em Idéias, Jails, Javascript, New school em maio 1, 2012
E aí meus queridos!
No post passado dei uma pequena introdução sobre meu projeto solitário Jails. Neste post gostaria de refazer aquela nossa aplicação Flickr véia que fiz na primeira conversa sobre o padrão MVC no javascript. Para quem não viu ou não se lembra, tinha feito um screencast sobre como montar uma aplicação usando alguns conceitos do MVC sob meu ponto de vista.
Ela é uma aplicação bem simples, trazendo uma lista de imagens do flickr de acordo com uma busca feita num campo de texto.
Agora com o Jails, vou refazer toda a lógica para demonstrar na prática o uso desse modesto framework. Sem muito papo, vamos à Model:
/**
* @class Model
*/
;(function(namespace){
namespace.Home = {};
Jails.extend('Model', Home.Model = {
data :{},
flickr :{
url :'http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?',
params :{
tags :'',
format : 'json'
}
}
});
})(window)
Iniciamos a variável Home que carregará as 3 camadas. Definimos uma propriedade flickr que armazenará dados como os parâmetros ajax que enviaremos para o rest do flickr e a url do ajax. tags é o parâmetro variável que pegaremos do campo de texto.
Iniciada nossa model, vamos à View:
;(function(Model){
//Static
var list, load, form;
Jails.extend('View', Home.View = {
loader :'loading',
templates :{
flickr :'<li><div class="image"><img src="@{image}" alt="@{title}" /></div></li>'
},
initialize :function(){
list = $('#list');
load = $('.load');
form = $('form');
form.submit( this.submit );
},
submit :function(){
Jails.url.redirect('/' + this.search.value);
this.search.value = '';
return false;
},
wait :function(){
load.addClass(Home.View.loader);
},
loaded :function(){
load.removeClass(Home.View.loader);
}
});
})(Home.Model)
Lá em cima pegamos a Model (já criada) como argumento para se quisermos usarmos na nossa View. Estendemos nosso objeto Home.View com o Jails, e construímos os métodos e propriedades em cima desse objeto. Percebam que iniciei 3 variáveis estáticas lá no início do código, que vão ser usadas nos métodos que criaremos na view e para que sejam visíveis à todos os métodos, precisam ser estáticas.
- list : Vai carregar o elemento dom ul. Que será a lista de imagens trazidas do flickr.
- form : O elemento formulário do html, que possui o campo de texto da pesquisa.
- load : Um div para mostrar um gif de loading enquanto o ajax está sendo processado.
Existe também uma propriedade na view chamada “loader” que possui o nome da classe a ser colocada no div para exibir o gif animado, e outra propriedade “templates” que possui o template do html que será gerado dinamicamente pelo javascript quando possuirmos o json do flickr. Reparem que há duas variáveis dentro desse template, image e title. Eles serão substituídos pelos valores do json do flickr.
No Jails toda view possui um método chamado .initialize() que é chamado automaticamente pelo framework. Lá, nós setamos as variáveis estáticas com os elementos do dom, e adicionamos o evento .submit do formulário. Este método da view vai pegar o valor do campo e redirecionar a url para o valor buscado, através do método url.redirect().
Ainda temos mais dois métodos na nossa view o .wait() e o loaded() que criei para adicionar ou remover a classe de loading do div de classe “load”.
Percebam que na View, apenas mexemos com os elementos html, guardamos em variáveis, setamos eventos e etc. Este é o papel da View na minha modesta opinião.
Certo, vamos agora pegar os dados do flickr via controller. O resultado final será passado para a view que se encarregará de printar as imagens na tela.
/**
* @class Controller
*/
;(function(Model, View){
Jails.extend('Controller', Home.Controller = {
index :function(){
get_flickr();
}
});
function get_flickr(){
var cache = Jails.get_cache('flickr');
if(cache)
View.display(cache);
else{
View.wait();
$.getJSON( Model.flickr.url, Model.flickr.params, ajax );
}
};
function ajax(response){
var
html = '', item = response.items;
for(var i = 0; i < response.items.length) ; i++){
html += View.inject({
image :item[i].media.m,
title :item[i].title,
}, View.templates.flickr);
}
View.display( html );
Jails.set_cache('flickr', html);
};
})(Home.Model, Home.View)
Novamente nós estendemos nosso objeto Home com a classe ‘Controller’ do Jails, pegamos também como parâmetro no closure nossa View e nossa Model para facilitar. Ao carregar a aplicação pela primeira vez, nós cairemos na action “index” através das rotas (Mostrarei mais pra frente).
Para não poluir muito o objeto Controller, separei em duas funções diferentes para fazer o ajax.
get_flickr() :
Pega o conteúdo do cache com flag “flickr” se existir esse conteúdo ele o manda pra view mostrar.
Caso contrário, ele faz uma requisição ajax para o flickr passando os valores da model contendo os parâmetros e a url do ajax. Passa também a função de nome “ajax” como callback.
ajax() :
É o callback do ajax, ele pega o array de objetos retornados do flickr e itera sobre ele para montar o html final que iremos mostrar na tela. No for uso um método muito útil da View que é o .inject().
E quando eu falo que ele é útil, ele é útil mesmo, significa que raramente vai deixar de usar numa aplicação, especialmente se for uma aplicação ajax. Ele recebe dois parâmetros, um json e uma string. Ele irá retornar a string que passou substituindo wildcards como “@{nome}” pelo valor reespectivo no json.
e.g {nome :’Eduardo’}.
Vejam que no for, não passei uma string enorme e feiosa, passei a propriedade da nossa view que carrega essa string feiosa. Fica muito mais limpo o código, mais organizado, uma vez que a parte de “mostrar” deve ser centralizada na view. A variável “html” concatena a cada passo a string com o novo item do array através do operador “+=”.
Ao final, mandamos essa string com o html final para a nossa view mostrar na tela. Depois ainda salvamos no cache com uma flag chamada “flickr”. Então, quando cairmos nessa rota novamente, o método .get_flickr() anteriormente citado, vai verificar se há algo no cache e enviar direto para a view sem requisitar novamente o ajax. Isso é MUITO útil quando se quer fazer aqueles esquemas de carregamento ajax de sessões no conteúdo central do seu site.
E ARROTA? BUUUUUUUURG! Nossa…foi péssimo isso…
Bom, como a action “index” da controller é chamada? Definimos isso nas rotas:
/**
* @singleton Routes
*/
;(function( namespace ){
namespace.routes = [
{ '#!/' :Home.Controller.index }
]
})(Jails)
Bem simples e intuitivo, quando cair no root do site, será executado o método .index() da Home.Controller.
Coisa fina né ? =)
Então, a aplicação ainda é inútil, uma vez que só carrega o ajax no momento que visita o site pela primeira vez, não existe a mudança do parâmetro da model para buscarmos novas imagens no ajax.
Lembram que na view, fazemos um redirect ao postar o formulário?
Esse redirect cai numa rota assim : ‘#!/minha busca’. Esta string “minha busca” precisa ser usada como parâmetro na requisição ajax para trazer as novas imagens.
Então precisamos definir uma rota nova:
/**
* @singleton Routes
*/
;(function( namespace ){
namespace.routes = [
{ '#!/:tag' :Home.Controller.tag },
{ '#!/' :Home.Controller.index }
]
})(Jails)
Só é executada uma rota apenas, e sua ordem de prioridade é maior olhando de cima para baixo. Então a nova rota precisa estar antes da rota ‘#!/’ senão ela nunca será executada. Eu poderia ter usado a mesma action index na rota e pegado o parametro de busca, mas preferi criar outra action chamada “tag” para ser mais didático =).
Criada a rota para o parâmetro, criamos a action .tag() que vai receber um parâmetro “:tag” como está ali na rota.
Jails.extend('Controller', Home.Controller = {
index :function(){
get_flickr();
},
tag :function(tag){
Model.flickr.params.tags = tag;
this.index();
}
});
Pronto! Pegamos o parametro “tag” e alteramos o valor do parâmetro do ajax contido na nossa model.
Pela natureza da organização MVC, é apenas isso que a action .tag() deve fazer, o resto é exatamente o que a index faz. Então, basta chamar a index para chamarmos o método get_flickr() para trazermos as novas imagens de acordo com a busca.
Vejam que há bastante organização e com isso reutilização de código. Além das vantagem de métodos DRY como o .inject e de otimização como o set_cache e o get_cache.
Ahh… como fica o método .display() da View?
Ela só precisa dizer que não está mais carregando e mostrar o seu conteúdo novo:
display :function(html){
var html = $(html);
this.loaded();
list.html(html);
}
O método .display() pode ser escrito com mais purpurina, poderia fazer algum efeito para mostrar as novas imagens etc.
Queria mostrar meio na prática como usar o Jails na mesma aplicação que havia feito anteriormente. Acho que agora dá pra ter uma idéia de como ele funciona e qual a lógica que usei para montar o framework. Ele é simples, leve, e te direciona à um desenvolvimento mais organizado além de tentar evitar que reescreva código à toa.
Ainda vou montar um screencast mostrando alguns métodos que não foram mostrados aqui. Tive que enxugar um pouco a aplicação do flickr para que “coubesse” no post. Eu fiz ela com mais viadagens, considerando também o caso de não haver resultados e etc. Vou deixar disponível para download para quem quiser dar uma investigada no código pra aprender um pouco mais sobre o Jails.
Um abraço.
Walking Again…
Publicado por javiani em Boas práticas, Idéias, Pensamentos em março 18, 2012
Fazanos hein meus queridos….
Estava há muito tempo sem postar, mas graças à Deus por bons motivos. Às vezes gostamos tanto do que fazemos que acabamos esquecendo de viver a vida… Por muito tempo deixei minha vida social de lado, me dedicando apenas à faculdade e ao trabalho. Isso é muito ruim…porque trabalho nós achamos outro, dinheiro nós conseguimos de uma forma ou de outra, mas infelizmente não conseguimos recuperar o tempo que perdemos… E quanto mais velhos ficamos mais isso pesa. O tempo pesa. Mais do que recuperar o tempo perdido, o difícil é aprender o que deixamos de aprender com experiências de coisas mais corriqueiras, depois de velho.
Nesses últimos anos tenho me tornado cada dia mais sênior no meu trabalho e mais júnior na vida pessoal e acadêmica…Você quando chega nesse estágio, já recusou muitas festas, muitos bares, muitas baladas porque está “cansado demais”.
Se eu pudesse dar um conselho para qualquer pessoa é que ache o equilíbrio entre as duas coisas, esse equilíbrio existe e estou começando a encontrar apenas agora. Você pode e consegue achar tempo para tudo, mesmo estudando, trabalhando, namorando, fazendo academia ao mesmo tempo, você deve conseguir tempo para tudo e precisa encontrar tempo para tudo.
Todo mundo se pergunta quem de fato é em algum momento da vida, se é nerd, se é descolado, se é isso se é aquilo, e acaba querendo ser muitas vezes aquilo que não é, para se encaixar no que é mais “Legal”. Estava passando por esta fase, e deixei de ser aquilo que eu realmente era, comecei a perder tempo na vida social e na vida profissional. Porque eu sou daquele tipo de pessoa que prefere sempre acreditar nas coisas ruins que falam sobre nós, não sei se você também é assim. Isso é muito prejudicial, porque você vai ouvir coisas boas e muitas coisas ruins de outras pessoas, inclusive daquelas que você julga ser seus amigos.
Como eu ouvi coisas do tipo: “Você nunca vai conseguir…”, “Não é para você”, “Você é isso”, “Você é aquilo” . Você acaba desistindo de muita coisa ou deixando de conseguir muitas coisas…antes mesmo de tentar. As pessoas não gostam de ter alguém que tenha mais coisas ou que consiga mais coisas do que elas, uma forma de tentar sabotar isso é te falar o quão nada você é.
Sempre ouvi nos meios de comunicação sobre “Você precisa acreditar mais em você” ou “Não ligue para o que os outros pensam” coisas desse tipo. Para mim eram apenas frases clichês que todo mundo que conseguia alguma coisa ou conseguia chegar à algum lugar, falava para desabafar. Hoje isso faz muito sentido e acabo percebendo que aquilo que eu havia dito no parágrafo acima é verdade não só para mim como para todo mundo.
O fato é que você pode ser o que quiser ser, mas o mais importante é fazer o que gosta e deixar os esteriótipos de lado. Era o que eu estava fazendo nesse tempo todo longe do blog, correndo atrás de muitas coisas que havia deixado de lado. Comecei a perceber, que poderia conseguir ser bem sucedido na vida social, na vida profissional, na vida acadêmica se quisesse, pra isso precisava esquecer tudo aquilo que ouvi e ouço e comecei a fazer tudo o que senti vontade de fazer . E estou fazendo.
Não vou dizer que me dei bem em tudo e estou com a vida perfeita, mas enfrento os fracassos e decepções muito mais do que antes e isso é EXTREMAMENTE IMPORTANTE para ser bem sucedido em qualquer coisa. Você precisa fracassar, você precisa saber enfrentar as coisas para poder ter coragem de ousar. Se não fracassa é porque não tenta, se não tenta, nào conseguirá nada.
Um colega do trabalho me passou uma série de vídeos do site papodehomem.com.br muito bons sobre motivação, e era o que eu estava precisando, acho que nem ele sabe o quão importante foi para mim aqueles vídeos. Enfim, acho que são bem conhecidos hoje, mas vale muito a pena deixar aqui no blog caso alguém ainda não tenha visto. Eu aconselho ver todos e todos os dias.
Bom, é sobre isso que se trata o post de hoje, não sobre trabalho, não sobre algoritmos, sobre uma experiência da minha vida.
Queria me desculpar pela ausência, vou começar a postar coisas novas agora, e aposto que vão gostar muito do próximo post. =)
Um abraço!
http://papodehomem.com.br/listas-descaralhantes-3-videos-para-matar-a-preguica/
O Mvc e o Javascript – Na prática
Publicado por javiani em Design Pattern, Idéias, Javascript, New school em dezembro 30, 2010
Fala galera,
Eu tinha prometido uma implementação do Mvc na prática, e resolvi fazer isso através de um screencast, porque era mais fácil de explicar, mais fácil de demonstrar…
Fiz uma aplicação simples usando a API do Flickr, e fiz já considerando que conhecem o esquema Mvc que comentei no post anterior, para não perder muito tempo com explicações.
Ainda quero fazer um post mostrando a aplicação da galeria de imagens, mas vou precisar de um pouco mais de tempo para formulá-lo.
Perdoem a voz de ganso morto, mas é a voz que Deus me deu. =)
Qualquer dúvida, ou crítica, postem aqui. =P
Abraço.
Screencast : O Mvc e o Javascript – Na prática
Aprox. 15 min
Google Developer Day – Questão 5
Publicado por javiani em Idéias, Javascript, New school, Técnicas de programação em outubro 17, 2010
E aí galera, tranquilo?
Eu queria postar sobre o DevQuiz do Google faz um tempinho, em particular a questão número 5 que era um pouco mais complexa, mas não achei correto publicar a minha solução enquanto as inscrições ainda rolavam, mas agora que já elvis, gostaria de publicá-la aqui.
A história na verdade começou quando na Agência, ao saber do questionário, a galera de Interface começou a resolver as questões, cada um usando a sua lógica. No final, alguns fizeram e compartilharam suas soluções.
Eu achei interessante isso, porque saiu um pouco da rotina meio “Fábrica de Pastel” e começamos a discutir as soluções propostas de cada um, percebemos que pensamos de forma muito diferente, não pior, não melhor, mas diferente.
Como o tempo contava na hora de responder as perguntas, não se pode criticar o código final seja lá qual for o problema, se de resolução, performance, design ou qualquer outro…
E como defensor ferrenho do Javascript, entusiasta, estudante e escritor do assunto ( já que tenho o blog ) acertei na mosca a resposta, certo?
BÉEEEEEEEEEE! FAIL!
Meu script foi considerado o mais dificil de se entender ( o que é muito subjetivo ) e no final das contas não funcionou retornando a resposta certa =\.
DAMN!!!
Maaasssss felizmente acabei aprendendo coisas interessantes nos códigos alheios, o que valeu a brincadeira.
Claro, após revisto os erros, reescrevi o código envolvendo as funções soltas em um objeto e preservei TODA a lógica, removendo as redundâncias.
O primeiro código fail foi esse:
var double_n = function(string){
return !!string.match(/1{2}|2{2}|3{2}|4{2}|5{2}|6{2}|7{2}|8{2}|9{2}|0{2}/g)
}
var soma_n = function(string){
var cont = 0
string.replace(/\d/g, function(d){
cont += +d
return d
})
return !(!!(!cont % 2))
}
var last_first = function(string){
if (string.charAt(0) == string.charAt(string.length - 1))
return false
return true
}
//Telefone é o textarea com os números
var array = $('#telefone').val().split(/\n/)
//O último elemento vinha vazio por causa do último \n
array.pop()
var contador = 0
$.each(array, function(i){
if (double_n(array[i]) && soma_n(array[i]) && last_first(array[i]))
contador++
})
console.log(contador)
Meu erro foi a mania que tenho de querer me certificar de que o retorno de uma condição retorne um valor booleano de fato ao invés de um Truthy ou Falsy. Ou seja, num retorno de string vazia, tenho a mania de transformar antes em um boolean tipo: !!”"
Com isso, errei ali no retorno da soma_n, na precedência dos operadores unários.
Mas acabei aprendendo com esse erro e além disso aprendi a melhorar minha RegExp verbosa, por uma bem mais simples na solução do líder técnico da área.
Aí vai o código reescrito com as modificações necessárias, removi algumas redundâncias, mas a lógica se mantém a mesma:
var Resolution = {
of :function(array, cont){
var el = null
var i = 0
with( this ) while( el = array[i++] )
cont += if_hasnt_dup(el) &&
if_sum_isnt_mod2(el) &&
if_last_isnt_first(el) ? 1:0
return cont
},
if_sum_isnt_mod2 :function(string){
var cont = 0
string.replace(/\d/g, function(d){ cont += +d })
return !(cont % 2)
},
if_hasnt_dup :function(string){
return !(!!string.match(/(\d)\1/g))
},
if_last_isnt_first :function(string){
return !(string.charAt(0) == string.charAt(string.length - 1))
}
}
alert( Resolution.of(arr, 0) )
Eu usei um with ali, vocês sabem que é horrível e que jamais devemos usar o with, mas eu coloquei ali para dificultar ainda mais o código rsrsrs.
Para quem programa em Javascript, a resolução do problema foi bem rápida, uma porque a própria linguagem permite isso a outra porque era só botar o código no firebug e executar! Que foi o que eu fiz e imagino que muitos outros fizeram também.
Também fiz em Ruby, usando a mesma lógica que usei em Javascript:
require 'jcode'
def sum_isnt_mod2?(string)
cont = 0
string.each_char { |c| cont+= c.to_i }
(cont%2).zero?
end
def hasnt_dup?(string)
!(string =~ /(\d)\1/)
end
def last_isnt_first?(string)
!(string[0,1] == string[-1,1])
end
def answer (arr,count)
arr.each do |v|
count += 1 if sum_isnt_mod2?(v) && hasnt_dup?(v) && last_isnt_first?(v)
end
count
end
puts answer(array, 0)
Em ambas as linguagens, resolvi considerando os números de telefones como strings ao invés de números, porque achei muito mais fácil.
Você que está lendo o blog agora, resolveu a questão? Acertou ? Errou ?
Posta sua solução nos comentários, acertando ou não tenho certeza que há algo para aprender no código, sempre há…
Se resolveu usando outra linguagem de programação, MELHOR AINDA, poste para mostrarmos as diferenças das linguagens, seria muito interessante.
Obrigado mais uma vez pela atenção galera, um grande abraço!
[Update]
A Carmen Sachetto que faz o Curso de Ciência da Computação comigo no Mackenzie, fez esta solução em Scheme!!
Muito foda, olha só:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; No peculiar condado de Compiladorshire, todos os telefones têm 6 dígitos. ;
; A companhia telefônica estabelece as seguintes regras sobre os números: ;
; Não pode haver dois dígitos consecutivos idênticos, porque isso é chato; ;
; A soma dos dígitos tem que ser par, porque isso é legal; ;
; O último dígito não pode ser igual ao primeiro, porque isso dá azar. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; função principal ;
; entrada: uma lista com listas ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (Principal lista)
(if (null? lista) '()
(if (= (Verifica (car lista)) 0) (cons (car lista) (Principal (cdr lista)))
(Principal (cdr lista)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Verifica se um numero de telefone é valido ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (Verifica lista)
(if (= (Iguais (cdr lista) (car lista))
(Epar (somaElem lista 0))
(PrimUlt (cdr lista) (car lista) (car lista))
0) 0
(if (not (= (Iguais (cdr lista) (car lista))
(Epar (somaElem lista 0))
(PrimUlt (cdr lista) (car lista) (car lista))
0) ) 1)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; verifica se ultimo elemento é igual a primeiro ;
; se ultimo elemento for igual ao primeiro, retorna 1, senão retorna 0 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (PrimUlt lista primeiro anterior)
(if (null? lista) (comparaElem primeiro anterior)
(PrimUlt (cdr lista) primeiro (car lista))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compara dois elementos ;
; se forem iguais, retorna 1 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (comparaElem a b)
(if ( = a b) 1
(if (not ( = a b)) 0)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; soma elementos de uma lista ;
; retorna soma ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (somaElem lista soma)
(if (null? lista) soma
(somaElem (cdr lista) (+ soma (car lista)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; verifica se um número é par ou não ;
; se for par retorna 0, senão retorna 1 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (EPar numero)
(if (= (remainder numero 2) 0) 0
(if (not (= (remainder numero 2) 0)) 1)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; verifica se há dois dígitos consecutivos idênticos ;
; se houver, retorna 1 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (Iguais lista anterior)
(if (null? lista) 0
(if (= anterior (car lista)) 1
(Iguais (cdr lista) (car lista)))))
Bem legal né ?!?!?!
Paginação em Javascript – Parte 1
Publicado por javiani em Do baú, Idéias, Javascript, Técnicas de programação em agosto 22, 2010
Meus queridos, devido à falta de tempo que estou tendo e um pouco de preguiça, decidi prorrogar o post da parte 2 de MVC em javascript. Eu acho muito interessante esse assunto e não posso expor minha idéia assim de qualquer jeito.
Antes, gostaria de compartilhar um código de paginação em Javascript. Gosto muito desse código porque foi o primeiro projeto que desenvolvi em Javascript quando era apenas um garoto na linguagem. Na época, num compromisso pessoal, decidi que iria sem olhar referencias na internet e sem me poluir com códigos prontos, desenvolver uma “Função” ( na época eu desenvolvia funções rsrs ) que pudesse fazer uma paginação, toda feita em Js.
Então, desenvolvi o algoritmo para a paginação por conta própria, da qual me orgulho até hoje, e depois de muito tempo, refatorei o código pela primeira vez e implementei algumas coisas de forma mais atual no que diz respeito ao desenvolvimento orientado à objetos em Js e etc.
Esta primeira refatoração fiz há algum tempinho, então é claro que é necessário uma nova revisão do código, porque ele está em algumas partes redundante e precisa de melhorias.
Decidi quebrar este post em duas partes, porque fiz uma nova versão deste código usando todos os princípios atuais e usando conceitos novos que adquiri com minha experiência na linguagem. Na segunda parte vou mostrar essa nova forma de fazer e seus prós e contras em contraste com essa versão mais antiga.
De qualquer forma na versão 1.3.2, ele em duas vezes me salvou a vida e de forma perfeita não me deixou na mão em nenhum momento. Simples, prático, rápido, me ajudou em duas aplicações bem complexas e por isso merece estar aqui.
Vamos lá à explicação de como funciona.
Sua idéia é bem simples, ele pega duas listas no html, uma que contem a classe jsP-pages, de onde vai embutir as páginas da paginação, e a outra que contem a classe jsP que contém a sua lista de itens paginados.
Se esses dois elementos não existirem ele os cria.
Então vamos ao código:
var pagination = new jsP.Class('content')
pagination . open({
$ : options,
size : pages.length,
show : 3,
iterate: function(x){
$('<li />').appendTo(this).load( pages[x] )
},
callback: function(){}
})
Então, o objeto é instanciado passando como string o id do objeto pai onde guardará a paginação, um container e ele contem apenas um método público que é o open.
O método open recebe um json com algumas opções para o desenvolvedor, são elas:
$ : um curinga, que guarda as opções dos plugins.
size: O tamanho total da quantidade da informação à ser mostrada.
show: A quantidade de informação à ser mostrada por vez na página.
iterate: A função que é chamada n vezes de acordo com o size e o show passados anteriormente, e é nessa função que você como desenvolvedor vai decidir o que será feito.
O iterate recebe um valor inteiro como argumento que são os índices dos elementos que fazem parte do conteúdo da paginação e é chamado no escopo do elemento html de classe “jsP”.
No exemplo acima, eu tenho um array contendo a url das páginas em ajax que desejo carregar. Então, se o array tiver um length igual à 6, por exemplo, haveriam duas páginas e o iterate ia ser chamado 3 vezes na primeira página e 3 vezes na segunda, variando o x de 0 à 2 no nosso caso.
O jQuery ali é bem simples, para cada página ele irá criar x li’s cujo conteúdo é carregado por ajax na url do array pages.
Importante saber é que se você tem 50 páginas, o jsPagination vai chamar apenas o iterate da página atual. Então se você clica na página 2, ele chamará o iterate de novo, x vezes. Aí está o ponto forte da classe, e até hoje eu me espanto, porque a lógica foi bem desenvolvida sendo na época em que estava engatinhando no ramo da programação. Mesmo com uma experiência maior de hoje, pouquíssimas coisas tenho desenvolvido com tamanha inteligência na lógica, claro, relativamente falando.
Voltando, o callback é uma função que é chamada no momento que a página atual da paginação é chamada e é opcional, deixei vazio ali apenas para lembrar que ele existe.
Como havia falado, existe o curinga “$” onde você configura os plugins do jsPaginator, que tem por padrão 3 plugins:
map: que recebe uma funcão que é executada para cada elemento listado na página atual.
currency: responsável por colocar uma classe na listagem de páginas da página atual. Pode ser passado um booleano true, onde o jsPagination vai colocar uma classe padrão, ou pode ser passado um json contendo uma chave “classe” e um valor do tipo string contendo o nome da classe desejado pelo programador.
nextPrev: responsável por adicionar mais dois links na lista das páginas da paginação, próximo e anterior.
Ele pode ter apenas um booleano com valor true ou false para ser usado. Ou pode receber um json contendo 5 atributos:
prev : A string que aparecerá na listagem indicando a página anterior. por default é “Anterior”.
next : A string que aparecerá na listagem indicando a página posterior. por default é “Próximo”.
clPrev : A string com o nome da classe do elemento prev. por default é “anterior”.
clNext : A string com o nome da classe do elemento posterior. por default é “proximo”.
hidePages: Recebe um booleano que define se os números das páginas devem ser ocultos, apenas permanecendo o next e prev.
Bom, sabendo tudo isso, já dá pra mostrar o resto do código de exemplo que mostrei lá em cima no começo do post, para fazer mais sentido:
var pages = [
"pages/conteudo1.htm",
"pages/conteudo2.htm",
"pages/conteudo3.htm",
"pages/conteudo4.htm",
"pages/conteudo5.htm"
]
var options = {
map:function(element){
$(element)
.css({
'border': '1px solid red',
'width' : '300px',
'height': '50px',
'margin': 'auto'
})
},
currency: true,
nextPrev: { hidePages: false}
}
var pagination = new jsP.Class('content')
pagination . open({
$ : options,
size : pages.length,
show : 3,
iterate: function(x){
$('<li />').appendTo(this).load( pages[x] )
},
callback: function(){}
})
Viram? o size seria o tamanho do array, show mostra a quantidade de elementos que quero mostrar e iterate é o corpo da função que irá criar os elementos dinamicamente =). Acho que nesse código ficou mais clara a forma como se usa o curinga, é apenas um objeto contendo opções dos plugins. Coloquei este objeto em uma variável chamada options para não poluir a chamada do método da classe.
É bem simples de ser usado…
Embora ele desempenhe bem o seu papel, ele é lento, pois mexe no DOM o tempo todo, removendo o conteúdo das duas listas e adicionando novo conteúdo sempre que é paginado.
Mostrarei como contornar este problema na próxima parte do post.
Bom, vou deixar aqui no post a última versão da classe, que está na 1.3.2.
jsPagination.zip
E para quem quer ver um exemplo prático,tem um aqui:
/jsPagination
Neste link usei um Css para a galeria de imagens, o Css Hoverbox Image Gallery que vi neste post do Danilo no TidBits.
No demo, o jsPagination ainda está numa versão mais antiga, mas suas chamadas e métodos funcionam da mesma forma, mantendo a retrocompatibilidade. Então, se achar melhor entender o código do exemplo prático, fique à vontade =).
Mas pegue o código fonte daqui que é melhor, vai estar sempre atualizado =).
Um grande abraço.
