<?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; cross browser</title>
	<atom:link href="http://juliogreff.net/tag/cross-browser/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>A Aplicação Ajax Perfeita</title>
		<link>http://juliogreff.net/a-aplicacao-ajax-perfeita/</link>
		<comments>http://juliogreff.net/a-aplicacao-ajax-perfeita/#comments</comments>
		<pubDate>Thu, 07 Jun 2007 16:39:00 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[acessibilidade]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[filosofia]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[usabilidade]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/a-aplicacao-ajax-perfeita/</guid>
		<description><![CDATA[Tempos atrás andei pensando sobre uma aplicação Ajax. O que ela deveria ser, como deveria funcionar, tudo o que precisaria ter. Incrementei a idéia, pensando na acessibilidade, usabilidade, unobstrusividade, essas coisas. Cheguei a conclusão que não existem muitas dessas por aí. Não que essa idéia fosse &#8220;a aplicação ajax perfeita&#8221;, mas sim a ideal. Demoraria [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/hijax-ajax-acessivel/' rel='bookmark' title='Permanent Link: Hijax: Ajax Acessível'>Hijax: Ajax Acessível</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/fila-de-requisicoes-em-ajax/' rel='bookmark' title='Permanent Link: Fila de Requisições em Ajax'>Fila de Requisições em Ajax</a></li>
<li><a href='http://juliogreff.net/ajax-vs-moda-vs-performance/' rel='bookmark' title='Permanent Link: Ajax vs. Moda vs. Performance'>Ajax vs. Moda vs. Performance</a></li>
<li><a href='http://juliogreff.net/ajax-requisicoes-head/' rel='bookmark' title='Permanent Link: Ajax: Requisições HEAD'>Ajax: Requisições HEAD</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Tempos atrás andei pensando sobre uma aplicação Ajax. O que ela deveria ser, como deveria funcionar, tudo o que precisaria ter. Incrementei a idéia, pensando na <a href="http://juliogreff.net/ajax-vs-acessibilidade/">acessibilidade</a>, usabilidade, unobstrusividade, essas coisas. Cheguei a conclusão que não existem muitas dessas por aí.</p>
<p>Não que essa idéia fosse &#8220;a aplicação ajax perfeita&#8221;, mas sim a ideal. Demoraria muito a ser feita, mas eu consideraria uma obra de arte.</p>
<h3>Padronização</h3>
<p>Essa parte é a parte fácil, que todo mundo <strong>sempre</strong> deveria se dar ao trabalho de fazer: manter seu trabalho dentro dos web standards.</p>
<p>Validar sua marcação, seus CSSs, isso todo mundo faz (ou deveria). Mas às vezes um certo item é deixado de lado: seus XMLs, que não causariam muito problema, a não ser um XML em especial: os feeds. Ou seja, valide tudo que possa ser validado.</p>
<h3>Manutenção</h3>
<p>Código bom é código comentado. Disso ninguém discorda. Sempre comente seus códigos, tanto para seu uso em futuras manutenções e atualizaçãoes, quanto para seus visitantes que querem descobrir o segredo daquela técnica inovadora que você implementou. JavaScript ninguém esconde, e uma técnica nova deveria poder chegar a todos que quisessem, mesmo que seja investigando seu código. Melhor ainda se ele estiver comentado, mesmo que seja somente em partes mais obscuras.</p>
<p>E o tamanho do código não aumentaria? Sim, mas você só precisará comentar partes essenciais, aquelas mais complicadas que você sabe que irá esquecer com o tempo. Além do mais, se você esquecer de seu código, perderá muito tempo até lembrar o que cada parte faz.</p>
<h3>Compatibilidade</h3>
<p>Outra parte facílima, mas indispensável. Se tudo for seguido, nem tanto, mas ainda assim se torna muito mais agradável usar uma aplicação que funcione como deveria funcionar.</p>
<p>Com todas as opções de browsers existentes hoje, sempre haverá aquele que terá problemas (geralmente o azulzinho que todo mundo já conhece). Mas existem maneiras de amenizar o problema. Isso não só com Ajax, mas qualquer &#8220;defeito&#8221; de JavaScript e CSS que possa atrapalhar a experiência do usuário.</p>
<p>Essa parte pode, sem problemas, ser deixada para os frameworks já existentes, que fazem seu trabalho muito bem. A compatibilidade vem sendo muito focada por essas bibliotecas, facilitando, e muito, seu trabalho.</p>
<h3>Controle de readyStates</h3>
<p>Agora começa a parte divertida. Tudo que está logo acima qualquer um faz. Vamos começar adicionando nossos diferenciais.</p>
<p>Geralmente, costuma-se cuidar de apenas dois readyStates: 1 e 4 (aberto e carregado), que resultam no clássico &#8220;Carregando&#8230;&#8221; e a requisição completa. Não que seja necessário, mas um controle completo de estados poderia ser bom.</p>
<p>O usuário saber que sua requisição está sendo processada ajuda, já que não pensaria que a requisição travou (isso acontece bastante quando a requisição demora demais).</p>
<p>Coloquei os readyStates, o que significam e uma sugestão para o texto de carregamento. Os readyStates 0 e 4 não precisam disso, já que 0 não tem muito uso, e 4 terá sua própria função.</p>
<ul>
<li><strong>Não Inicializado (0)</strong></li>
<li><strong>Aberto (1)</strong>: &#8220;Abrindo Requisição&#8221; ou &#8220;Iniciando Requisição&#8221;</li>
<li><strong>Enviado (2)</strong>: &#8220;Enviando Dados&#8221;</li>
<li><strong>Recebendo (3)</strong>: &#8220;Carregando&#8221; ou &#8220;Recebendo Dados&#8221;</li>
<li><strong>Completo (4)</strong></li>
</ul>
<p>Não que seja necessário, mas também seria válido cuidar dos status da requisição também, pelo menos 200 (OK), 404, 500, e os outros erros mais comuns.</p>
<h3>Histórico</h3>
<p>Esse é o maior problema das aplicações Ajax. Já faz tempo que <a title="Ativando o Botão Voltar" href="http://juliogreff.net/ativando-o-botao-voltar/">as primeiras soluções para histórico apareceram</a>, e <a title="Histórico para Navegação via JavaScript" href="http://juliogreff.net/historico-para-navegacao-via-javascript/">outras melhoradas</a>, e ainda há centenas de aplicações que não se dão ao trabalho de implementar qualquer das soluções.</p>
<p>O histórico <strong>sempre</strong> deve ser implementado, mesmo que sua aplicação não queira dominar o mundo.</p>
<h3>Cache</h3>
<p>O cache, considerado uma praga por muitos, pode ser de uma grande ajuda para sua aplicação. Sempre que se faz uma requisição estática (que não muda em pouco tempo), deve-se usar o cache, pois quando refizermos essa requisição, ela terminará mais rápido.</p>
<p>Além do mais, usando o histórico, podemos guardar requisições &#8220;cacheadas&#8221; no próprio JavaScript. Assim, mais rápido ainda.</p>
<p>É claro que, em requisições dinâmicas, não devemos usar essa técnica. Ela pode prejudicar o usuário, pois não há maneira de atualizar a página através do F5.</p>
<h3>Filas de Requisição</h3>
<p>Todos sabem que se quando uma requisição estiver em andamento, e outra for iniciada, a primeira será cancelada.</p>
<p>Assim como o histórico, já existem milhares de soluções diferentes para <a title="Fila de Requisições em Ajax" href="http://juliogreff.net/fila-de-requisicoes-em-ajax/">fila de requisições</a>. Esse recurso deve também ser usado sempre que possível (ou seja, sempre). Isso pode evitar aborrecimentos ao usuário.</p>
<h3>Inobstrusividade</h3>
<p>Essa é a questão mais polêmica. Sua aplicação não deve usar JavaScript obstrusivo (ou usar o menos possível), fazendo-a de maneira que funcione corretamente em qualquer browser.</p>
<p>E o Ajax sem JavaScript, como fica? Também tive idéias mirabolantes quanto a isso. Você deve usar o mesmo script server-side tanto para requisições assíncronas (Ajax) quanto para as síncronas (me refiro àquelas via browser). Para isso, usamos aquele header <code>X-Requested-With</code>, que seu server-side deve identificar.</p>
<p>Dessa maneira, não &#8220;trancamos&#8221; o conteúdo nem ao usuário nem aos buscadores e afins. Benefícios ao usuário e a você (e ao seu bolso, se for o caso).</p>
<p>Lembre-se de tornar o conteúdo Ajax-less atrativo aos olhos do usuário também, usando o mesmo layout do resto da aplicação (ou a mesma estrutura, caso seja XML).</p>
<h3>Desempenho</h3>
<p>O desempenho é outra característica muito essencial. Em tráfego de dados muito grande, devemos tomar cuidado com o JavaScript. Muito <a title="responseXML" href="http://juliogreff.net/responsexml/">XML</a> gera muitas chamadas ao DOM, e isso leva tempo. Aí o <a title="JavaScript Object Notation" href="http://juliogreff.net/javascript-object-notation/">JSON</a> entra em cena.</p>
<p>O Profiler do Firebug pode ser muito útil, já que ele monitora o tempo de execução da sua aplicação e das requisições que ela faz.</p>
<p>Bem, é isso. Quem sabe um dia veremos uma aplicação destas. Estou trabalhando em uma função que faça boa parte disso, espero que consiga terminar. Fui!</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/hijax-ajax-acessivel/' rel='bookmark' title='Permanent Link: Hijax: Ajax Acessível'>Hijax: Ajax Acessível</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/fila-de-requisicoes-em-ajax/' rel='bookmark' title='Permanent Link: Fila de Requisições em Ajax'>Fila de Requisições em Ajax</a></li>
<li><a href='http://juliogreff.net/ajax-vs-moda-vs-performance/' rel='bookmark' title='Permanent Link: Ajax vs. Moda vs. Performance'>Ajax vs. Moda vs. Performance</a></li>
<li><a href='http://juliogreff.net/ajax-requisicoes-head/' rel='bookmark' title='Permanent Link: Ajax: Requisições HEAD'>Ajax: Requisições HEAD</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/a-aplicacao-ajax-perfeita/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<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>Drag and Drop &#8211; Parte 2</title>
		<link>http://juliogreff.net/drag-and-drop-parte-2/</link>
		<comments>http://juliogreff.net/drag-and-drop-parte-2/#comments</comments>
		<pubDate>Thu, 08 Mar 2007 22:08:36 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[drag and drop]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=76</guid>
		<description><![CDATA[Esse post é continuação de Drag and Drop &#8211; Parte 1. Nessa segunda parte sobre Drag and Drop, vou explicar como &#8220;soltar&#8221; os objetos, como prometido no post anterior. Ficou curioso? Então vamos ao trabalho. Antes de começar, vamos tomar como exemplo uma lixeira: devemos carregar itens para dentro dela. Simples, não acha? Pois é, [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/drag-and-drop-parte-1/' rel='bookmark' title='Permanent Link: Drag and Drop &#8211; Parte 1'>Drag and Drop &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
<li><a href='http://juliogreff.net/estendendo-objetos-dom/' rel='bookmark' title='Permanent Link: Estendendo Objetos DOM'>Estendendo Objetos DOM</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="post-see">Esse post é continuação de <a title="Drag and Drop - Parte 1" href="http://juliogreff.net/drag-and-drop-parte-1/">Drag and Drop &#8211; Parte 1</a>.</p>
<p>Nessa segunda parte sobre <a title="Drag and Drop - Parte 1" href="http://juliogreff.net/drag-and-drop-parte-1/">Drag and Drop</a>, vou explicar como &#8220;soltar&#8221; os objetos, como prometido no post anterior. Ficou curioso? Então vamos ao trabalho.</p>
<p>Antes de começar, vamos tomar como exemplo uma lixeira: devemos carregar itens para dentro dela. Simples, não acha? Pois é, se você respondeu &#8220;sim&#8221;, ledo engano.<br />
Como estamos carregando um item, ele ess carregando um item, ele está sempre <strong>diretamente</strong> abaixo do ponteiro do mouse. Desse modo, é impossível disparar um evento de mouse (<code>mouseup</code>, <code>mousedown</code>, <code>mouseover</code>&#8230;) em qualquer elemento da página. Se você carregar um item para uma lixeira, o mouse ainda estará acima do elemento, e não da lixeira.<br />
Existem algumas maneiras para resolver o problema, muito fáceis até. O problema da maioria delas é o mesmo: estética. Não mover o elemento até que o mouse seja soltado, colocar o elemento logo abaixo do ponteiro, entre outras coisas não muito bonitas de se ver.<br />
Mas pra tudo existe uma solução. Difícil, mas é uma boa solução. O plano é o seguinte: vamos criar uma lista de todos os alvos. Não vamos atirar em ninguém, esses alvos serão os lugares onde os itens podem ser largados. Quando o botão do roedor eletrônico for soltado, checaremos a posição do mouse e a posição de cada alvo, para sabermos se o ponteiro está em cima de algum desses alvos.<br />
Vamos ao código:</p>
<pre><code>/*
Ainda precisamos de todo o código dos exemplos anteriores,
com exceção da função mouseUp (substituída agora)
*/

var dropTargets = [];

function addDropTarget(dropTarget){
	dropTargets.push(dropTarget);
}

function mouseUp(ev){
	ev           = ev || window.event;
	var mousePos = mouseCoords(ev);

	for(var i=0; i &lt; dropTargets.length; i++){
		var curTarget  = dropTargets[i];
		var targPos    = getPosition(curTarget);
		var targWidth  = parseInt(curTarget.offsetWidth);
		var targHeight = parseInt(curTarget.offsetHeight);

		if(
			(mousePos.x &gt; targPos.x)                &amp;&amp;
			(mousePos.x &lt; (targPos.x + targWidth))  &amp;&amp;
			(mousePos.y &gt; targPos.y)                &amp;&amp;
			(mousePos.y &lt; (targPos.y + targHeight))){
// Aqui executamos a ação desejada.
		}
	}

	dragObject   = null;
}
</code></pre>
<p>Usamos assim: definimos um alvo com a função <code>addDropTarget</code>, assim como <code>makeDraggable</code> de antes. Quando soltamos o mouse, a função <code>mouseUp</code> checa a posição de cada alvo e a posição do mouse, e então executa a ação que precisamos.<br />
Tudo OK, tudo prontinho. É claro que o resto é criatividade: containers, organização de dados, alguma coisa pra ser carregada pela sua página, ou qualquer outra bugiganga sem muita utilidade. Até!</p>
<p><em>Este texto é uma versão do original, <a title="How to Drag and Drop in JavaScript" rel="external" href="http://www.webreference.com/programming/javascript/mk/column2/index.html">How to Drag and Drop in JavaScript</a>.</em></p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/drag-and-drop-parte-1/' rel='bookmark' title='Permanent Link: Drag and Drop &#8211; Parte 1'>Drag and Drop &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
<li><a href='http://juliogreff.net/estendendo-objetos-dom/' rel='bookmark' title='Permanent Link: Estendendo Objetos DOM'>Estendendo Objetos DOM</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/drag-and-drop-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Drag and Drop &#8211; Parte 1</title>
		<link>http://juliogreff.net/drag-and-drop-parte-1/</link>
		<comments>http://juliogreff.net/drag-and-drop-parte-1/#comments</comments>
		<pubDate>Tue, 06 Mar 2007 21:43:00 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[drag and drop]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=74</guid>
		<description><![CDATA[&#8220;Drag and Drop&#8221; é aquele conhecido efeito de arrastar e soltar, comum em muitos serviços que encontramos na Internet hoje em dia, e acredito que você já tenha se deparado com muitos desses serviços. Dividi este tutorial em duas partes, pra não ficar muito cansativo. Nessa primeira parte, vou explicar o básico, como &#8220;arrastar&#8221;. Na [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/drag-and-drop-parte-2/' rel='bookmark' title='Permanent Link: Drag and Drop &#8211; Parte 2'>Drag and Drop &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/firefox-event-listeners-e-return/' rel='bookmark' title='Permanent Link: Firefox, Event Listeners e Return'>Firefox, Event Listeners e Return</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>&#8220;Drag and Drop&#8221; é aquele conhecido efeito de arrastar e soltar, comum em muitos serviços que encontramos na Internet hoje em dia, e acredito que você já tenha se deparado com muitos desses serviços.<br />
Dividi este tutorial em duas partes, pra não ficar muito cansativo. Nessa primeira parte, vou explicar o básico, como &#8220;arrastar&#8221;. Na outra, vamos aprender a &#8220;soltar&#8221; (parece meio óbvio, mas vai ser útil, aguarde).</p>
<h3>Capturando Movimentos do Mouse</h3>
<p>A primeira coisa que devemos fazer é capturar as coordenadas do mouse quando ele se move. Isso é feito adicionando uma função ao evento <code>document.onmousemove</code>.</p>
<pre><code>document.onmousemove = mouseMove;// Essa não é a melhor maneira de fazer isso// Quando for "de verdade", use addEventfunction mouseMove(ev){        ev           = ev || window.event;        var mousePos = mouseCoords(ev);}function mouseCoords(ev){        if(ev.pageX || ev.pageY){                return {x:ev.pageX, y:ev.pageY};        }        return {                x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,                y:ev.clientY + document.body.scrollTop  - document.body.clientTop        };}</code></pre>
<p>Primeiro vamos ao evento. Praticamente tudo que fizemos quando estamos em uma página dispara um evento (um clique, um movimento de mouse, uma tecla pressionada&#8230;). No IE, esse evento é global, e fica na variável <code>window.event</code>. Nos browsers de verdade (Firefox, Opera, Safari&#8230;), esse evento é passado como argumento para a função que está vinculada a ação.<br />
Sempre diferente, o IE dá um jeito de atrapalhar. Nos browsers (Firefox, Opera, Safari&#8230;, IE não é browser), <code>event.pageX</code> e <code>event.pageY</code> representam a posição do mouse em relação ao documento, onde o topo esquerdo é a posição 0&#215;0. Se você rolar a página 100 pixels abaixo, <code>pageY</code> será 100, e assim por diante.<br />
Já se você clicar num ícone com um &#8220;E&#8221; azul e for testar, a posição do mouse em relação a <strong>janela</strong> estará armazenada em <code>event.clientX</code> e <code>event.clientY</code>. Assim sendo, mesmo se você rolar a página (e manter o mouse no lugar), a posição será sempre 0&#215;0 (já que a posição é em relação a janela, e não ao documento inteiro). As variáveis <code>scrollTop</code> e <code>scrollLeft</code> nos ajudam a resolver o problema, já que elas armazenam a &#8220;quantidade&#8221; rolada. Piorando um pouco a situação (e aumentando mais um termo em nossa expressão algébrica &#8220;made-for-ie&#8221;), o documento não fica na posição 0&#215;0, há uma pequena borda ao redor. <code>document.body.clientLeft</code> e <code>document.body.clientTop</code> contém a largura dessa borda.<br />
Pra não nos preocuparmos com isso, o dito cujo criador da função (que permanece desconhecido pra mim) deixou tudo pronto. Em todos os exemplos, suprimirei essa função, mas ela deve estar lá sempre!</p>
<h3>Capturando Cliques do Mouse</h3>
<p>Agora precisamos saber quando o botão do mouse é pressionado e quando ele é soltado. Novamente usamos os eventos, agora <code>onmousedown</code> e <code>onmouseup</code>. Note que eles não devem ser vinculados ao documento, e sim ao objeto que queremos arrastar. Assim só eles poderão ser arrastados, e não o documento.</p>
<pre><code>document.onmouseup = mouseUp;var dragObject     = null;

function makeClickable(object){        object.onmousedown = function(){                dragObject = this;        }}

function mouseUp(ev){        dragObject = null;}</code></pre>
<p>A variável dragObject conterá o objeto que está sendo carregado. Se o objeto for &#8220;arrastável&#8221;, e clicarmos nele, ele vai pra essa variável. Caso contrário, ela permanece nula. E quando soltamos o botão do mouse, idem. E para tornar um objeto possível de se arrastar (&#8220;arrastável&#8221;, não sei se isso existe), usamos a função <code>makeClickable</code>, passando o dito objeto como parâmetro.</p>
<h3>Movendo um Objeto</h3>
<p>Agora na reta final. Primeiro, para podermos arrastar um objeto, precisamos que o estilo <code>position</code> seja <code>absolute</code>, obviamente porque a sua posição é relativa ao topo esquerdo do documento, assim como a posição do mouse.<br />
Uma vez que <code>objeto.style.position = "absolute"</code>, tudo que temos que fazer é mudar os estilos <code>top</code> e <code>left</code>. So, voila! Só falta saber como fazer isso:</p>
<pre><code>document.onmousemove = mouseMove;document.onmouseup   = mouseUp;

var dragObject  = null;var mouseOffset = null;

function mouseMove(ev){        ev           = ev || window.event;        var mousePos = mouseCoords(ev);}

// mouseCoords(ev)...

function getMouseOffset(target, ev){        ev = ev || window.event;

     var docPos    = getPosition(target);        var mousePos  = mouseCoords(ev);        return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};}

function getPosition(e){        var left = 0;        var top  = 0;

     while (e.offsetParent){                left += e.offsetLeft;                top  += e.offsetTop;                e     = e.offsetParent;        }

     left += e.offsetLeft;        top  += e.offsetTop;

     return {x:left, y:top};}

function mouseMove(ev){        ev           = ev || window.event;        var mousePos = mouseCoords(ev);

     if(dragObject){                dragObject.style.position = 'absolute';                dragObject.style.top      = mousePos.y - mouseOffset.y;                dragObject.style.left     = mousePos.x - mouseOffset.x;

             return false;        }}function mouseUp(){        dragObject = null;}

function makeDraggable(item){        if(!item) return;        item.onmousedown = function(ev){                dragObject  = this;                mouseOffset = getMouseOffset(this, ev);                return false;        }}          </code></pre>
<p>Esse &#8220;juntão&#8221; de códigos (e alguns a mais) nos permite mover livremente um objeto (desde que seja &#8220;arrastável&#8221; (preciso de um substituto pra essa palavra), através de <code>makeDraggable</code>).<br />
Algo mais que possa interessar: quando clicamos em um item (item = objeto &#8220;arrastável&#8221;, ufa), guardamos outra variável: <code>mouseOffset</code>. Ela contém o lugar em que clicamos em nosso item. Isso para que possamos posicionar o item abaixo do mouse da mesma maneira quando clicado.<br />
Outra função diferente que usamos: <code>getPosition</code>. Ela retorna a posição de um item relativo ao documento. Como seu <code>offsetLeft e offsetTop</code> são relativos ao seu elemento pai, a função vai somando até chegar ao documento.</p>
<h3>Soltando um Objeto</h3>
<p>Até agora cumprimos tudo, carregamos o item para qualquer lugar da página. Mas podemos fazer mais que isso, como encaixar o item em um lugar específico, ou carrega-lo para uma lixeira, pasta&#8230;</p>
<p>Isso é legal, concorda? E tenho um segredo pra contar: só na <a title="Drag and Drop - Parte 2" href="http://juliogreff.net/drag-and-drop-parte-2/">parte 2</a>, até!</p>
<p class="post-see">Não esqueça de ler a <a title="Drag and Drop - Parte 2" href="http://juliogreff.net/drag-and-drop-parte-2/">parte 2</a> do artigo!</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/drag-and-drop-parte-2/' rel='bookmark' title='Permanent Link: Drag and Drop &#8211; Parte 2'>Drag and Drop &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/firefox-event-listeners-e-return/' rel='bookmark' title='Permanent Link: Firefox, Event Listeners e Return'>Firefox, Event Listeners e Return</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/drag-and-drop-parte-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Estendendo Objetos DOM</title>
		<link>http://juliogreff.net/estendendo-objetos-dom/</link>
		<comments>http://juliogreff.net/estendendo-objetos-dom/#comments</comments>
		<pubDate>Sun, 18 Feb 2007 21:35:00 +0000</pubDate>
		<dc:creator>Julio Greff</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[dom]]></category>

		<guid isPermaLink="false">http://www.juliogreff.blog.br/?p=66</guid>
		<description><![CDATA[Estender objetos DOM vem sendo um problema desde que IE é browser (ou quase isso, IE não é um browser, pode ser usado até como torradeira (?), mas browser não). Como o bichinho azul não nos deixa estender Object ou Element (não me pergunte o porquê), nos vemos em um grande problema, que muitos desenvolvedores [...]

<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/estendendo-o-javascript/' rel='bookmark' title='Permanent Link: Estendendo o JavaScript'>Estendendo o JavaScript</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/mootools-classes/' rel='bookmark' title='Permanent Link: Mootools &#8211; Classes'>Mootools &#8211; Classes</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Estender objetos DOM vem sendo um problema desde que IE é browser (ou quase isso, IE não é um browser, pode ser usado até como torradeira (?), mas browser não).<br />
Como o bichinho azul não nos deixa estender <code>Object</code> ou <code>Element</code> (não me pergunte o porquê), nos vemos em um grande problema, que muitos desenvolvedores já tentaram resolver. Um dos mais bem-sucedidos nisso (dos que conheço) foi o <a title="Bernardo Rufino" rel="external friend" href="http://bermonruf.wordpress.com/">Bermonruf</a>, <a title="Estendendo Objetos JS Cross Browser - Parte 1" rel="external friend" href="http://bermonruf.wordpress.com/2007/01/05/extendendo-objetos-js-cross-browser-parte-1/">nesse post</a>. Ele usa uma maneira criativa de estender os objetos DOM. Não tão eficiente quanto estender a raíz dos objetos (maldito IE!), mas funciona impressionantemente bem, devido as restrições a nós, pobres mortais, impostas. O <a title="Estendendo Objetos JS Cross Browser - Parte 1" rel="external friend" href="http://bermonruf.wordpress.com/2007/01/05/extendendo-objetos-js-cross-browser-parte-1/">post</a> explica melhor a idéia do que eu.<br />
Eu, perfeccionista não satisfeito, continuei atrás de uma maneira &#8220;elegante&#8221;, como diz o Bernardo. Não encontrei, mas encontrei uma maneira diferente, e que se aplica melhor ao meu estilo de desenvolvimento (me ajudou muito, não só com o DOM). Baseia-se em <a title="Extending DOM Nodes with Mootools" rel="external" href="http://www.coryhudson.com/blog/2006/09/26/extending-dom-nodes-with-mootools/">Extending DOM Nodes with Mootools</a>, de <a title="Cory Hudson" rel="external" href="http://www.coryhudson.com/blog/">Cory Hudson</a>. Como não sou bom pra re-explicar soluções dos outros, leia lá.</p>
<h3>Fuçando na Mootools</h3>
<p>Como estou desenvolvendo uma biblioteca, não quero que seja necessário outras para fazê-la funcionar. Então fui fuçar na <a title="Mootools Library" rel="external" href="http://mootools.net/">Mootools</a>. Achei a &#8220;solução&#8221; para nosso &#8220;problema&#8221;. Vamos criar algumas funções daqui a pouco, baseadas em <code>Object.extend</code>, <code>Element.extend</code> e <code>$</code>. É tudo que iremos precisar para estender nossos objetos.<br />
Utilizaremos a mesma idéia do Bernardo (estender objeto por objeto), mas de uma maneira diferente (apenas os elementos retornados pela função <code>$</code> serão estendidos).</p>
<h3>As Funções para Estender</h3>
<p>As funções que apresentarei a vocês vêm diretamente da minha biblioteca. Elas tem algumas pequenas modificações que julguei necessárias, mas são praticamente a mesma coisa.</p>
<pre><code>Object.extend = function(objDestination, objSource) {  if(typeof objSource == "undefined") {    objSource = objDestination;    objDestination = this;  }  for(var property in objSource)    objDestination[property] = objSource[property];  return objDestination;}Element.extend = function(objSource) {  return Object.extend(Element.prototype, objSource);}</code></pre>
<p>Antes de <code>Element.extend</code>, precisamos definir a função <code>Element</code>, também da minha biblioteca, também baseada na <a title="Mootools Library" rel="external" href="http://mootools.net/">Mootools</a>.</p>
<pre><code>var Element = function(mElement) {  if(typeof mElement == "string")    mElement = document.createElement(mElement);  return $(mElement);}</code></pre>
<p>Quase tudo que precisamos está aí. Agora falta a função <code>$</code>, que retornará nossos objetos DOM já estendidos.</p>
<h3>A função pra objeto e$tendido</h3>
<p>Como já disse, apenas os objetos retornados por <code>$</code> serão e$tendidos. Essa função retornará o objeto estendido com tudo que estiver no <a title="JavaScript Orientado a Objetos - Parte 2" href="http://juliogreff.net/javascript-orientado-a-objetos-parte-2/">protótipo</a> (<code>prototype</code>) da &#8220;classe&#8221; <code>Element</code>. Mais simples: todos os métodos da &#8220;classe&#8221; <code>Element</code> estarão em todos os objetos retornados por <code>$</code>. Como? Vamos codificar:</p>
<pre><code>// Adaptado da Mootoolsvar $ = function(el) {        el = document.getElementById(el);        el.extend = Object.extend;        el.extend(Element.prototype);        return el;}</code></pre>
<p>Pronto, aí está! That&#8217;s all folks! Peraí, ainda não. Não vão embora ainda, temos que estender <code>Element</code> ainda! Lembre-se, tudo que estiver em <code>Element</code> está nos objetos retornados em <code>$</code>.</p>
<h3>Estendendo Element</h3>
<p>Caramba, postagem concisa essa, não? Estende isso, aquilo&#8230; Vou deixar que o código abaixo se auto-explique:</p>
<pre><code>Element.extend({  "metodo": function() { alert(this.innerHTML); },  "bold": function() { this.style.fontWeight = "bold"; }}</code></pre>
<p>Estendemos (quase) tudo. Cada par desses aí resultará em um método (nesse caso, 2 pares, 2 métodos). Colocamos dois métodos no <code>prototype</code> de <code>Element</code>, e eles irão parar nos nossos objetos DOM.</p>
<h3>Reaproveitando isso tudo</h3>
<p>Um dos grandes méritos da <a title="JavaScript Orientado a Objetos - Parte 1" href="http://juliogreff.net/javascript-orientado-a-objetos-parte-1"><abbr title="Programação Orientada a Objetos">POO</abbr></a> é que podemos reutilizar tudo. Usando <code>Object.extend</code>, você pode estender qualquer objeto: strings, arrays, objetos DOM individuais, qualquer coisa. Basta chamar a função com dois argumentos: <code>objDestination</code> (objeto de destino) e <code>objSource</code> (métodos ou propriedades a serem adicionados, no formato <a title="JavaScript Object Notation" href="http://juliogreff.net/javascript-object-notation/">JSON</a>).<br />
Espero que eu tenha sido claro, e utilizem bem!</p>


<h3>Posts Relacionados</h3><ul><li><a href='http://juliogreff.net/estendendo-o-javascript/' rel='bookmark' title='Permanent Link: Estendendo o JavaScript'>Estendendo o JavaScript</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-1/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 1'>JavaScript Orientado a Objetos &#8211; Parte 1</a></li>
<li><a href='http://juliogreff.net/mootools-classes/' rel='bookmark' title='Permanent Link: Mootools &#8211; Classes'>Mootools &#8211; Classes</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-2/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 2'>JavaScript Orientado a Objetos &#8211; Parte 2</a></li>
<li><a href='http://juliogreff.net/javascript-orientado-a-objetos-parte-3/' rel='bookmark' title='Permanent Link: JavaScript Orientado a Objetos &#8211; Parte 3'>JavaScript Orientado a Objetos &#8211; Parte 3</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://juliogreff.net/estendendo-objetos-dom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

