Dev (Back & Front)ARTIGO

Plugin MooTools para gerenciamento de histórico

Texto
original disponível em
http://davidwalsh.name/mootools-history

?

Uma das razões pelas quais
gosto da tecnologia AJAX é porque ela permite evitar que páginas desnecessárias
sejam carregadas. Por que carregar o cabeçalho, o rodapé, e outros dados
estáticos múltiplas vezes se eles não mudam? É um desperdício de tempo,
processamento e conexão. Infelizmente, até o momento, atualizações constantes
são a norma na internet – mas elas não precisam ser.

Christoph Pojer, um desenvolvedor MooTools,
adicionou o plugin para gerenciamento de histórico à sua biblioteca Power Tools. Ele substitui o carregamento de URLs do mesmo site fornecendo um
método para capturar cliques de links, carregar o conteúdo das páginas via AJAX
(Mootools’ Request.HTML class), modificar o objeto que guarda endereço da página para manter registros de histórico, e reavaliar conteúdos de links para
permitir que os desenvolvedores criem websites de uma página rápidos e eficientes.

Ver Demo 

O método tradicional de um sistema de histórico dinâmico com suporte do “botão voltar” sempre foi baseado no uso de JavaScript com endereços de âncora hash. Tecnologias mais novas, incluindo métodos HTML5’s window.onpopstate and history.pushState permitem opções mais confiáveis de
administrar o histórico. O plugin Moo Tools para gerenciamento de histórico suporta métodos
modernos para administração do histórico. Deixe-me mostrar como implementá-lo
rapidamente.

Estrutura HTML

O plugin para gerenciamento de histórico não necessita de nenhum ajuste
da estrutura HTML, mas pelo menos um conteúdo designado deve ser identificado;
você pode, naturalmente, ter quantas áreas de conteúdo quiser, mas
precisará de solicitações múltiplas ao AJAX para acessá-las, a menos que você
use uma solicitação Request.JSON para acessar o conteúdo de múltiplas áreas da
página. Para essa simples demonstração, definiremos um cabeçalho, um rodapé e
uma área de conteúdo:

<div id="body">

<!-- header -->
<header>
<a href="/" data-noxhr>David Walsh Blog</a> <!-- fresh page load due to "data-noxhr" -->
<div>MooTools History Plugin Demo</div>
<div>This is a simple example of the MooTools History plugin created by Christoph Pojer</div>

</header>

<!-- menu -->
<ul id="demoMenu">
<li><a href="mootools-history.php">Home</a></li>
<li><a href="mootools-history-david.php">About David Walsh</a></li>
<li><a href="mootools-history-mootools.php">About MooTools</a></li>
<li><a href="mootools-history-christoph">About Christoph Pojer</a></li>
</ul>

<!-- content area -->
<article id="contentHolder">

<!-- initial page content goes here -->

</article>


<!-- footer -->
<footer>

</footer>
</div>

A área de conteúdo é a única
parte que terá mudanças. A página deverá carregar como de costume.

O JavaScript MooTools

Considerando que o plugin MooTools para gerenciamento de histórico foi
incluído na página, há algumas poucas funções que devem ser criadas no
domready. O primeiro é um método que executará a solicitação de conteúdo quando
um link é clicado:

// Content holder (all content placed within this element)
var contentHolder = document.id("contentHolder");

// Create a Request object which will be reused when links are clicked
var request = new Request.HTML({
onSuccess: function(nodeTree,elements,html) {
// Set the content into the content holder
contentHolder.set("html",html);
// Execute directions that should be executed whenever a page changes
onPageUpdate();
}
});

// Create a function that loads the page content
var loadPage = function(url) {
// Make a HTML request to get the content for this page
request.send({ url: url });
};

O
próximo passo é a criação de um método (teoricamente opcional, mas você normalmente
vai querer fazer alguma coisa uma vez que o conteúdo tenha sido carregado) que
rodará toda vez que um conteúdo seja recebido:

// Function that will execute whenever a page gets changed
var onPageUpdate = function() {

// Do whatever you'd like here!

// Possibly manually record a Google Analytics page view?

};

O plugin MooTools para gerenciamento de histórico não solicita que
você faça qualquer coisa quando um conteúdo é recebido, mas provavelmente você
vai querer fazer alguma coisa. Por que gravar manualmente  a visualização da página dentro do Google
Analytics
?

O próximo pedaço é importante em deixar os links das páginas estáticas passarem pelo armazenador de histórico baseado em ajax. Uma única linha do Element.Delegation já consegue realizar o trabalho – não só para o carregando da página inicial, mas para todo carregamento que será executado depois disso:

// The listener that manages all clicks
var listener = function(evt){
evt.preventDefault(); // Prevent following the URL
History.push(this.get('href')); // Push the new URL into History
};

// Add event delegation to add clicks. Both of these work:
//document.body.addEvent("click:relay(a:not([href=#]):not([href^=http://]):not([data-noxhr]))",listener);
document.body.addEvent("click:relay(a:not([href=#],[href^=http://],[data-noxhr]))",listener);

Quando qualquer link que aponta para outra página é clicado, o método listener pára o evento e envia a
nova URL para o plugin, mudando a barra de endereços, administrando o clique do
botão back/forward.

Uma função back também é criada de forma que
possamos providenciar um link “back” e um link “forward”, para andar para trás
e para frente no histórico da página, se escolhermos usá-lo:

// Listener for the "Back" link
var back = function(evt){
evt.preventDefault();
History.back(); // Go back
};

// Listener for the "Forward" link
var forward = function(evt){
evt.preventDefault();
History.forward(); // Go back
};

// Add to links
document.id("backLink").addEvent("click",back);
document.id("forwardLink").addEvent("click",forward);

O
próximo passo é adicionar um evento change no próprio plugin para gerenciamento de histórico para rodar
nossa função loadPage quando a URL da página muda:

// When the history changes, update the content 
History.addEvent('change',loadPage);

Se
o cliente não suporta o método history.pushState, o plugin avalia o hash e
carrega a página como necessário:

// Handle the initial load of the page if the browser does not support pushState, check if the hash is set
if(!History.hasPushState()) {
// Check if there is a hash
var hash = document.location.hash.substr(1);
if (!hash) return;

// If the hash equals the current page, don't do anything
var path = document.location.pathname.split('/');
path = path[path.length - 1];
if (hash == path) return;

// Load the page specified in the hash
loadPage(hash);
}

Finalmente,
rodar onPageUpdate no carregamento domready não dói, uma vez que os eventos são adicionados uma
vez na onPageUpdate:

// Update the page
onPageUpdate();

Agora a página está pronta
para suportar permutas de conteúdo baseadas no plugin para gerenciamento de histórico e operadas pelo
AJAX. Graças à função onPageUptade,
links são adicionados a eventos na medida em que chegam, de modo que até os
conteúdos recuperados pelo AJAX podem ser administrados pelo plugin.

Dicas e estratégias para websites que mantêm histórico com hash 

Plugins como o do MooTools para gerenciamento de histórico, a obra prima de Christoph, são muito úteis no enriquecimento da experiência do
usuário, mas necessitam de um pouco do conhecimento da lógica do desenvolvedor:

  • Uso
    do
    Event Delegation
    – Lembre-se de que num sistema do estilo do plugin MooTools para gerenciamento de histórico, designar eventos a
    elementos diretamente pode não ser a melhor solução, porque tais elementos
    podem desaparecer no próximo clique de um link. Usar event delegation em vez de tradicionalmente delegar eventos aos elementos pode lhe poupar de um
    monte de problemas. Leia o topico MooTools
    Element.Delegation
    se não
    estiver familizarizado com event delegation.
  • Não assuma suporte
    para JavaScript
    – Tenha
    em mente de que o cliente pode não suportar JavaScript. Mecanismos de busca
    adicionaram suporte para JavaScript, mas é importante usar URLs que trabalhem
    tanto em sites gerenciados pelo plugin MooTools para gerenciamento de histórico quanto em websites sem JavaScript.
  • Use detecão para AJAX – O MooTools proporciona um cabeçalho
    específico para AJAX na requisição chamada HTTP_X_REQUESTED_WITH.  Clique aqui para aprender como usá-lo para detectar
    solicitações de AJAX. Você vai querer ser capaz de detectar o AJAX de forma que
    tais solicitações simplesmente retornem o conteúdo, e não o cabeçalho ou o rodapé
    (etc) juntamente com ele. Você pode escrever um client-side script/regex para
    analisar o conteúdo, mas isso é muito ineficiente. Meu demo usa PHP para
    armazenar o conteúdo da página em variáveis, como segue:
// Load pages based on querystring
$qstring = $_SERVER['QUERY_STRING'];
if($qstring == 'home' || $qstring == '') {
$content.= '<h1>Welcome Home!</h1>';
$content.= '<p>History Management via popstate or hashchange. Replaces the URL of the page without a reload and falls back to Hashchange on older browsers.</p><p>This demo page aims to teach you how you can use Christoph Pojer's outstanding History widget to load only the content you need, dynamically and reliably.</p>';
}
elseif($qstring == 'about-david') {
$content.= '<h1>About David Walsh</h1>';
$content.= '<p>My name is David Walsh. I'm a 27 year old Web Developer from Madison, Wisconsin. In the web world, I am:</p>
<ul>
<li>Founder and Lead Developer for Wynq Web Labs.</li>
<li>Software Engineer for SitePen.</li>
<li>Core Developer for the MooTools JavaScript framework.</li>
<li>Co-Founder of Script & Style, a website aimed at making web developers and designers better.</li>
</ul>
<p>I don't design the websites - I make them work.</p>
<p>I am also an admirer of the great <a href="?about-christoph">Christoph Pojer!</a>.</p>';
}
// and more....
// Page not found
else {
$content.= '<h1>Page Not Found</h1>';
$content.= '<p>The page you were attempting to find could not be found.</p>';
}

// If request was via AJAX, push it out.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
echo $content;
exit();
}

Obviamente
seu sistema estará buscando conteúdo de um banco de dados ou outros arquivos
estáticos, mas você entende o ponto – carregar o conteúdo antes de qualquer saída de página, aspirar para o AJAX e distribuir o conteúdo condizente. Se
não for uma solicitação AJAX, você deve distribuir o conteúdo dentro das áreas
de conteúdo do HTML, via métodos tradicionais.

Essas dicas devem bastar para
colocá-lo em condições de usar um sistema baseado no plugin MooTools para gerenciamento de histórico. Lembre-se de que o
JavaScript visa a melhorias – tenha em mente de que seu usuário (ou mecanismo de
busca) pode não suportar JavaScript e, sendo assim, certifique-se testando seu
website extensivamente!

Teste o exemplo. Clique de
página em página, use o back button, dê refresh na página etc. O plugin MooTools para gerenciamento de histórico é
sólido como uma rocha!

É desenvolvedor web e engenheiro de software. Atualmente, é desenvolvedor web sênior e evangelista na Mozilla, palestrante de conferências e desenvolvedor do MooTools JavaScript Framework e de vários plugins MooTools.

Ver perfil