Archive for the ‘JQuery’ Category
Usando o plugin timeago do JQuery no Rails
Atualizando (31/08/2008): Agora o timeago possui suporte à internacionalização, ao contrário do que está escrito abaixo (na época deste post o plugin não possuia tal recurso). Dentre os idiomas incluídos está o Português.
Na última edição do podcast do RailsEnvy, os caras falaram de um plugin bem legal para o JQuery, o timeago. A idéia desse plugin é criar elementos na página que indiquem tempo decorrido, mas por extenso. Esse tempo pode ser qualquer coisa: o tempo que uma página está aberta, a quantidade de dias que um chamado está aberto, etc. O interessante é que com o timeago, o elemento da página que exibe o intervalo de tempo é atualizado automaticamente. Se você abrir uma página e esperar tempo suficiente, verá que o texto muda. Todo o processamento ocorre do lado cliente, liberando o servidor desta tarefa.
No site do timeago existe um pequeno helper para o Rails, para gerar o html necessário de maneira bastante simples. Tudo o que você precisa fazer é incluir os arquivos javascript do jQuery (se você já usa o JRails o seu javascript_include_tag :defaults já faz isso) e o arquivo javascript do timeago.
Bom, o código do helper que existe na página do timeago é assim
def timeago(time, options = {})
options[:class] ||= "timeago"
content_tag(:abbr, time.to_s, options.merge(:title => time.getutc.iso8601)) if time
end
O que acontece é que o timeago precisa de uma string de data no formato iso8601, por exemplo 2008-07-17T09:24:17Z. O Ruby possui, na classe Time, o método Time.iso8601, o que facilita bastante nossa vida. Basta fazer meu_timestamp.iso8601 e você já tem uma string no formato iso8601 prontinha. O que o helper faz é criar uma tag “attr” e colocar no atributo “title” a string no formato iso8601.
Mas e se o atributo do meu model for uma data e não um timestamp? Ai é o pulo do gato: A classe Date não tem o método iso8601. Neste caso, vamos precisar alterar um pouco o helper, para aceitar tanto atributos que você mapeou na sua migration como :date quanto :datetime. A alteração é simples:
def timeago(time, options = {})
options[:class] ||= "timeago"
time = time.to_time unless time.kind_of?(Time)
content_tag(:abbr, time.to_s, options.merge(:title => time.getutc.iso8601)) if time
Agora basta fazer assim na sua view:
<%= timeago(@seu_objeto.um_datetime) %>
Detalhe: Óbviamente todo o texto criado pelo timeago está em inglês e não há qualquer mecanismo de internacionalização. Se você quiser deixar tudo em português (foi o que eu fiz) basta abrir o arquivo jquery.timeago.js e colocar o seu texto lá. Em por exemplo fiz assim (o arquivo é pequeno e voc com certeza irá se localizar facilmente)
//....
var words = seconds < 45 && "menos de um minuto" ||
seconds < 90 && "cerca de um minuto" ||
minutes < 45 && Math.round(minutes) + " minutos" ||
minutes < 90 && "cerca de uma hora" ||
hours < 24 && "cerca de " + Math.round(hours) + " horas" ||
hours < 48 && "um dia" ||
days < 30 && Math.floor(days) + " dias" ||
days < 60 && "cerca de um mês" ||
days < 365 && Math.floor(days / 30) + " meses" ||
years < 2 && "cerca de um ano" ||
Math.floor(years) + " anos";
//...
Helper para usar o datepicker do JQuery no Rails
Nos dois projetos Rails em que estou trabalhando atualmente deixei de usar a dupla Prototype + Scriptaculous (padrão do Rails) e instalei o plugin jrails. Esse plugin possibilita substituir o Prototype e o Scriptaculous pelo JQuery nas aplicações Rails, mantendo funcionalidade da grande maioria dos helpers para javascript (toda aquelas coisas de rjs, etc), mas gerando código javascript compatível com o JQuery.
Fiz essa mudança porque o JQuery facilita muito a criação de interfaces mais atrativas, coisa muito importante para quem cria aplicações web corporativas. Com o esquema de plugins do JQuery, é possível criar aplicações muito responsivas, funcionais e bonitas.
Recentemente foi criada uma biblioteca para o JQuery chamada JQuery-UI, ou seja, um conjunto de funcionalidades específicos para a criação de interfaces com o usuário. Um dos componentes que acho realmente interessantes nesta biblioteca é o Datepicker, o qual cria um calendário bem bacana em campos de formulário que devem receber datas.
A idéia então foi: Como usar isso “The Rails Way”, sem ter que ficar escrevendo toda hora o código javascript necessário para criar uma instância do datepicker associada a um campo dos meus formulários? Simples: Criei um helper para isso. Mais precisamente, criei um helper no ApplicationHelper, para que o código fique disponível nas views de toda a aplicação.
Vamos ao código!
module ApplicationHelper
def datepicker_tag(model, attribute, options ={}, datepicker_options = {})
field_id = "#{model}_#{attribute}"
field_name = "#{model}[#{attribute}]"
field = ::ActionView::Helpers::InstanceTag.new(model, attribute, self)
options = {:id => field_id, :name => field_name}.merge(options)
datepicker_options = options_for_javascript(datepicker_options)
js = "$(document).ready(function() { $(\"\##{field_id}\").datepicker(#{datepicker_options});});"
field.tag(:input, options) + javascript_tag(js)
end
end
O método acima cria uma tag html input e gera o código javascript necessário para fazer com que este input torne-se um datepicker. Basicamente eu utilizo helpers já existentes no Rails e crio uma instância de ActionView::Helpers::InstanceTag, a qual fica associada ao model do form. Isso é importante porque quando você precisar trazer o formulário para edição, por exemplo, o campo já virá preenchido certinho.
Em seguida utilizo essa instância para criar uma tag do tipo input e concateno a saída disso tudo com o código javascript necessário para criar um datepicker associado ao nosso input.
Notem que as opcões recebidas como argumentos do método são utilizadas para inicializar o input e o objeto javascript criados.
Os parâmetros para o método são:
model: O model que está sendo criado/editado no form.
attribute: O atributo do model ao qual o datepicker será associado
options: hash de opções que devem ser passadas para a criação do input. Basicamente as mesmas utilizadas em helpers como o text_field_tag, etc.
datapicker_options: hash com opções que serão passadas para a criação do javascript que inicializa o datepicker. Possíveis valores para este campo podem ser obtidas na documentação do datepicker.
Para usar isso, precisamos incluir os arquivos do JQuery no seu layout. Como o JQuery-UI pode ser baixado de forma personalizada, ou seja, somente os arquivos que lhe interessam (para diminuir o footprint da biblioteca), o nome dos arquivos podem variar um pouco. De qualquer forma, basta baixar os arquivos javascript necessários (o core do jquery-ui e o arquivinho para o datepicker) e os arquivos CSS. Coloque tudo em seu lugar dentro da pasta public do seu projeto e adicione tudo na sua view, usando javascript_include_tag e stylesheet_include_tag.
Considere agora que você quer criar um formulário para um (adivinhem!) aluno, e que este cara possui uma data de nascimento. Seria legal que esse campo para a data de nascimento tivesse um datepicker bonitinho né?
<% form_for(@aluno) do |form| %> <%= datepicker_tag :aluno, :nascimento, :size => 10 %> <% end %>
A saída disso é algo assim:
<input id="aluni_nascimento" name="aluno[nascimento]" size="10" />
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() { $("#aluno_nascimento").datepicker({});});
//]]>
</script>
Se quiser pode passar opções específicas do datepicker em um segundo hash.
Estou pensando em juntar isso com mais algumas coisas que usam o JQuery-UI e criar um plugin, vamos ver como anda meu tempo…


