BreakDance na ZonaJ

Num blog em que o texto das várias entradas tende a ser extenso (como este), a página principal começa rapidamente a ter um comprimento considerável.
Quando se pretende consultar uma entrada mais antiga só temos duas hipóteses:

  • se

    guimos o link permanente para a entrada (caixa ‘Posts Recentes’) e depois fazemos ‘back’ no browser;

  • damos ao dedo a fazer scroll na página até que a entrada fique visível.

Uma forma interessante de resolver este problema seria ter uma opção de toggle do texto das entradas, ou seja, ter uma opção para mostrar ou esconder o texto dos posts por escolha do utilizador.

Estava a matutar sobre isto enquanto admirava os tons campestres desta página e pensei que não era má ideia pôr a solução em prática.

Um requisito importante é que o teria de fazer sem alterar efectivamente a página (só para não estar a chatear o Administrador do blog durante o fim-de-semana :-) ).

Outro é que o código teria de ser suficiente pequeno para poder ser postado aqui.

Era definitivamente um bom desafio para por à prova o jQuery.

Precisava de quatro operações para concretizar as alterações:

  1. esconder inicialmente o texto das entradas e os links para tags e comentários mas não o titulo ou a informação dos autores;
  2. acrescentar à frente do nome do autor um link para permitir mostrar ou esconder o texto;
  3. associar ao evento click do link uma função para concretizar a opção do utilizador;
  4. desenvolver a função;

Usei o Firebug para analisar a estrutura do DOM da página.
Cada entrada tem uma estrutura fixa:

  1. um <h2> com o link para o titulo;
  2. um <h4> com a data do post e a identificação do autor;
  3. um <div> com a class ‘entry’ com o texto;
  4. um <p> com a class ‘tagged’ com links para as tags e comentários

Portanto, para concretizar a primeira operação só precisava de esconder os elementos com as classes ‘entry’ e ‘tagged’ que em jQuery se traduz como:
$('.entry, .tagged').hide();

Para a concretizar segunda operação acrescentei um link à frente do nome do autor, ou seja, de todos os <h4>s precedidos por <h2>s, ou em jQuery:
$('h2 ~ h4').append('<a href="javascript:void(0)" class="entryToggler">(Mostrar)</a>');

Para a terceira opção e visto que associei os links criados à class entryTogger, basta associar uma função ao evento onclick de todos os

elementos com esta classe ou em jQuery:
$('.entryToggler').click(toggleEntry);

Falta só desenvolver a função toggleEntry.

Uma vez que esta função tem acesso ao elemento anchor seleccionado pelo utilizador (this), podia usá-lo como referência para:

  1. verificar o estado da entrada a partir do texto:
    var isHidden = $(this).text().search('Mostrar')!=-1;
  2. seleccionar os elementos correspondentes ao texto e aos links para as tags e comentários:
    var x=$(this).parent().next(); x = x.add(x.next());
  3. mostrar ou esconder os elementos seleccionados:
    isHidden ? x.slideDown('slow') : x.slideUp('slow');
  4. alterar o texto do link para ficar de acordo com a operação:
    isHidden ? $(this).text('(Esconder)') : $(this).text('(Mostrar)');

e estava feito!

Como podem testar o código? É fácil:
abram a página principal do blog. (pessoal do rss, tem mesmo que ser na página principal)

Se estiverem a usar o Firebug podem copiar o código completo para a consola e executarem-no:

var toggleEntry = function(){	
	var isHidden = $(this).text().search('Mostrar')!=-1;
	var x=$(this).parent().next();
	x = x.add(x.next());
	isHidden ? x.slideDown('slow') : x.slideUp('slow');	
	isHidden ? $(this).text('(Esconder)') : $(this).text('(Mostrar)');		
};
$('.entry, .tagged').hide();
$('h2 ~ h4').append('<a href="javascript:void(0)" class="entryToggler">(Mostrar)</a>');
$('.entryToggler').click(toggleEntry);

Para os outros casos, escrevi o código todo numa só linha que podem copiar para a caixa de endereço do browser (substituindo o http://www.zonaj.org):

javascript:var toggleEntry = function(){var isHidden = $(this).text().search('Mostrar')!=-1;var x=$(this).parent().next();x = x.add(x.next());isHidden ? x.slideDown('slow') : x.slideUp('slow');isHidden ? $(this).text('(Esconder)') : $(this).text('(Mostrar)');};$('.entry, .tagged').hide();$('h2 ~ h4').append('<a href="javascript:void(0)" class="entryToggler">(Mostrar)</a>');$('.entryToggler').click(toggleEntry);void(0);

Testado com FF2, IE7 e Opera9.

É claro que tive a vantagem de não me ter de preocupar em importar o script de jQuery porque a própria página já o faz.
Caso estivesse a alterar o DOM de uma página que não use jQuery, podia fazer o mesmo tipo de alterações usando o jQuerify.

Nota 1:
Para deixar a primeira entrada sem alterações basta alterar a linha
$('.entry, .tagged').hide();
para
$('.entry, .tagged').not(':first').hide();
e a linha
$('h2 ~ h4').append('<a href="javascript:void(0)" class="entryToggler">(Mostrar)</a>');
para
$('h2 ~ h4').not(':first').append('<a href="javascript:void(0)" class="entryToggler">(Mostrar)</a>');

Nota 2:
Para remover a irritante ‘caixa picotada’ à volta do link quando este fica activo, acrescentar como ultima linha da função:
$(this).blur();

Nota 3:
O código final tem cerca de 10 (!) linhas e repeti-o 3 vezes neste post.

Nota 4:
Para ter de volta a página original basta fazer reload no browser (mesmo tendo alterado a linha de endereço).