<?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"
	>

<channel>
	<title>Caio Moritz Ronchi</title>
	<atom:link href="http://www.caiomoritz.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caiomoritz.com</link>
	<description>Idéias tratando de desenvolvimento de software.</description>
	<pubDate>Fri, 02 Jan 2009 20:48:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Vim no Windows com codificação UTF-8</title>
		<link>http://www.caiomoritz.com/2009/01/02/vim-no-windows-com-codificacao-utf-8/</link>
		<comments>http://www.caiomoritz.com/2009/01/02/vim-no-windows-com-codificacao-utf-8/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 20:14:42 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Vim]]></category>

		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=188</guid>
		<description><![CDATA[Estou usando o Cygwin no Windows para testar meu futuro
deploy de uma aplicação PHP. Tive vários problemas para fazê-la
funcionar, e no meio tempo precisei abrir diversos arquivos que
editei originalmente no Ubuntu. Como no Linux os arquivos têm
codificação UTF-8, no Vim do Windows os caracteres especiais
aparecem corrompidos (acho que a codificação padrão que o Vim
assume no [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Vim no Windows com codificação UTF-8",
	url: "http://www.caiomoritz.com/2009/01/02/vim-no-windows-com-codificacao-utf-8/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Estou usando o <a href="http://www.cygwin.com">Cygwin</a> no Windows para testar meu futuro
deploy de uma aplicação PHP. Tive vários problemas para fazê-la
funcionar, e no meio tempo precisei abrir diversos arquivos que
editei originalmente no Ubuntu. Como no Linux os arquivos têm
codificação UTF-8, no Vim do Windows os caracteres especiais
aparecem corrompidos (acho que a codificação padrão que o Vim
assume no Windows é latin-1). Para forçar a codificação UTF-8, portanto,
estou usando esta linha no <code>.vimrc</code>:</p>

<pre><code>set enc=utf-8
</code></pre>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Vim+no+Windows+com+codifica%C3%A7%C3%A3o+UTF-8&url=http%3A%2F%2Fwww.caiomoritz.com%2F2009%2F01%2F02%2Fvim-no-windows-com-codificacao-utf-8%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2009/01/02/vim-no-windows-com-codificacao-utf-8/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Vídeos do ClicRBS agora em Flash</title>
		<link>http://www.caiomoritz.com/2008/12/17/videos-do-clicrbs-agora-em-flash/</link>
		<comments>http://www.caiomoritz.com/2008/12/17/videos-do-clicrbs-agora-em-flash/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 01:16:07 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[ClicRBS]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=186</guid>
		<description><![CDATA[Finalmente os vídeos do ClicRBS estão em Flash
e podem ser assistidos tranqüilamente no Linux sem maiores
maracutaias. Acabei de descobrir assistindo este aqui
do Luiz Carlos Prates.

Aleluia!


<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Vídeos do ClicRBS agora em Flash",
	url: "http://www.caiomoritz.com/2008/12/17/videos-do-clicrbs-agora-em-flash/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Finalmente os vídeos do ClicRBS estão em Flash
e podem ser assistidos tranqüilamente no Linux sem maiores
maracutaias. Acabei de descobrir assistindo <a href="http://www.clicrbs.com.br/blog/jsp/default.jsp?uf=2&amp;pg=1&amp;coldir=1&amp;section=Blogs&amp;topo=4023.dwt&amp;uf=2&amp;local=18&amp;template=3948.dwt&amp;source=DYNAMIC,blog.BlogDataServer,getBlog&amp;blog=425&amp;tipo=1&amp;post=133591">este aqui</a>
do Luiz Carlos Prates.</p>

<p>Aleluia!</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=V%C3%ADdeos+do+ClicRBS+agora+em+Flash&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F12%2F17%2Fvideos-do-clicrbs-agora-em-flash%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/12/17/videos-do-clicrbs-agora-em-flash/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Aviso aos navegantes</title>
		<link>http://www.caiomoritz.com/2008/11/18/aviso-aos-navegantes/</link>
		<comments>http://www.caiomoritz.com/2008/11/18/aviso-aos-navegantes/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 11:18:54 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=179</guid>
		<description><![CDATA[Há 2 semanas, após atualizar meu Ubuntu para a versão 8.10 meu teclado parou
de funcionar adequadamente (não tenho mais acentos funcionando,
este post está sendo escrito do local onde trabalho).
A coisa está feia para os brasileiros
usuários de Ubuntu. Eu registrei esse problema no bugtracker deles,
mas até agora nada.

Pra piorar, ainda esta semana uma outra atualização
de pacotes [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Aviso aos navegantes",
	url: "http://www.caiomoritz.com/2008/11/18/aviso-aos-navegantes/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Há 2 semanas, após atualizar meu Ubuntu para a versão 8.10 meu teclado parou
de funcionar adequadamente (não tenho mais acentos funcionando,
este post está sendo escrito do local onde trabalho).
A coisa está feia para os brasileiros
usuários de Ubuntu. Eu <a href="https://bugs.launchpad.net/ubuntu/+bug/294954">registrei esse problema</a> no bugtracker deles,
mas até agora nada.</p>

<p>Pra piorar, ainda esta semana uma <a href="http://www.ubuntero.com.br/?p=613">outra atualização</a>
de pacotes removeu o ponto (.) do teclado. Você apertava o ponto, na tela
aparecia uma vírgula. Esse último problema eu acabei resolvendo com ajuda
desse post do Ubuntero, mas resolver
o problema maior do teclado não está fácil. Minha última atualização do Ubuntu (quando
subi para a 8.04) já havia provocado o mesmo problema,
mas como agora a distribuição adotou um tal de HAL, minha antiga solução não serve mais.</p>

<p>Quando eu conseguir arrumar o problema do teclado volto a postar.</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Aviso+aos+navegantes&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F11%2F18%2Faviso-aos-navegantes%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/11/18/aviso-aos-navegantes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>O polêmico separador de namespaces do PHP</title>
		<link>http://www.caiomoritz.com/2008/10/28/o-polemico-separador-de-namespaces-do-php/</link>
		<comments>http://www.caiomoritz.com/2008/10/28/o-polemico-separador-de-namespaces-do-php/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 11:00:18 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=170</guid>
		<description><![CDATA[Para quem não sabe, é prometida para a versão 5.3 do PHP a adição
de suporte a namespaces. Eu falei um pouco sobre isso no ano passado.

O que acabou criando discórdia entre os desenvolvedores do PHP e os usuários
da linguagem foi a decisão do core team de substituir o então separador de namespaces
:: por uma contra [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "O polêmico separador de namespaces do PHP",
	url: "http://www.caiomoritz.com/2008/10/28/o-polemico-separador-de-namespaces-do-php/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Para quem não sabe, é prometida para a versão 5.3 do PHP a adição
de suporte a namespaces. Eu falei um pouco sobre isso no <a href="http://www.caiomoritz.com/2007/12/22/versao-53-do-php-tera-namespaces/">ano passado</a>.</p>

<p>O que acabou criando discórdia entre os desenvolvedores do PHP e os usuários
da linguagem foi a <a href="http://wiki.php.net/rfc/namespaceseparator">decisão</a> do core team de substituir o então separador de namespaces
<code>::</code> por uma <em>contra barra</em> (<code>\</code>).</p>

<p>Ou seja, código que você futuramente escreveria assim:</p>

<pre><code>Meu::belo::namespace
</code></pre>

<p>Escreverá assim:</p>

<pre><code>Meu\belo\namespace
</code></pre>

<p>Contra-barra é melhor ou pior que dois pontos? Na verdade pra mim tanto faz,
acho que nunca vou utilizar namespaces quando estiver programando PHP. Não que
eles não sejam úteis, mas nunca cheguei a escrever grandes bibliotecas em PHP.
Quando o fiz, não tive problemas em distribui-las por diretórios, utilizando
convenções razoáveis para nomes de classe. Mas, sim, é verdade, é melhor
escrever isso (não sei se esta será a sintaxe escolhida):</p>

<pre><code>using MeuLongoPrefixoParaEvitarConflito;

class FrontController {
}

class FrontControllerHelper {
}
</code></pre>

<p>Do que escrever isto:</p>

<pre><code>class MeuLongoPrefixoParaEvitarConflito_FrontController {
}

class MeuLongoPrefixoParaEvitarConflito_FrontControllerHelper {
}
</code></pre>

<p>O exemplo acima, na minha opinião, justifica a adição de namespaces à linguagem.
Eu não escrevo frameworks PHP, mas quem escreve certamente vai agradecer muito.</p>

<p>Por outro lado, acho que namespaces chegaram tarde demais. Afinal, a linguagem já possui uma
sopa de funções lançadas no namespace global (em torno de 3000 funções,
se não estou enganado). Evidentemente nenhuma dessas funções será remanejada
para um namespace adequada num futuro próximo (em nome da compatiblidade retroativa).</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=O+pol%C3%AAmico+separador+de+namespaces+do+PHP&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F10%2F28%2Fo-polemico-separador-de-namespaces-do-php%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/10/28/o-polemico-separador-de-namespaces-do-php/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Instalando o plugin Flash 10 no Linux</title>
		<link>http://www.caiomoritz.com/2008/10/27/instalando-o-plugin-flash-10-no-linux/</link>
		<comments>http://www.caiomoritz.com/2008/10/27/instalando-o-plugin-flash-10-no-linux/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 21:34:39 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Flash]]></category>

		<category><![CDATA[Linux]]></category>

		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=174</guid>
		<description><![CDATA[Hoje instalei o Flash 10 no meu Ubuntu. O procedimento deve ser bastante parecido
para outras distribuições (exceto se você tem um PC com arquitetura 64 bits, nesse
caso o sofrimento pode ser maior). Antes de iniciar a instalação feche o Firefox.

Vá até o site de download da Adobe. Escolha a versão &#8220;tar.gz para Linux&#8221;. Após o [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Instalando o plugin Flash 10 no Linux",
	url: "http://www.caiomoritz.com/2008/10/27/instalando-o-plugin-flash-10-no-linux/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Hoje instalei o Flash 10 no meu Ubuntu. O procedimento deve ser bastante parecido
para outras distribuições (exceto se você tem um PC com arquitetura 64 bits, nesse
caso o sofrimento pode ser maior). Antes de iniciar a instalação feche o Firefox.</p>

<p>Vá até o <a href="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash&amp;Lang=BrazilianPortuguese">site de download da Adobe</a>. Escolha a versão &#8220;tar.gz para Linux&#8221;. Após o download,
desempacote o arquivo:</p>

<pre><code>tar xzf install_flash_player_10_linux.tar.gz
</code></pre>

<p>E comece a instalação:</p>

<pre><code>cd install_flash_player_10_linux/
sudo ./flashplayer-installer
</code></pre>

<p>Quando perguntado sobre &#8220;path of the Mozilla, Netscape, or Opera browser&#8221;, eu digitei:</p>

<pre><code>/usr/lib/firefox-3.0.3
</code></pre>

<p>Acredito que isso seja algo específico do Ubuntu (a versão exata do Firefox,
obviamente, dependerá da configuração do seu sistema). Nas últimas vezes que precisei instalar o
Flash eu costumava digitar <code>/usr/lib/mozilla-firefox</code>, mas dessa vez não funcionou. Se tiver
problemas com a sua distribuição, tente encontrar dentro de <code>/usr/lib</code> um diretório que tenha
um nome como <code>mozilla</code> ou <code>firefox</code>, e então teste todos eles.</p>

<p>Bom, para testar se tudo deu certo, abra seu Firefox e, por exemplo, vá até o YouTube. Abra qualquer vídeo
e teste se o vídeo toca corretamente. Se sim, clique com o botão direito do mouse sobre o vídeo.
Nessa hora aparecerá um menu contextual, e você verá &#8220;About Flash Player 10&#8243;. É uma forma simples
de verificar se o Firefox está utilizando a nova versão ou a antiga versão do plugin Flash.</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Instalando+o+plugin+Flash+10+no+Linux&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F10%2F27%2Finstalando-o-plugin-flash-10-no-linux%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/10/27/instalando-o-plugin-flash-10-no-linux/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Acessando configurações do banco de dados no Rails</title>
		<link>http://www.caiomoritz.com/2008/10/24/acessando-configuracoes-do-banco-de-dados-no-rails/</link>
		<comments>http://www.caiomoritz.com/2008/10/24/acessando-configuracoes-do-banco-de-dados-no-rails/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 11:00:15 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=144</guid>
		<description><![CDATA[Toda aplicação Rails possui o arquivo config/database.yml, onde você configura
a conexão com o banco de dados nos ambientes de produção, desenvolvimento e teste.
O Rails se encarrega de realizar a conexão com o banco de dados quando a aplicação
é iniciada (com o WEBrick, por exemplo).

E como fazer caso seja necessário, no seu contexto, ter acesso
ao username [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Acessando configurações do banco de dados no Rails",
	url: "http://www.caiomoritz.com/2008/10/24/acessando-configuracoes-do-banco-de-dados-no-rails/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Toda aplicação Rails possui o arquivo <code>config/database.yml</code>, onde você configura
a conexão com o banco de dados nos ambientes de produção, desenvolvimento e teste.
O Rails se encarrega de realizar a conexão com o banco de dados quando a aplicação
é iniciada (com o WEBrick, por exemplo).</p>

<p>E como fazer caso seja necessário, no seu contexto, ter acesso
ao username e password presentes nesse arquivo? Acredito que esses dados não estejam
disponíveis em nenhum dos objetos que o Rails instancia (eu procurei), certamente por questões de
segurança, mas se você realmente precisa carregar esses dados, eis aqui uma forma
bem simples.</p>

<p>De preferência dentro de um controller da sua aplicação (como o <code>ApplicationController</code>),
você pode definir esta linha:</p>

<pre><code>class ApplicationController &lt; ActiveRecord::Base
  @@db_config = YAML.load_file("#{RAILS_ROOT}/config/database.yml")[RAILS_ENV]
end
</code></pre>

<p>Agora você tem em <code>@@db_config</code> um hash (cujas chaves são strings, e não símbolos)
com tudo aquilo que você precisa. Digamos que seu <code>config/database.yml</code> tivesse esta
cara:</p>

<pre><code>production:
  adapter: mysql
  database: teste_production
  username: teste
  password: teste
  timeout: 5000

development:
  adapter: mysql
  database: teste_development
  username: teste
  password: teste
  timeout: 5000
</code></pre>

<p>Se o servidor da aplicação está rodando em modo de desenvolvimento, então a constante
<code>RAILS_ENV</code> guarda <code>development</code>. Por conseqüência, <code>@@db_config['database']</code>, por
exemplo, guarda <code>teste_development</code>.</p>

<p>Por ter sido declarada no escopo de classe de <code>ApplicationController</code>, nesse exemplo
<code>@@db_config</code> estaria disponível em todos os métodos de todos os seus controllers.</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Acessando+configura%C3%A7%C3%B5es+do+banco+de+dados+no+Rails&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F10%2F24%2Facessando-configuracoes-do-banco-de-dados-no-rails%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/10/24/acessando-configuracoes-do-banco-de-dados-no-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Documentação do jQuery em formato CHM</title>
		<link>http://www.caiomoritz.com/2008/10/23/documentacao-do-jquery-em-formato-chm/</link>
		<comments>http://www.caiomoritz.com/2008/10/23/documentacao-do-jquery-em-formato-chm/#comments</comments>
		<pubDate>Thu, 23 Oct 2008 11:00:15 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=163</guid>
		<description><![CDATA[A documentação do jQuery em formato CHM não é novidade, mas o que eu descobri
sem querer é que o autor original do arquivo, volta e meia, gera esse arquivo novamente
e atualiza aquele post com o link para a nova versão. Portanto, vale a pena ficar de olho.

Outra dica importante é que, se você usa Linux, [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Documentação do jQuery em formato CHM",
	url: "http://www.caiomoritz.com/2008/10/23/documentacao-do-jquery-em-formato-chm/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://charupload.wordpress.com/2007/12/07/jquery-documentation-chm/">documentação do jQuery em formato CHM</a> não é novidade, mas o que eu descobri
sem querer é que o autor original do arquivo, volta e meia, gera esse arquivo novamente
e atualiza aquele post com o link para a nova versão. Portanto, vale a pena ficar de olho.</p>

<p>Outra dica importante é que, se você usa Linux, recomendo que abra o arquivo utilizando
o <code>kchmviewer</code>, que renderiza o documento com uma ótima qualidade. Já o <code>xchm</code> deixa
esse documento em especial bem pobre, sem a formatação original, e nem dá vontade de utilizar.</p>

<p>A versão atual do arquivo conta, além da documentação do jQuery, com a documentação
completa do conjunto de extensões jQuery UI (que utilizo e recomendo).</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Documenta%C3%A7%C3%A3o+do+jQuery+em+formato+CHM&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F10%2F23%2Fdocumentacao-do-jquery-em-formato-chm%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/10/23/documentacao-do-jquery-em-formato-chm/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Uma aula prática de jQuery</title>
		<link>http://www.caiomoritz.com/2008/10/22/uma-aula-pratica-de-jquery/</link>
		<comments>http://www.caiomoritz.com/2008/10/22/uma-aula-pratica-de-jquery/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 10:00:59 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=153</guid>
		<description><![CDATA[Quando comecei a utilizar jQuery prometi aqui no blog um artigo
introdutório sobre a biblioteca, que acabei não escrevendo. Acho
que não vai fazer muita falta, afinal há tantos por aí. Mas,
para não passar por tratante, resolvi escrever algo. Afinal, arregacei
as mangas, utilizei bastante a biblioteca e sobrevivi pra contar
a história. Aqui segue uma receita de bolo [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Uma aula prática de jQuery",
	url: "http://www.caiomoritz.com/2008/10/22/uma-aula-pratica-de-jquery/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Quando comecei a utilizar jQuery prometi aqui no blog um artigo
introdutório sobre a biblioteca, que acabei não escrevendo. Acho
que não vai fazer muita falta, afinal há <a href="http://delicious.com/caiomoritz/jquery">tantos por aí</a>. Mas,
para não passar por tratante, resolvi escrever algo. Afinal, arregacei
as mangas, utilizei bastante a biblioteca e sobrevivi pra contar
a história. Aqui segue uma receita de bolo para você aprender como
realizar as tarefas mais corriqueiras com jQuery.</p>

<h2>Nomenclatura</h2>

<p>Durante o texto vou me referir à função <code>$</code> como função <code>jQuery</code>, pois
na verdade elas são a mesma coisa. A diferença é que a função <code>$</code> não
estará disponível se você optar por utilizá-la <em>sem conflitos</em>.</p>

<h2>Como começar</h2>

<p>Antes de escrever qualquer código JavaScript, faço questão de utilizar
aquela técnica clássica onde o nosso código JS começa a ser executado
apenas quando o DOM terminou de ser carregado:</p>

<pre><code>$(document).ready(function() {
    // aqui vai o código específico da sua aplicação
});
</code></pre>

<p>Esse código eu deixo em um arquivo externo, e o referencio a partir
da tag <code>&lt;script&gt;</code> presente no meu template HTML (independente do
framework que você estiver - ou não - utilizando, manter o código JS
fora do seu template HTML é uma forma simples de separar apresentação
e comportamento).</p>

<p>Deste ponto em diante passo a omitir essas linhas de inicialização. Todo
o código que for exibido pode ser posicionado na linha 2 da listagem de código
acima.</p>

<h2>Encontrando elementos</h2>

<p>Cedo ou tarde você precisará encontrar elementos do seu documento e manipulá-los.
Na verdade, boa parte da minha programação JavaScript consiste disso.
Com o jQuery, qualquer ação começa com uma chamada à função jQuery, e com esta
não poderia ser diferente. Para encontrar um elemento você pode passar uma
string que atenda a especificação da biblioteca para <a href="http://docs.jquery.com/Selectors">seletores</a>. Alguns exemplos:</p>

<pre><code>// todos os parágrafos contendo a classe "warning"
$('p.warning');

// todas as checkboxes dentro do elemento de id "users_list"
$('#users_list input[type=checkbox]');
</code></pre>

<h2>Fazendo alguma coisa com os elementos</h2>

<p>Encontrar os elementos e não fazer nada com eles não serve pra muita coisa.
Por exemplo, vamos imaginar que você queira fazer a seguinte operação: quando
o usuário clicar em um link com a classe <code>help</code>, vamos mostrar a ele
um alerta. É algo bem estúpido, e como esperado, simples de fazer:</p>

<pre><code>$('a.help').click(function() {
    alert('Você clicou num parágrafo de ajuda!');
});
</code></pre>

<p>A função jQuery, quando recebe uma string, irá retornar um outro objeto jQuery,
contendo internamente uma lista de todos os elementos encontrados no documento
que satisfazem a sua consulta. Como esse retorno é um outro objeto jQuery, você
já pode realizar uma chamada de função sobre esse objeto (neste caso, <code>click</code>).
Veremos mais adiante como levar esse conceito ao extremo.</p>

<h2>Parando eventos</h2>

<p>Quando definimos o evento para cliques sobre links com a classe <code>help</code>, não evitamos
que a URL especificada no atributo <code>href</code> do link fosse seguida pelo navegador. Se 
esse link tinha como <code>href</code> o símbolo <code>#</code>, então após o clique a barra de rolagem vertical
(se existia) foi movida para o topo do documento.</p>

<p>Para evitar esse comportamento, precisamos utilizar o objeto de tipo <code>Event</code> que o jQuery
envia para a nossa função de processamento de eventos. Veja como:</p>

<pre><code>$('a.help').click(function(e) {
    // o link não será seguido pelo navegador
    e.preventDefault();
});
</code></pre>

<p>Caso você esteja observando a submissão de um formulário, pode utilizar a mesma
técnica para evitar que o formulário seja submetido.</p>

<pre><code>$('form#create_user').submit(function(e) {
    // o formulário não será enviado
    e.preventDefault();
});
</code></pre>

<p>Esses são apenas alguns dos eventos disponíveis, <a href="http://docs.jquery.com/Events">aqui</a> você pode encontrar todos eles.</p>

<h2>Manipulando as classes de um elemento</h2>

<p>Você tem à disposição 3 métodos básicos para manipular as classes
de elementos. Aprenda a utilizá-los com exemplos:</p>

<pre><code>// adiciona a classe "teste" ao parágrafo
$('p:first').addClass('teste')

// remove a classe "teste" ao parágrafo
$('p:first').removeClass('teste')

// adiciona (se não existir) ou remove (se existir) a classe "teste" ao parágrafo
$('p:first').toggleClass('teste')
</code></pre>

<h2>Acessando atributos</h2>

<p>Acessar atributos é algo trivial com jQuery:</p>

<pre><code>// recupera o "href" do link
var id = $('a#add_another_row').attr('id');

// define o "href" do link
var id = $('a#add_another_row').attr('href', '#');
</code></pre>

<p>Note que <code>attr</code> atua apenas sobre o primeiro elemento interno a um objeto jQuery.
Por atributos, nesse caso, entende-se as <em>propriedades</em> de um elemento <em>HTML</em> (diferente
de suas propriedades de estilo).</p>

<h2>Definindo estilos de elementos</h2>

<p>Sempre que possível procuro manter todos os estilos associados ao documento
dentro das minhas definições CSS. Assim, se quero modificar o visual do sistema,
sei que é apenas lá que devo mexer. Mas em algumas situações me vi obrigado a quebrar
essa regra. São casos onde você precisará manipular propriedades CSS específicas de
elementos.</p>

<pre><code>$('a#do_something_crazy').click(function(e) {
    e.preventDefault();

    // vamos recuperar a cor do link
    alert("Agora o link tem cor " + $(this).css('color'));

    // agora vamos alterar apenas a cor do link
    $(this).css('color', 'blue');

    // agora vamos alterar as propriedades CSS "color" e "background-color" do link
    $(this).css({
        color: 'green',
        backgroundColor: 'red'
    });
});
</code></pre>

<p>Na listagem acima apresentei as 3 formas de utilizar a função <code>css</code>:</p>

<ul>
<li><code>css(propriedade)</code>: recupera o valor de &#8220;propriedade&#8221;</li>
<li><code>css(propriedade, valor)</code>: define o valor de &#8220;propriedade&#8221; como &#8220;valor&#8221;</li>
<li><code>css(objeto)</code>: define diversos pares de &#8220;propriedade/valor&#8221;</li>
</ul>

<h2>Encontrando elementos ancestrais</h2>

<p>Imagine que você está definindo um tratador de evento sobre um link. Esse link
está dentro de uma célula de tabela (<code>td</code>), que por sua vez está dentro de uma
linha de tabela (<code>tr</code>). No contexto do tratamento desse evento, seu objeto atual,
associado à variável <code>this</code>, é esse link. Nesse momento você percebe que precisa,
por algum motivo, do <code>id</code> da linha onde está link (isso acontece bastante comigo).
Para esses casos utilize a função <code>parents</code>, que retorna todos os ancentrais do elementos
do objeto jQuery atual.</p>

<pre><code>$('a#do_something').click(function(e) {
    var rowId = $(this).parents('tr:first').attr('id');
});
</code></pre>

<p>Como <code>parents</code> retorna <em>todos</em> os ancestrais, passamos à função um seletor jQuery, indicando
que queremos apenas a primeira linha. Simples, rápido e indolor.</p>

<h2>Encontrando elementos filhos</h2>

<p>Já vimos como encontrar ancestrais. Quando você quer fazer o caminho inverso, é só utilizar
a função <code>find</code>. Por exemplo, imagine que você está processando a submissão de um formulário
e precisa encontrar vários campos desse formulário, para validá-los. Se eles não possuem <code>id</code>&#8217;s
associados, o <code>find</code> será uma mão na roda.</p>

<pre><code>$('form#authentication').submit(function(e) {
    e.preventDefault();
    var username = $(this).find('input[name=username]').val();
    var password = $(this).find('input[name=password]').val();
});
</code></pre>

<h2>Valores de elementos</h2>

<p>Utilize a função <code>val</code> para descobrir o conteúdo de determinados elementos
(como o conteúdo de uma caixa de texto, por exemplo):</p>

<pre><code>$('#username').val();
</code></pre>

<p>Funções semelhantes são <code>text</code> e <code>html</code>.</p>

<h2>Realizando tarefas de acordo com o navegador do usuário</h2>

<p>Como avisar ao seu usuário que você, por exemplo, está utilizando uma biblioteca
baseada no elemento <code>canvas</code>, e que a experiência desse usuário no Internet Explorer
não será tão boa (baixa performance)? Verifique que navegador ele está utilizando:</p>

<pre><code>if ($.browser.msie) {
    alert('Experimente o Firefox!');
}
</code></pre>

<p>Você pode realizar testes para outros navegadores também, é claro. Dê uma olhada na
documentação dos <a href="http://docs.jquery.com/Utilities">utilitários</a> da biblioteca.</p>

<h2>Inserindo elementos no documento</h2>

<p>Volta e meia crio pequenos frameworks baseados em classes de elementos, de forma a evitar
a repetição de código HTML. Nesses casos sempre é bom poder inserir código HTML arbitrário
após a carga do documento. Eis como fazer isso com jQuery:</p>

<pre><code>$('&lt;p&gt;Este parágrafo foi inserido dinamicamente!&lt;/p&gt;').appendTo('body');
$('&lt;p&gt;Este parágrafo também foi inserido dinamicamente!&lt;/p&gt;').prependTo('body');
</code></pre>

<p>Como podemos ver, quando a string enviada à função jQuery não é reconhecida como um seletor,
ela é reconhecida como um elemento a ser criado (não sei se é exatamente essa a implementação
interna, mas se você pensar assim não terá problemas para entender a diferença entre enviar 
uma string como seletor ou um novo elemento HTML).</p>

<p>As funções <code>appendTo</code> e <code>prependTo</code> são muito úteis nesses casos. Com elas você indica que
quer inserir um elemento como último ou como primeiro filho do elemento passado como parâmetro.</p>

<p>Sendo honesto: muitas vezes preciso inserir muito mais HTML do que uma
linhazinha dessas. Em situações reais já precisei inserir grandes trechos de formulário, por
exemplo. Não tenha medo: insira uma contra-barra ao fim de cada linha e prolongue sua string
HTML por diversas linhas:</p>

<pre><code>$('&lt;p class="input_row"&gt; \
   &lt;input id="username" type="text" /&gt; \
   &lt;/p&gt; \
   ...'
  )
  .prependTo($('form#auth'));
</code></pre>

<h2>Criando um cache</h2>

<p>Quando você precisa fazer 2 operações diferentes utilizando o mesmo seletor, mas em pontos
diferentes do código, é interessante atribuir o objeto jQuery que contém o resultado da consulta
a uma variável, para evitar o custo de processamento de uma nova consulta.</p>

<p>Portanto, isto não é legal:</p>

<pre><code>$('a.special').click(function() {
    //
});

// muitas linhas depois...

$('a.special').hover(function() {
    //
});
</code></pre>

<p>Isto é legal:</p>

<pre><code>var $specialLinks = $('a.special');

$specialLinks.click(function() {
    //
});

// muitas linhas depois...

$specialLinks.hover(function() {
    //
});
</code></pre>

<p>Note que utilizei um cifrão como prefixo para a variável <code>$specialLinks</code>. Considero
isso uma boa prática dentro de código JS que utilize jQuery, pois deixa bem claro
quais variáveis são objetos jQuery e quais não são. Se você for estudar o código de
plugins é provável que encontre essa mesma convenção sendo seguida.</p>

<h2>Encadeando funções</h2>

<p>Como disse anteriormente, toda função jQuery que você invoca a partir de um objeto
jQuery retorna o próprio objeto jQuery. Isso significa que em vez de fazer isto:</p>

<pre><code>var $newP = $('&lt;p class="warning"&gt;&lt;/p&gt;');
$newP.css('width', '100%');
$newP.appendTo('body');
</code></pre>

<p>Você pode fazer isto:</p>

<pre><code>$('&lt;p class="warning"&gt;&lt;/p&gt;')
    .css('width', '100%')
    .appendTo('body');
</code></pre>

<p>Sim, você pode encadear quantas chamadas quiser.</p>

<p>Em inglês o termo para esse encadeamento de chamadas é <em>chaining</em>. Quando vi
o código disposto dessa forma pela primeira vez não gostei nenhum pouco, pensei: &#8220;nunca vou fazer isso!&#8221;.
Mas hoje, se você abrir meus arquivos JS verá encadeamento de chamadas por todo lado.
Acho que isso vicia, simplesmente.</p>

<p>Se você for utilizar aquele parágrafo em algum outro ponto do código, crie um cache
para ele no momento da criação:</p>

<pre><code>var $warningP = $('&lt;p class="warning"&gt;&lt;/p&gt;')
    .css('width', '100%')
    .appendTo('body');
</code></pre>

<h2>Utilizando plugins</h2>

<p>Sem plugins o jQuery já teria sido uma grande idéia, mas com a possibilidade de definir
novas funções para o objeto jQuery, fica difícil reclamar dessa biblioteca. Em geral
um plugin jQuery tem um nome bastante sugestivo (como <code>tablesorter</code>), e o nome dele
indica exatamente qual o nome da função que corresponde ao plugin.</p>

<p>Para utilizar qualquer plugin jQuery basta incluir no seu cabeçalho HTML uma referência
(tag <code>&lt;script&gt;</code>) ao código-fonte do plugin após ter referenciado o código-fonte do jQuery.
Digamos que estejamos utilizando o plugin <code>tablesorter</code>, capaz de dar à tabelas HTML
poderes de ordenação de colunas. Eu utilizaria o plugin da seguinte forma:</p>

<pre><code>// primeiro verifique se o plugin foi carregado
if ($.fn.tablesorter) {
    $('table.record_list').tablesorter();
}
</code></pre>

<p>Com o código acima aplicamos o comportamento oferecido pelo plugin a todas as tabelas
de classe <code>record_list</code> do documento.</p>

<p>Note que a grande maioria dos plugins opta pela simplicidade: eles funcionam sem que você
passe parâmetros para a função principal. Se você precisar passar parâmetros, em geral
você irá passar um objeto literal, o qual sobrescreverá as opções padrão do plugin.</p>

<h2>jQuery e Firebug</h2>

<p>Dentro de um projeto que utiliza o jQuery, tire o máximo de proveito da biblioteca. Se
aquele seletor jQuery que você escreveu não está funcionando, copie e cole o código no
console do <a href="http://getfirebug.com/">Firebug</a> e veja a resposta. Se a resposta do console for simplesmente um array
vazio, quer dizer que seu seletor não casou com nenhum elemento. Caso contrário, você verá
uma representação dos elementos que casaram.</p>

<p>Além de fazer consultas no documento, gosto de manipular os elementos que encontro via
Firebug. Por exemplo:</p>

<pre><code>$('p.warning:first').css('background-color', 'red');
</code></pre>

<p>Acho mais fácil que utilizar o editor de CSS embutido no Firebug.</p>

<h2>Um exemplo completo</h2>

<p>Nosso documento contém uma tabela com a classe <code>record_list</code>, a qual está envolvida
por uma <code>div#table_panel</code>. Após o carregamento da página, vamos adicionar um link abaixo
dessa tabela. Esse link, quando clicado, adiciona uma nova linha à tabela.
Este exemplo sozinho não serve para nada, mas utilizei a mesma idéia aqui no meu projeto
para criar uma tabela que exibia todas as curvas de um gráfico. Para adicionar mais uma
curva ao gráfico, eu utilizava essa mesma abordagem: primeiro adicionava a nova linha,
e em seguida gerava o gráfico novamente, via Ajax.</p>

<pre><code>$(document).ready(function() {
    $('&lt;a href="#" id="create_new_line"&gt;Criar nova linha&lt;/a&gt;')
        .click(function(e) {
            e.preventDefault();
            $('&lt;tr&gt; \
                 &lt;td&gt;...&lt;/td&gt; \
                 &lt;td&gt;...&lt;/td&gt; \
                 &lt;td&gt;...&lt;/td&gt; \
               &lt;/tr&gt;'
            )
            .appendTo('table.record_list:first');
        })
        .appendTo('#table_panel');
});
</code></pre>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Uma+aula+pr%C3%A1tica+de+jQuery&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F10%2F22%2Fuma-aula-pratica-de-jquery%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/10/22/uma-aula-pratica-de-jquery/feed/</wfw:commentRss>
		</item>
		<item>
		<title>O PHP suporta expressões regulares estendidas</title>
		<link>http://www.caiomoritz.com/2008/09/30/o-php-suporta-expressoes-regulares-estendidas/</link>
		<comments>http://www.caiomoritz.com/2008/09/30/o-php-suporta-expressoes-regulares-estendidas/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 11:30:39 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[RegExp]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=141</guid>
		<description><![CDATA[Para saber o que são expressões regulares estendidas, recomendo
que leia este artigo aqui do blog. Então por que estou falando nisso
de novo?

Semana passada, estudando um certo script PHP, me deparei com uma validação
manual de data que utilizava o seguinte código (talvez as mensagens para o usuário
não fossem exatamente essas, é verdade):

if (!ereg('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]:[0-9][0-9]:[0-9][0-9]', $date)) {
  [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "O PHP suporta expressões regulares estendidas",
	url: "http://www.caiomoritz.com/2008/09/30/o-php-suporta-expressoes-regulares-estendidas/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>Para saber o que são expressões regulares estendidas, recomendo
que leia <a href="http://www.caiomoritz.com/2008/08/09/expressoes-regulares-estendidas-com-grep/">este artigo</a> aqui do blog. Então por que estou falando nisso
de novo?</p>

<p>Semana passada, estudando um certo script PHP, me deparei com uma validação
manual de data que utilizava o seguinte código (talvez as mensagens para o usuário
não fossem exatamente essas, é verdade):</p>

<pre><code>if (!ereg('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]:[0-9][0-9]:[0-9][0-9]', $date)) {
    echo 'Data inválida! Se deu mal!';
} else {
    echo 'Hoje passa... mas não acostuma!';
}
</code></pre>

<p>A idéia é validar uma data no formato <code>AAAA-MM-DD_HH:mm:SS</code>. Não ficou muito
óbvio, certo? Expressões regulares já são complexas por natureza, então é um
pecado mortal complicar aquelas que podem ser definidas de maneira simples.</p>

<p>Como a função <code>ereg</code> suporta expressões regulares <em>estendidas</em> (e há exatamente
esse exemplo na <a href="http://br2.php.net/manual/en/function.ereg.php">documentação oficial</a>!) o código pode ser reduzido para:</p>

<pre><code>if (!ereg('[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}:[0-9]{2}:[0-9]{2}', $date)) {
    echo 'Data inválida! Se deu mal!';
} else {
    echo 'Hoje passa... mas não acostuma!';
}
</code></pre>

<p>A <em>Dona Legibilidade de Código</em> agradece!</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=O+PHP+suporta+express%C3%B5es+regulares+estendidas&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F09%2F30%2Fo-php-suporta-expressoes-regulares-estendidas%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/09/30/o-php-suporta-expressoes-regulares-estendidas/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Uma funcionalidade do PHP que eu gostaria que não existisse</title>
		<link>http://www.caiomoritz.com/2008/09/29/uma-funcionalidade-do-php-que-eu-gostaria-que-nao-existisse/</link>
		<comments>http://www.caiomoritz.com/2008/09/29/uma-funcionalidade-do-php-que-eu-gostaria-que-nao-existisse/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 11:30:42 +0000</pubDate>
		<dc:creator>Caio Moritz Ronchi</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.caiomoritz.com/?p=136</guid>
		<description><![CDATA[É o maldito $$!

Infelizmente há programadores que gostam dele, e usam como bengala para
situações onde um simples array associativo daria conta do recado. Mas saiba
que um dia (uma semana, um mês, um ano depois) alguém vai pegar esse código,
e essa pessoa vai sofrer.

Se você não sabe o que é o $$, recomendo que continue lendo, [...]

<script type="text/javascript">
SHARETHIS.addEntry({
	title: "Uma funcionalidade do PHP que eu gostaria que não existisse",
	url: "http://www.caiomoritz.com/2008/09/29/uma-funcionalidade-do-php-que-eu-gostaria-que-nao-existisse/"
});
</script>
	]]></description>
			<content:encoded><![CDATA[<p>É o maldito <code>$$</code>!</p>

<p>Infelizmente há programadores que gostam dele, e usam como bengala para
situações onde um simples array associativo daria conta do recado. Mas saiba
que um dia (uma semana, um mês, um ano depois) alguém vai pegar esse código,
e essa pessoa vai sofrer.</p>

<p>Se você não sabe o que é o <code>$$</code>, recomendo que continue lendo, pois um dia
você pode precisar dar manutenção em um código desses. Se já sabe, por favor,
deixe um comentário dando uma razão racional para utilizá-lo (e não &#8220;eu tenho
preguiça de escrever arrays associativos&#8221;).</p>

<p>Para exemplificar o uso do <code>$$</code>, vamos considerar a idéia (insegura) de transformar
todas as chaves do array superglobal <code>$_GET</code> em variáveis. O código é o seguinte:</p>

<pre><code>foreach ($_GET as $key =&gt; $value) {
    $$key = $value;
}
</code></pre>

<p>Ok, você não entendeu o que está acontecendo. Imagine que o script que define esse
código é o <code>test.php</code>, e que ele está hospedado em <code>http://www.example.com/test.php</code>.
Vamos apontar nosso browser para esse script e passar 2 variáveis: <code>color</code> e <code>height</code>.
A URL seria:</p>

<pre><code>http://www.example.com/test.php?color=red&amp;height=3
</code></pre>

<p>O que o loop <code>foreach</code> está fazendo? Para cada par chave/valor (<code>$key</code>/<code>$value</code>) do nosso array (<code>$_GET</code>), 
é definida uma variável cujo nome é igual à chave do array (<code>$key</code>), e seu valor é igual
ao valor para o qual aquela chave do array aponta. Não entendeu nada ainda? Vamos de novo:</p>

<blockquote>
  <p><code>$$um_variavel_qualquer</code> referencia uma variável cujo nome depende do <em>valor</em> presente
  na variável <code>$uma_variavel_qualquer</code>.</p>
</blockquote>

<p>Outro exemplo:</p>

<pre><code>$nome = 'Caio';
$$nome = 'Programador';
echo $Caio;
</code></pre>

<p>Esse programa dá como resultado:</p>

<pre><code>Programador
</code></pre>

<p>Portanto, após a execução do <code>foreach</code>, as variáveis <code>$color</code> e <code>$height</code> estarão disponíveis.
Isso pode parecer legal à primeira vista, mas não é. Fora as questões de insegurança que ela
levanta (que você pode encontrar facilmente pelo Google), é complicada pegar um script não-MVC
de, digamos, 500 linhas, que você não escreveu, e tentar entender quando a variável <code>$um_nome_muito_maluco</code>
foi definida. Você vai subindo pelo script, chega ao topo e viu que na verdade ela não foi definida
explicitamente, mas sim dentro de um loop <code>foreach</code> que utiliza o mágico <code>$$</code>. Você já terá perdido
uns 10 minutos (sendo otimista) no momento em que se deu conta disso, e vai se lembrar
deste post (eu espero).</p>

<p>Portanto, tenha piedade do programador que dará manutenção no seu código no futuro. Lembre-se
de que esse programador pode ser você mesmo.</p>
<p><a href="http://sharethis.com/item?publisher=21d829e2-ba9c-442f-b7cb-4b660120b739&title=Uma+funcionalidade+do+PHP+que+eu+gostaria+que+n%C3%A3o+existisse&url=http%3A%2F%2Fwww.caiomoritz.com%2F2008%2F09%2F29%2Fuma-funcionalidade-do-php-que-eu-gostaria-que-nao-existisse%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.caiomoritz.com/2008/09/29/uma-funcionalidade-do-php-que-eu-gostaria-que-nao-existisse/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
