Recentemente os colegas do blog Problogdesign publicaram uma matéria bem interessante sobre como carregar os próximos conteúdos do seu blog WordPress usando Ajax. Para quem não sabe, Ajax é uma linguagem de programação que lhe permite poupar imenso tempo no carregamento de páginas e pedidos junto do seu servidor. O artigo explica como criar um plugin de raíz para substituir o seu link “Postagens mais Antigas” ou mesmo um outro plugin que você esteja usando como por exemplo o WP-Pagenavi para criar uma navegação, por um simples botão que lhe permite visualizar em tempo real as próximas postagens do seu blog WordPress, tal como acontece com o Twitter ou Facebook.

Pode visualizar a demo do plugin e ver a versão final do projeto se desejar. Pode ainda descarregar todos os ficheiros compilados num plugin aqui! (Faça o upload e ative-o).

Vamos então iniciar o nosso tutorial. O plugin que pretendemos desenvolver irá fazer o seguinte:

  • Múltiplos cliques – O primeiro clique abre a segunda página de posts, o segundo clique abre a terceira página de posts, etc.)
  • Verificar por postagens primeiro – Se não existirem mais posts para carregar, o usuário é avisado.
  • Não usar o plugin – Se um usuário não usar JavaScript, o site não será modificado de forma alguma.

ESTRUTURA DO PLUGIN

Irão existir 3 ficheiros no plugin (um PHP, um CSS, um JS). Para manter as boas práticas, iremos manter os ficheiros CSS e JavaScript nas suas próprias pastas. E vamos chamar o plugin de “pbd-ajax-load-posts”.

Agora vamos começar pelas partes necessárias no topo do nosso ficheiro pbd-ajax-load-posts.php:

<?php
/**
 * Plugin Name: PBD AJAX Load Posts
 * Plugin URI: http://www.escolawp.com/
 * Description: Load the next page of posts with AJAX.
 * Version: 0.1
 * Author: Pro Blog Design
 * Author URI: http://www.problogdesign.com/
 * License: GPLv2
 */

CARREGAR FICHEIROS E VALORES DE PASSAGEM

A primeira coisa que precisamos fazer é garantir que os nossos ficheiros JavaScript e CSS files são carregados nas páginas corretas. Mantenha-se em seu ficheiro pbd-ajax-load-posts.php e cole dentro dele o seguinte código:

/**
  * Initialization. Add our script if needed on this page.
  */
 function pbd_alp_init() {
 	global $wp_query;

 	// Add code to index pages.
 	if( !is_singular() ) {	
 		// Queue JS and CSS
 		wp_enqueue_script(
 			'pbd-alp-load-posts',
 			plugin_dir_url( __FILE__ ) . 'js/load-posts.js',
 			array('jquery'),
 			'1.0',
 			true
 		);

 		wp_enqueue_style(
 			'pbd-alp-style',
 			plugin_dir_url( __FILE__ ) . 'css/style.css',
 			false,
 			'1.0',
 			'all'
 		);

O código apresentado inicia com a introdução de uma nova função, pbd_alp_init() (alp = AJAX Load Posts), que mais tarde será colocada no local correto. Provavelmente irá reparar também que usámos a variável global $wp_query, a qual iremos usar no próximo passo.

A parte mais importante inicia-se na linha 8. A primeira declaração é na verdade uma declaração condicional. Isso significa que em qualquer página que não seja um artigo ou página individual, iremos correr este código.

Isto é uma forma de assegurarmos que o nosso código corre corretamente na homepage, páginas de tags, páginas de pesquisa, etc. Poderá adaptá-lo para ser mais específico, e.x. se você não desejar inclui-lo na sua homepage.

Depois disso usamos as funções wp_enqueue_script() e wp_enqueue_style() para dizermos ao WordPress sobre os nossos dois ficheiros (como também que iremos usar jQuery).

Agora, precisamos passar alguns valores ao nosso script, nomeadamente:

  • O número de página em que estamos no momento.
  • O número total de páginas.
  • O link para a próxima página.

Iremos usar a função wp_localize_script() para calcular todos ests valores no PHP, e depois mostrá-los na nossa página web de forma a que o nosso script possa acessá-los mais tarde.

// What page are we on? And what is the pages limit?
$max = $wp_query->max_num_pages;
$paged = ( get_query_var('paged') > 1 ) ? get_query_var('paged') : 1;

// Add some parameters for the JS.
wp_localize_script(
	'pbd-alp-load-posts',
	'pbd_alp',
	array(
		'startPage' => $paged,
		'maxPages' => $max,
		'nextLink' => next_posts($max, false)
	)
);

Iremos trabalhar primeiro dois valores. $max é o número máximo de páginas que a query pode retornar (ex. se cada página mostra 5 posts e existem 12 posts na categoria, o nosso máximo serão 3).

A variável $paged irá guardar a página em que nos encontramos (O objetivo do nosso plugin é garantir que o usuário nunca carrega uma segunda página).

Se saltarmos para a linha 12, você irá encontrar o nosso 3º valor (o link para a próxima página). next_posts() é uma função integrada no core do WordPress, a qual irá retornar o URL de que necessitamos.

A função wp_localize_script() é excelente porque torna bastante fácil passar valor do PHP para o JavaScript. O primeiro valor, ‘pbd-alp-load-posts’ deverá coincidir com o primeiro valor da chamada wp_enqueue_script().

O segundo valor, ‘pbd_alp’, é o nome que iremos usar no nosso JavaScript mais tarde.

Finalmente, iremos enviar uma ordem da informação. Se analisar o código-fonte do nosso HTML mais tarde, você visualizar algo parecido com isto logo antes do nosso ficheiro JavaScript ser carregado:

<script type='text/javascript'>
/* <![CDATA[ */
var pbd_alp = {
	startPage: "1",
	maxPages: "6",
	nextLink: "http://www.problogdesign.com/demo/ajax-load-posts/page/2/"
};
/* ]]> */
</script>

Agora, apenas necessitamos encerrar a nossa declaração “If”, a nossa função pbd_alp_init(), e depois colocar tudo no seu devido lugar.

 	}
 }
 add_action('template_redirect', 'pbd_alp_init');

jQUERY – O CORAÇÃO DO PLUGIN

Agora que já carregámos os nossos scripts e passámos os valores que necessitávamos, é altura de avançarmos para a parte mais interessante do nosso tutorial.

Abra o ficheiro load-posts.js. A primeira coisa que precisamos fazer é acessar as 3 variáveis que passámos na nossa função PHP.

jQuery(document).ready(function($) {

	// The number of the next page to load (/page/x/).
	var pageNum = parseInt(pbd_alp.startPage) + 1;

	// The maximum number of pages the current query can return.
	var max = parseInt(pbd_alp.maxPages);

	// The link of the next page of posts.
	var nextLink = pbd_alp.nextLink;

A foma de acessarmos aos nossos valores é usando o formato: pbd_alp.valueName (pbd_alp foi o segundo valor que introduzimos no wp_localize_script(), lembra?).

O mais importante a lembrar é que os nossos números foram enviados como strings, portanto, usamos a função JavaScript’s parseInt() function para voltar a convertê-los em números.

Com o pageNum, adicionamos um ao número uma vez que ele vai guardar o número da próxima página a carregar (Não a página atual).

A grande maioria dos templates wordpress já tem navegação entre as páginas, na forma de links Artigos Antigos/Novos Artigos. Nós queremos substituir isso pelo nosso botão AJAX, pelo que o nosso primeiro passo é substituir esses links pelo nosso próprio botão.

/**
 * Replace the traditional navigation with our own,
 * but only if there is at least one page of new posts to load.
 */
if(pageNum <= max) {
	// Insert the "More Posts" link.
	$('#content')
		.append('<div class="pbd-alp-placeholder-'+ pageNum +'"></div>')
		.append('<p id="pbd-alp-load-posts"><a href="#">Load More Posts</a></p>');

	// Remove the traditional navigation.
	$('.navigation').remove();
}

Começamos com uma verificação da condicional. Lembre-se que o pageNum é o número da página seguinte, e caso seja maior que o max, significa que não existem mais páginas para carregar. Nesse caso, nós não queremos que apareça o nosso botão.

No caso de existir mais conteúdos para carregar, procuramos pela div #content, e adicionamos-lhe duas coisas no final. A primeira é uma div vazia, que iremos usar mais à frente para adicionar as nossas postagens.

A segunda é o nosso botão (um link regular HTML), envolvido num parágrafo.

Finalmente, procuramos pela div .navigation e removê-mo-la. Se o nosso template usar uma class diferente para os botões de navegação, você terá de alterar isso manualmente (.navigation é o padrão nos templates de 2010). O mesmo se aplica à div #content!

O resultado do código acima é que o nosso botão já se encontra no seu lugar, embora ainda não faça nada.

E porque fizemos tudo com JavaScript, temos a certeza de que o nosso plugin não faz uso do botão quando não existem mais páginas para carregar, e também porque se o JavaScript não for carregado, o plugin não faz rigorosamente nada.

Agora, vamos avançar para a funcionalidade quando o usuário clica no botão.

/**
 * Load new posts when the link is clicked.
 */
$('#pbd-alp-load-posts a').click(function() {

	// Are there more posts to load?
	if(pageNum <= max) {

		// Show that we're working.
		$(this).text('Loading posts...');

A primeira linha deste código é a manipulação de um evento com jQuery, que corre quando o usuário clica no botão.

Na linha 7, voltamos a correr a mesma verificação como anteriormente. Isto é importante porque o nosso script iria carregar uma mensagem de erro 404 caso não existam mais artigos para carregar. Isso nós não queremos!

A linha 10 atualiza o texto do nosso botão para “Loading posts…” Isto é interessante porque o usuário recebe imediatamente uma mensagem assim que carrega no botão.

O próximo passo é fazer a chamada em AJAX. Uma série de coisas acontecem aqui, portanto copie e cole o seguinte código para o seu script e depois explicaremos tudo mais à frente.

$('.pbd-alp-placeholder-'+ pageNum).load(nextLink + ' .post',
	function() {
		// Update page number and nextLink.
		pageNum++;
		nextLink = nextLink.replace(/\/page\/[0-9]?/, '/page/'+ pageNum);

		// Add a new placeholder, for when user clicks again.
		$('#pbd-alp-load-posts')
			.before('<div class="pbd-alp-placeholder-'+ pageNum +'"></div>')

		// Update the button message.
		if(pageNum <= max) {
			$('#pbd-alp-load-posts a').text('Load More Posts');
		} else {
			$('#pbd-alp-load-posts a').text('No more posts to load.');
		}
	}
);

A primeira linha é a mais importante. Iremos usar um seletor jQuery para seleccionar o espaço reservado à nossa div. A razão pela qual adicionámos o número pageNum ao final do nome da class é porque caso o usuário volte a clicar no botão, iremos adicionar os novos posts a um novo espaço reservado (não substituindo pelos anteriores).

Na linha 2, iniciamos uma nova função que irá correr assim que a chamada AJAX termine. A primeira coisa que faz é atualizar os nossos valores para a próxima vez que o botão for clicado.

O pageNum é incrementado em um (para apontar para a próxima página), e o nextLink é atualizado usando uma expressão regular. Ele procura pelo URL para a /page/2/ (ou outro número), e atualiza o número da página pelo número da página seguinte.

Na linha 8, adicionamos um novo espaço reservado à nossa div. Este será usado da próxima vez que o botão for clicado.

Finalmente, na linha 12, voltamos a atualizar o texto do nosso botão. Se existirem mais artigos para serem carregados, revertemos para o texto original. Se não existirem, atualizaremos o texto indicando isso mesmo.

Agora apenas necessitamos concluir o nosso código:

		} else {
			$('#pbd-alp-load-posts a').append('.');
		}	

		return false;
	});
});

Este código inicia fechando a nossa primeira declaração “if” (existem mais páginas para carregar?). Se não existirem, ele adiciona ‘.’ ao botão da mensagem. Isto é muito simples para dar uma resposta visual ao usuário quando o botão é clicado (veja o screenshot em baixo).

ESTILIZAR

O botão está finalmente funcionando! A única coisa que está faltando é estilizá-lo. Você poderá fazê-lo da forma que bem entender usando CSS. Neste tutorial usamos CSS3 para tornar os cantos do botão redondos, e adicionar um gradiente e uma sombra.

Adicione o seguinte código ao seu ficheiro css/style.css:

#pbd-alp-load-posts a:link, #pbd-alp-load-posts a:visited {
	display: block;
	text-align: center;
	padding: 4px 0;
	color: #444;
	text-decoration: none;

	/** Rounded Corners **/
	-moz-border-radius: 8px;
	border-radius: 8px;

	/** Drop shadow **/
	-moz-box-shadow: 1px 1px 1px #999;
	-webkit-box-shadow: 1px 1px 1px #999;
	box-shadow: 1px 1px 1px #999;

	/** Gradients : http://css-tricks.com/css3-gradients/ */
	/* fallback */
	background-color: #f1f1f1;

	/* Firefox 3.6+ */
	background: -moz-linear-gradient(100% 100% 90deg, #e4e3e3, #f1f1f1);

	/* Safari 4-5, Chrome 1-9 */
	/* -webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*) */
	background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f1f1f1), to(#e4e3e3));

	/* Safari 5.1+, Chrome 10+ */
	background: -webkit-linear-gradient(#f1f1f1, #e4e3e3);

	/* Opera 11.10+ */ background: -o-linear-gradient(#f1f1f1, #e4e3e3);
}

#pbd-alp-load-posts a:hover, #pbd-alp-load-posts a:active {
	/** Drop shadow **/
	-moz-box-shadow: 1px 1px 1px #bbb;
	-webkit-box-shadow: 1px 1px 1px #bbb;
	box-shadow: 1px 1px 1px #bbb;

	/** Gradients : http://css-tricks.com/css3-gradients/ */
	/* fallback */
	background-color: #f5f5f5;

	/* Firefox 3.6+ */
	background: -moz-linear-gradient(100% 100% 90deg, #eaeaea, #f5f5f5);

	/* Safari 4-5, Chrome 1-9 */
	/* -webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*) */
	background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f5f5f5), to(#eaeaea));

	/* Safari 5.1+, Chrome 10+ */
	background: -webkit-linear-gradient(#f1f1f1, #eaeaea);

	/* Opera 11.10+ */ background: -o-linear-gradient(#f5f5f5, #eaeaea);

E está feito! Guarde o seu trabalho e ative o seu plugin.

Se desejar pode visualizar a demo do plugin e ver a versão final do projeto. Pode ainda descarregar todos os ficheiros compilados num plugin aqui! (Faça o upload e ative-o).

Este tutorial foi criado originalmente pelos colegas do Problogdesign. Visite-os!

Até Já!