<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JulioGreff.net &#187; histórico</title>
	<atom:link href="http://juliogreff.net/tag/historico/feed/" rel="self" type="application/rss+xml" />
	<link>http://juliogreff.net</link>
	<description>A mesma web, um novo estilo de desenvolvimento</description>
	<lastBuildDate>Sat, 07 May 2011 17:07:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Histórico para Navegação via JavaScript</title>
		<link>http://juliogreff.net/historico-para-navegacao-via-javascript/</link>
		<comments>http://juliogreff.net/historico-para-navegacao-via-javascript/#comments</comments>
		<pubDate>Tue, 05 Jun 2007 23:03:34 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Destaques]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[botão voltar]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[histórico]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/historico-para-navegacao-via-javascript/</guid>
		<description><![CDATA[Já foram criadas muitas soluções para consertar o histórico quando fazemos a navegação via JavaScript (o maior problema com Ajax): a do Cau Guanabara, a minha, a do Bermonruf, além de outras derivações juntando pedaços das três. Agora eu volto aqui não para criar uma função nova, mas sim explicar os passos para você criar [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/estatisticas-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Estatísticas para Navegação via JavaScript'>Estatísticas para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/inneroptions/' rel='bookmark' title='Permanent Link: innerOptions'>innerOptions</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Já foram criadas muitas soluções para consertar o histórico quando fazemos a navegação via JavaScript (o maior problema com Ajax): <a href="http://cauguanabara.blogsome.com" rel="external" title="Cau Guanabara">a do Cau Guanabara</a>, <a href="http://juliogreff.net/back-button-improved/" title="Back Button Improved">a minha</a>, <a href="http://bermonruf.wordpress.com/2006/11/24/solucao-simples-para-o-botao-voltar-cross-browser/" rel="friend external" title="Solução Simples para o Botão Voltar Cross Browser">a do Bermonruf</a>, além de outras derivações juntando pedaços das três. Agora eu volto aqui não para criar uma função nova, mas sim explicar os passos para você criar a sua própria função, atendendo às suas próprias necessidades.</p>
<p>Vamos resolver o problema por partes, na seguinte ordem:</p>
<ul>
<li><a href="#bookmarking">Bookmarking</a></li>
<li><a href="#historico">Histórico</a></li>
<li><a href="#correcoes-ie">Correções para o IE</a></li>
<li><a href="#aperfeicoamentos">Aperfeiçoamentos</a></li>
<li><a href="#completo">Código Completo e Uso</a></li>
</ul>
<p>Vale lembrar também que estou escrevendo códigos para cuidar do histórico para <strong>JavaScript</strong>, e não só Ajax (aliás, todas as soluções anteriores faziam isso, mas pouca gente se tocou).</p>
<h3>Código Base</h3>
<p>Usaremos a seguinte página-base para testarmos nosso script:</p>
<pre><code>&lt;html&gt;
&lt;head&gt;
&lt;title&gt;BackButton Fixes&lt;/title&gt;
&lt;script&gt;
var appHash = ""; // Não se preocupe com essa linha agora...
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;select id="select"&gt;
&lt;option value="option-0"&gt;-- Change --&lt;/option&gt;
&lt;option value="option-1"&gt;Option 1&lt;/option&gt;
&lt;option value="option-2"&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Como testaremos a navegação somente com JavaScript, não precisaremos fazer qualquer requisição Ajax. Portanto, não precisaremos de uma função para tal.</p>
<h3><a title="bookmarking" name="bookmarking"></a>Bookmarking</h3>
<p>Como na navegação via JavaScript não mudamos a URL, não podemos fazer bookmarking, já que a aplicação, sempre que acessada, estará no estado inicial. A única maneira de permitir o bookmarking seria mudando a URL.</p>
<p>Como sempre estaremos na mesma página, acrescentaremos apenas um fragmento após o nome do arquivo. Poderíamos optar pelas query strings (<code>file.ext?param=value</code>), mas elas atualizariam a página quando fossem mudadas. Então optaremos pelos hashes (<code>file.ext#hash</code>), que não atualizam a página e podem ser mudados à vontade.</p>
<p>Primeiramente, quando a página é carregada, precisamos verificar se houve bookmarking:</p>
<pre><code>function initialize() {
  var browserHash = window.location.hash.substring(1); // Hash da barra de navegação
  browserHash = (!browserHash) ? 0 : browserHash; // Hash padrão
  $("select").selectedIndex = browserHash;
}
</code></pre>
<p>Não se esqueça de modificar a tag body para <code>&lt;body onload="initialize()"&gt;</code> (nos preocuparemos com obstrusão depois), e de criar a função <code>$()</code> para pegar elementos pela ID.</p>
<p>Se especificarmos um hash &#8220;1&#8243; ou &#8220;2&#8243;, nosso select mudará quando <strong>atualizarmos</strong> a página, ele não mudará automaticamente. Mas já temos nosso bookmarking inicial.</p>
<p>Por enquanto, quando mudamos nosso select, a URL não muda. Isso significa que nosso usuário terá que adivinhar qual hash deverá usar, o que não é bom. Precisamos de uma função que mude o hash do navegador quando mudarmos as opções do select:</p>
<pre><code>function makeBookmark() {
  window.location.hash = "#" + $("select").selectedIndex; // Muda o hash da página
}
</code></pre>
<p>E também devemos modificar nosso select para <code>&lt;select id="select" onchange="makeBookmark()"&gt;</code>. Agora, toda vez que trocamos as opções do select, o hash do navegador muda para podermos fazer o bookmark mais tarde.</p>
<p>Até o presente momento, tudo funcionando no IE, no FF e no Opera. Note que no FF e Opera o histórico já é ativado, embora não faça efeito.</p>
<h3><a title="historico" name="historico"></a>Histórico</h3>
<p>Atualmente, os browsers não disparam evento algum quando voltamos ou avançamos no histórico. Sendo assim, não existe nenhuma maneira &#8220;automática&#8221; que nos ajude a verificar quando navegarmos pelo histórico.</p>
<p>Para fazer a verificação, executamos uma função em um curto intervalo de tempo. Essa função verifica se o hash do browser se refere ao estado da aplicação. Se for falso, faz as modificações necessárias.</p>
<p>Vamos começar fazendo as alterações necessárias para a função <code>initialize</code>:</p>
<pre><code>function initialize() {
  handleHistory(); // Verificação inicial
  window.setInterval(handleHistory, 100); // Intervalo para verificação
}</code></pre>
<p>Essa é a função que faz a verificação inicial e &#8220;agenda&#8221; as próximas, a cada 100 milissegundos. A função que faz a verificação é a seguinte:</p>
<pre><code>function handleHistory() {
  if(window.location.hash != appHash) { // Verificação de Estado
    appHash = window.location.hash; // Trocamos o estado da aplicação
    $("select").selectedIndex = window.location.hash.substring(1); // Trocamos a opção selecionada
  }
}
</code></pre>
<p>Ela compara o hash da aplicação (que é o <code>appHash</code>, variável global lá do início do nosso script) com o hash do browser. Se forem diferentes, faremos as adaptações, em nosso caso seria a mudança das opções do select.</p>
<p>Outra modificação necessária em nosso script será a função <code>makeBookmark</code>, que agora se chamará <code>makeHistory</code>:</p>
<pre><code>function makeHistory(newHash) {
  window.location.hash = "#" + newHash;
  appHash = newHash;
}
</code></pre>
<p>Ela será executada toda vez que mudarmos as opções do select. O select também deverá ser mudado para <code>&lt;select id="select" onchange="makeHistory(this.selectedIndex)"&gt;</code>.</p>
<p>Note que temos alguns problemas: quando no estado inicial, não temos diferença entre <code>appHash</code> e o hash do browser, fazendo com que nada aconteça (causa problemas com o uso de Ajax), e ainda não temos o funcionamento desejado nem no IE nem no Opera.</p>
<h3><a title="correcoes-ie" name="correcoes-ie"></a>Correções para o IE</h3>
<p>O IE sempre foi do contra, e ele não abriu excessão para nossa técnica anterior. Quando trocamos o hash da página, o IE não ativa o histórico, e não há maneira de contornar isso sem a gambiarra. Essa gambiarra seria o uso de um iframe escondido, do qual falaremos daqui a pouco.</p>
<p>Como você já deve ter entendido o espírito da coisa, vou postar o código inteiro, e vou explicando as linhas que forem necessárias, até porque alguém pode ter se perdido.</p>
<pre><code>var appHash = "";
var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") &gt; -1) ? true : false;
function $(id) { return document.getElementById(id); }
function makeHistory(newHash) {
  if(isIe === true)
    $("control-iframe").setAttribute("src", "control.htm?id=" + newHash);
  window.location.hash = "#" + newHash;
  appHash = newHash;
}
function handleHistory() {
  var browserHash = (hash = window.location.hash) ? hash : "#" + 1;
  if(browserHash != appHash) {
    appHash = browserHash;
    $("select").selectedIndex = browserHash.substring(1);
  }
}
function createIFrame() {
  var iFrame = document.createElement("iframe");
  iFrame.setAttribute("src", "control.htm?id=1");
  iFrame.setAttribute("id", "control-iframe");
  iFrame.style.display = "none";
  document.body.appendChild(iFrame);
}
function initialize() {
  if(isIe === true)
    createIFrame();
  handleHistory();
  window.setInterval(handleHistory, 100);
}
</code></pre>
<p>Vamos pela ordem. Na função <code>initialize</code>, criamos um iframe escondido se o browser for o IE (definido pela variável <code>isIe</code>, lá no começo), através da função <code>createIFrame</code>, sem mistério.</p>
<p>Na função <code>makeHistory</code>, trocamos a URL do iframe (se for o caso), forçando sua atualização (veremos porque mais tarde).</p>
<p>No iframe, temos o seguinte código:</p>
<pre><code>&lt;html&gt;&lt;head&gt;&lt;script type="text/javascript"&gt;
frameUrl = window.location.search.substring(4);
parentHash = (typeof(hash = parent.location.hash.substring(1)) != "undefined" ? hash : "");
if(frameUrl != "")
  parent.location.hash = frameUrl;
&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;
</code></pre>
<p>Toda vez que o iframe é atualizado (seja pelo usuário ou pela navegação no histórico), ele muda o hash da página pai, nos permitindo fazer a verificação de estados.</p>
<p>Também fiz uma pequena modificação: estado inicial (caso não haja um hash) para o FF/Opera. Na parte do IE já fiz direto.</p>
<h3><a title="aperfeicoamentos" name="aperfeicoamentos"></a>Aperfeiçoamentos</h3>
<p>Para facilitar o uso, e por causa de alguns bugs existentes, fiz algumas modificações no código ao longo do tempo. Não irei explica-las agora, isso fica para uma outra oportunidade.</p>
<p><a title="completo" name="completo"></a>O código completo do script, corrigido e atualizado, é esse:</p>
<pre><code>
var appHash = "";
var appIndex = "";
var appDefault = "home";
var appFunction = function(){};
var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") &gt; -1) ? true : false;
function $(id) { return document.getElementById(id); }
function makeHistory(newHash) {
  if(isIe === true)
    $("control-iframe").setAttribute("src", "control.htm?id=" + newHash);
  else if(newHash != appIndex)
    window.location.hash = newHash;
  else
    go2index();
}
function handleHistory() {
  var browserHash = (hash = window.location.href.split("#")[1]) ? hash : "";
  if(browserHash != appHash) {
    if(browserHash != "") {
      appFunction(browserHash);
      appHash = browserHash;
      makeHistory(browserHash);
	}
	else {
	  clearInterval(checkInterval);
	  window.location.hash = appHash;
	  makeHistory(appIndex);
	}
  }
}
function createIFrame() {
  var iFrame = document.createElement("iframe");
  iFrame.setAttribute("src", "control.htm?id=" + (hash = window.location.href.split("#")[1]) ? hash : appDefault);
  iFrame.setAttribute("id", "control-iframe");
  iFrame.style.display = "none";
  document.body.appendChild(iFrame);
}
function initialize() {
  if(isIe === true)
    createIFrame();
  checkBookmark();
  checkInterval = setInterval(handleHistory, 100);
}
function checkBookmark() {
  var browserHash = (hash = window.location.href.split("#")[1]) ? hash : "";
  window.location.hash = (browserHash == "") ? appDefault : browserHash;
}
function go2index() {
  window.location = window.location.href.split("#")[0] + "#";
  window.location.reload();
}
function goTo(strUrl) {
	window.location.hash = strUrl;
	appFunction(strUrl);
}
</code></pre>
<p>E o código do iframe control.htm é:</p>
<pre><code>&lt;html&gt;&lt;head&gt;&lt;script type="text/javascript"&gt;
frameUrl = window.location.search.substring(4);
parentHash = (typeof(hash = parent.location.href.split("#")[1]) != "undefined" ? hash : "");
if(parentHash != "" &amp;&amp; frameUrl == parent.window.appIndex)
  parent.window.go2Index();
else if(frameUrl != "" &amp;&amp; frameUrl != parent.window.appIndex)
  parent.location.hash = frameUrl;
&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;
</code></pre>
<p>Pra usar a função, você faz sua página normalmente. Você precisará criar um arquivo com todo o script acima, e inclui-lo em sua página. Você também precisará criar o arquivo control.htm, o nosso iframe.</p>
<p>No script, você poderá mudar as variáveis <code>appDefault</code> (hash inicial), <code>appIndex</code> (hash que deve atualizar a página) e <code>appFunction</code> (função que faz a navegação). Para executar sua função de navegação, chame a função <code>makeHistory</code>, passando a query string como parâmetro.</p>
<p>Simples, não? Não, mas é fácil de usar. Dúvidas, bugs, sugestões, qualquer coisa que possa ajudar, é só comentar!</p>
<h3>Créditos</h3>
<p>Não criei tudo isso do nada, me baseei em algumas idéias já existentes. As principais foram de Mike Stenhouse (idéia original), Bernardo Rufino (aperfeiçoamentos), Dekassegui (correções e personalizaçãoes), e um pouco da minha idéia quase-original também (que não me lembro o nome do sujeito que tinha postado um rascunho em um fórum por aí).</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/estatisticas-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Estatísticas para Navegação via JavaScript'>Estatísticas para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/inneroptions/' rel='bookmark' title='Permanent Link: innerOptions'>innerOptions</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/historico-para-navegacao-via-javascript/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Back Button Improved!</title>
		<link>http://juliogreff.net/back-button-improved/</link>
		<comments>http://juliogreff.net/back-button-improved/#comments</comments>
		<pubDate>Sat, 18 Nov 2006 15:05:17 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[botão voltar]]></category>
		<category><![CDATA[histórico]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=33</guid>
		<description><![CDATA[Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: Histórico para Navegação via JavaScript. Desde minha última postagem, muita coisa aconteceu&#8230; O portal Ajax Online foi hackeado (juro que não fui eu) e está fora do ar, tive a oportunidade de conhecer o IE7 (realmente [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
<li><a href='http://juliogreff.net/ajax-sem-o-x/' rel='bookmark' title='Permanent Link: Ajax sem o X'>Ajax sem o X</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>
<p>Desde minha última postagem, muita coisa aconteceu&#8230; O portal <a href="http://www.ajaxonline.com.br" rel="external friend">Ajax Online</a> foi hackeado (juro que não fui eu) e está fora do ar, tive a oportunidade de conhecer o IE7 (realmente estou atrasado nesse ponto), fui convidado para ser colunista do <a href="http://www.yourspot.com.br/programacao/" rel="external friend">yourDevelop</a>, e mais outras coisinhas.</p>
<p>Como prometi, estou postando a versão cross-browser e acessível do meu script que faz o botão voltar funcionar. Na verdade, esse script é mais uma cópia do Mike Stenhouse, mas simplifiquei muita coisa, e melhorei um pouco no que foi possível. Alguns problemas ainda persistem no IE, mas são um tanto incomuns. Não vou explicar o código, só a parte lógica, pois os códigos já foram explicados anteriormente.</p>
<p>Diferente do <a href="http://cauguanabara.blogsome.com/2006/11/15/historico-do-browser-para-navegacao-via-ajax/" rel="external">Cau Guanabara</a>, resolvi os problemas de refresh, bookmark e histórico (voltar e avançar) em um único script, funcionando em Firefox e IE. Tive a paciência de ler todo o script do <a href="http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps" rel="external">Mike Stenhouse</a> e entender todo ele, e criar um novo, simplificando alguns aspectos.</p>
<p>A lógica do Voltar-Avançar continua sempre a mesma. Manipulamos o botão através dos hashes (e iframes também, no caso do IE), que ativam o botão voltar. Neste caso, comparamos o hash da página com o local que está carregado dentro da página. Por exemplo: na barra de endereços, temos &#8220;http://localhost/index.htm#page1&#8243;, mas na página está carregado o conteúdo pertencente ao hash &#8220;page2&#8243;. Assim, quando a função &#8220;checkChanges&#8221; for executada novamente, ela vai sincronizar o hash com o conteúdo.</p>
<p>A parte do refresh e bookmarking é extremamente fácil. Quando a página é carregada, a função &#8220;checkChanges&#8221; (ou &#8220;checkBookmark&#8221;, no IE) é chamada, e apenas sincroniza o conteúdo com o hash inicial, sem mais enrolações.</p>
<h3>Modificações</h3>
<p>Em relação ao script original, modifiquei umas coisinhas. Uma delas foi a maneira como o iframe é criado. Em vez de &#8220;document.write&#8221;, usei DOM. Simples, qualquer um fazia.</p>
<p>As outras modificações, um pouco mais complicadas, se referem todas aos objetos urlFix e iFrameFix. Usei JSON em vez dos objetos como funções. Isso evita aquele &#8220;new&#8221;. Ahh! Também não usei o PageLocator.makeNewLocation. Usei window.location.hash, que faz a mesma coisa e ocupa menos código.</p>
<h3>Usando no seu site</h3>
<p>Em um comentário, perguntaram-me como proceder para utilizar o script em uma página. Acabei não explicando na hora porque ficaria muito difícil. Agora ficou fácil (nunca leram isso no Banco Postal???). Vamos lá, então.</p>
<p>Insira tudo que estiver entre as tags  no seu site, sem exceções. E insira os links normalmente também, apontando para a página que deveria ser carregada sem o uso de Ajax. Lembre-se da query string &#8220;hash=&#8221;. Dentro daquilo deve estar todas as query strings que sejam necessárias (eu sei, é difícil usar mais que uma).</p>
<p>O script fará quase tudo sozinho, você só precisará da função doGetPage. Ela será a responsável pelas requisições Ajax. Faça como uma função qualquer, passando o atributo hash como query string.</p>
<h3>E o código???</h3>
<p><del datetime="2008-10-25T19:05:57+00:00">Pensou que eu ia esquecer? Não sou tão mal assim. O código está disponível para download, zipado, <a href="http://frameworx.ueuo.com/ajaxnav.zip" rel="external me">aqui</a></del> O código acabou se perdendo no tempo e no espaço. Leia a atualização do post para algo ainda melhor! Ele <del datetime="2008-10-25T19:05:57+00:00">tem</del> tinha:</p>
<ul>
<li>A página principal index.html</li>
<li>A página mock-page.php</li>
</ul>
<p>Tudo funciona direitinho, menos doGetPage. Usei apenas para simular&#8230; Apesar de dever ser incluída, não coloquei content.php também. Por quê? Porque não faremos nada em Ajax aqui! Apenas simulando&#8230;</p>
<p><strong>[update]</strong>Dica do Dekassegui, pra retirar o bloco de script suplementar lá embaixo: <a href="http://ajaxonline.com.br/forum/viewtopic.php?p=50#50" rel="external">Subversão Parcial</a><strong>[/update]</strong></p>
<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
<li><a href='http://juliogreff.net/ajax-sem-o-x/' rel='bookmark' title='Permanent Link: Ajax sem o X'>Ajax sem o X</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/back-button-improved/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Botão Voltar para IE</title>
		<link>http://juliogreff.net/botao-voltar-para-ie/</link>
		<comments>http://juliogreff.net/botao-voltar-para-ie/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 20:31:07 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[botão voltar]]></category>
		<category><![CDATA[histórico]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=32</guid>
		<description><![CDATA[Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: Histórico para Navegação via JavaScript. Como todos já devem saber, meu código para simular o botão voltar não funciona no IE. Mas, inspirado na idéia de Mike Stenhouse, apresentada a mim pelo Cau Guanabara, criei um [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
<li><a href='http://juliogreff.net/estatisticas-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Estatísticas para Navegação via JavaScript'>Estatísticas para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>
<p>Como todos já devem saber, <a href="http://juliogreff.net/ativando-o-botao-voltar" title="Ativando o Botão Voltar">meu código</a> para simular o botão voltar não funciona no IE. Mas, inspirado na idéia de <a href="http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps" rel="external" title="Fixing the Back Button and Enabling Bookmarks for Ajax Apps">Mike Stenhouse</a>, apresentada a mim pelo <a href="http://cauguanabara.blogsome.com/" rel="external" title="Cau Guanabara">Cau Guanabara</a>, criei um código que funciona no IE.</p>
<p>Bem, inicialmente meu código tem 2 probleminhas, facilmente resolvidos:</p>
<ul>
<li>Ele não funciona no Firefox. Mas basta integrar minhas duas funções e tudo se resolve.</li>
<li>Ele é completamente &#8220;inacessível&#8221;. A acessibilidade foi por água abaixo. Mas existem técnicas para desfazer isso. Não coloquei aqui, pois meu objetivo é ensinar o botão voltar.</li>
</ul>
<p>Ambos problemas podem ser resolvidos. E não é difícil. Para resolve-los, pretendo escrever mais um código. Vou avisando que vai ser grande, mas melhor que os dois que já criei. Se você aceita as condições supra citadas, proponho: continuemos&#8230;</p>
<p>O conceito utilizado é simplesmente o mesmo: comparar o hash com o local da página, que estará em uma variável, que será definida através de uma função. A técnica que é um pouco diferente: em vez de apenas hashes, utilizaremos iframes, que ativam o botão voltar no IE.</p>
<h3>Passos Básicos</h3>
<p>Para utilizarmos essa técnica, estou usando um XHTML normal. Por razões de acessibilidade (um pouco, né), estou usando também a função &#8220;addEvent()&#8221;, para manipular o evento &#8220;window.onload&#8221;. Vamos lá:</p>
<pre><code>&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Botão Voltar no IE&lt;/title&gt;
&lt;script&gt;
function addEvent(obj, evType, fn){
	 if (obj.addEventListener){
		 obj.addEventListener(evType, fn, true);
		 return true;
	 } else if (obj.attachEvent){
		 var r = obj.attachEvent("on"+evType, fn);
		return r;
	 } else {
		return false;
	 }
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="container"&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="javascript:document.getElementById('ajaxnav').setAttribute('src', 'mock-page.php?hash=1');"&gt;Page 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:document.getElementById('ajaxnav').setAttribute('src', 'mock-page.php?hash=2');"&gt;Page 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:document.getElementById('ajaxnav').setAttribute('src', 'mock-page.php?hash=3');"&gt;Page 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>Observe o motivo da inacessibilidade: os links. Por que eles apontam para um objeto? Calma&#8230; Esse objeto, por dedução, é um iframe. Mas onde ele está? Temos que criar ele via JavaScript (não tentei criar direto, acho que é assim pra &#8220;enganar&#8221; o validador). Antes do fechamento do corpo da página, insira:</p>
<pre><code>&lt;script&gt;
var windowlocator = window.location.hash.split("#")[1] || "1";
document.write("&lt;iframe id='ajaxnav' name='ajaxnav' src='mock-page.php?hash="+windowlocator+"' style='display: none;'&gt;&lt;/iframe&gt;");
&lt;/script&gt;</code></pre>
<p>E aí está. Aliás, não está, ele é invisível(sério???)! E ele aponta para uma página &#8220;mock-page.php&#8221;. Essa foi pura e simplesmente copiada do Mike. Mais tarde veremos ela.</p>
<h3>O Script</h3>
<p>Agora sim, o temido script.</p>
<pre><code>var locator;		// Variável c/ local da pagina
function iFrameFix() {
	locator = document.frames['ajaxnav'].getLocation().split("?hash=")[1] || "1"; // A mesma variavel
	// Note que ela tem um valor "1" caso nada seja definido
	setTimeout("checkBookmark()",100);	// Função para checar Bookmark ou Refresh
}</code></pre>
<p>Sinceramente, não sei porque um timeout ali em cima. Aqui funcionou direitinho sem ele.</p>
<p>Observe com atenção, caro aprendiz: tem uma função getLocation ali. Ela pegará o hash da página &#8220;mock-page.php&#8221;. Curioso? Dentro de uma página comum, temos um script:</p>
<pre><code>	&lt;script type="text/javascript"&gt;
function getLocation() {
	return '&lt;?php print "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'] ?&gt;';
}
&lt;/script&gt;</code></pre>
<p>Aquela função retorna um valor passado pelo PHP. Não convém ficar explicando PHP agora, até porque eu não sou muito bom nisso. Agora vamos a mais uma função:</p>
<pre><code>function checkBookmark() {
	window.location.hash = locator || "1";	// Local do Hash
	checkWhetherChanged(0);		// Checar mudanças
}
function checkWhetherChanged(location) {
	var locator = document.frames['ajaxnav'].getLocation().split("?hash=")[1] || "1";	// De novo, para não ter problemas
	if(locator != location) {	// Se página != hash...
		doGetPage(locator);		// Requisição Ajax
		window.location.hash = locator;	// E mudamos o hash da página
	}
	setTimeout("checkWhetherChanged(" + locator + ")", 200);	// Pequeno intervalo de tempo, e repetimos tudo, infinitamente
}</code></pre>
<p>Acho que o código é familiar. O importante é saber fazer a requisição Ajax. Não vou explicar ela aqui, você vai ter que sofrer e cria-la sozinho. Para isso, faça uma query string &#8221; &#8220;valor=&#8221; + locator&#8221;, algo assim.</p>
<p>Tá legal, tá tudo definido bonitinho, mas e quando começa tudo? Quando a página carregar, e temos que definir isso também.</p>
<pre><code>addEvent(window, "load", iFrameFix);</code></pre>
<p>Bem, acho que acabou&#8230; Como o pessoal disse que eu confundi muito no outro artigo, vou explicar o &#8220;fluxo do script&#8221;.</p>
<pre>[página carregada] Executamos "iFrameFix()";
[iFrameFix()] Definimos "locator" como sendo o hash do iframe;
			  Executamos "checkBookmark()";
[checkBookmark()] Definimos o hash da página como sendo igual a "locator" ou "1";
                  Executamos "checkWhetherChanged(0)", com parâmetro 0;
[checkWhetherChanged()] Pegamos "locator" de novo (para que sejam verificadas as modificações);
						Se "locator" for diferente de "location", fazemos uma requisição Ajax;
						E definimos "window.location" com um hash "locator";
						A cada 200 milissegundos, executamos essa função de novo;</pre>
<p>E em breve estarei colocando aqui o código completo, unindo as duas soluções, e de forma mais &#8220;acessível&#8221; também.</p>
<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/ativando-o-botao-voltar/' rel='bookmark' title='Permanent Link: Ativando o Botão Voltar'>Ativando o Botão Voltar</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
<li><a href='http://juliogreff.net/estatisticas-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Estatísticas para Navegação via JavaScript'>Estatísticas para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/botao-voltar-para-ie/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ativando o Botão Voltar</title>
		<link>http://juliogreff.net/ativando-o-botao-voltar/</link>
		<comments>http://juliogreff.net/ativando-o-botao-voltar/#comments</comments>
		<pubDate>Fri, 20 Oct 2006 22:34:25 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[botão voltar]]></category>
		<category><![CDATA[histórico]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=17</guid>
		<description><![CDATA[Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: Histórico para Navegação via JavaScript. Depois de um longo tempo de pesquisa, mais um tempinho para testes e melhoramentos, descobri um script que nos permite manipular o botão voltar. Como em Ajax a navegação é completamente [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
<li><a href='http://juliogreff.net/a-aplicacao-ajax-perfeita/' rel='bookmark' title='Permanent Link: A Aplicação Ajax Perfeita'>A Aplicação Ajax Perfeita</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>
<p>Depois de um longo tempo de pesquisa, mais um tempinho para testes e melhoramentos, descobri um script que nos permite manipular o botão voltar. Como em Ajax a navegação é completamente por JavaScript, o botão voltar não é ativado de maneira alguma, certo? É, quase. Existe um código extremamente complicado que faz o botão ser ativado. Nem vou explica-lo, vou deixar vocês sofrerem pra descobrir:</p>
<pre><code>top.location = "#hash";</code></pre>
<p>Esse é equivalente a &lt;a href=&#8221;#hash&#8221;&gt;. Como sabemos, âncoras (ou hashes) ativam o botão voltar. Tudo certo, eureka, descobrimos a América, um viva para nós. Mas existe um pequeno inconveniente: quando clicamos no botão voltar, ele não ativa nenhum evento no navegador. Isso mesmo, pode procurar em todas as referências que você conhece.</p>
<p>E agora??? Volte ao início da teoria do JavaScript. Você lembrará de uma simples função:</p>
<pre><code>setInterval("history(false)", 100);</code></pre>
<p>Isso te faz pensar em algo? Uma função executada a cada 1/10 de segundo? Ou qualquer outro intervalo pequeno. É esse &#8220;artifício&#8221; (legítima gambiarra, mas necessária) que usaremos para verificar se o usuário voltou, avançou ou recarregou a página.</p>
<p>Agora vamos montar um pedaço de nosso script:</p>
<pre><code>var local = "";
window.onLoad = setInterval("history(false)", 100);
function request( x ) {
	ajax(url + "?id=" + x); // Aqui uma função que faça a requisição Ajax
	top.location = "#" + x; // Pode ser trocado por um link com hash
	history(true); // Chama a função de histórico
}</code></pre>
<p>Agora preste atenção em alguns detalhes importantes: a função history foi chamada duas vezes, com false e outra vez com true. Esse parâmetro serve para dizer a função que o usuário (se for true) chamou a função ou foi pelo intervalo (caso for false). Outro detalhe: a variável &#8220;local&#8221; é a variável que dirá a função history em qual local (na página, lembre-se disso) estamos.</p>
<p>Curioso? Então vamos adiante, para a outra função do nosso script: history. Apertem os cintos e vamos decolar. Se você tem estômago fraco ou é cardíaco, recomendo&#8230; continuar, não tem nada de assustador, é extremamente simples:</p>
<pre><code>function history(fromUser) {
  localHash = location.hash.split("#")[1];
  if (fromUser){
    local = localHash;
  }
  else if (local != localHash){
        request(localHash);
  }
}</code></pre>
<p>Agora preste atenção novamente. Lembra do &#8220;local&#8221; (eu avisei pra não esquecer&#8230;)? Agora temos outro local, &#8220;localHash&#8221;, que é o local para onde o hash aponta. O nosso hash servirá de query string, se já deu pra notar. O que está no hash vai para a outra função em determinada situação.</p>
<p>Se &#8220;fromUser&#8221; for true (veio do usuário), não nos preocupamos e passamos localHash direto para o nosso local. Se for via intervalo, verificamos se &#8220;local&#8221; é igual a &#8220;localHash&#8221;. Se não for, executamos uma nova requisição. E é só isso! Apenas 9 linhas de código para a nossa função de histórico! Acabamos com todas as 7 cabeças do dragão. Espero que saibam usar, já que para muitas query strings o negócio fica mais complicado. Bom proveito!</p>
<p class="post-update">Depois de alguns aprimoramentos, essa técnica se tornou muito melhor. Como esse post está desatualizado, considere ler sua continuação: <a href="http://juliogreff.net/historico-para-navegacao-via-javascript/" title="Histórico para Navegação via JavaScript">Histórico para Navegação via JavaScript</a>.</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/botao-voltar-para-ie/' rel='bookmark' title='Permanent Link: Botão Voltar para IE'>Botão Voltar para IE</a></li>
<li><a href='http://juliogreff.net/back-button-improved/' rel='bookmark' title='Permanent Link: Back Button Improved!'>Back Button Improved!</a></li>
<li><a href='http://juliogreff.net/historico-para-navegacao-via-javascript/' rel='bookmark' title='Permanent Link: Histórico para Navegação via JavaScript'>Histórico para Navegação via JavaScript</a></li>
<li><a href='http://juliogreff.net/ajax-vs-acessibilidade/' rel='bookmark' title='Permanent Link: Ajax vs. Acessibilidade'>Ajax vs. Acessibilidade</a></li>
<li><a href='http://juliogreff.net/a-aplicacao-ajax-perfeita/' rel='bookmark' title='Permanent Link: A Aplicação Ajax Perfeita'>A Aplicação Ajax Perfeita</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/ativando-o-botao-voltar/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

