<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/1.5.1-alpha" -->
<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/"
>

<channel>
	<title>Pensamento Web</title>
	<link>http://cauguanabara.blogsome.com</link>
	<description>Blog de Cau Guanabara - desenvolvedor web em PHP / Javascript-DOM-CSS</description>
	<pubDate>Fri, 10 Aug 2007 13:40:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=1.5.1-alpha</generator>
	<language>en</language>

		<item>
		<title>Como construir um plugin para o WordPress</title>
		<link>http://cauguanabara.blogsome.com/2007/08/09/como-construir-um-plugin-para-o-wordpress/</link>
		<comments>http://cauguanabara.blogsome.com/2007/08/09/como-construir-um-plugin-para-o-wordpress/#comments</comments>
		<pubDate>Fri, 10 Aug 2007 01:55:44 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>PHP</category>
	<category>Web 2.0</category>
		<guid>http://cauguanabara.blogsome.com/2007/08/09/como-construir-um-plugin-para-o-wordpress/</guid>
		<description><![CDATA[	Como deixei claro no meu último post, recentemente resolvi vender alguns sites com administra&ccedil;&atilde;o via WP - o que me exigiu esfor&ccedil;o para achar alguma informa&ccedil;&atilde;o sobre como criar temas e plugins para WordPress. Meu ingl&ecirc;s é péssimo e ler um artigo nesse idioma pode ser uma tarefa cansativa e demorada (e &agrave;s vezes impossível) [...]]]></description>
			<content:encoded><![CDATA[	<p>Como deixei claro no meu último post, recentemente resolvi vender alguns sites com administra&ccedil;&atilde;o via WP - o que me exigiu esfor&ccedil;o para achar alguma informa&ccedil;&atilde;o sobre como criar temas e plugins para WordPress. Meu ingl&ecirc;s é péssimo e ler um artigo nesse idioma pode ser uma tarefa cansativa e demorada (e &agrave;s vezes impossível) para mim. A documenta&ccedil;&atilde;o no site do Wordress é clara e bastante completa, mas tudo está em ingl&ecirc;s&#8230; por isso resolvi escrever este post dando algumas dicas e mostrando o método que usei depois de <em>decifrar</em> alguns artigos de documenta&ccedil;&atilde;o e destrinchar alguns plugins que baixei da rede. </p>
<a id="more-36"></a>
<p>O WordPress hoje conta com uma API (Application Programming Interface) para dar suporte ao desenvolvimento de plugins que facilita as coisas de um modo incrível, tornando a tarefa de escrever um plugin algo bastante tranquilo, sem grandes dificuldades e sem interferir no funcionamento do núcleo do WP. Usando o que eles chamaram de &quot;Hooks&quot; (ganchos) podemos definir fun&ccedil;&otilde;es para serem executadas em momentos específicos a execu&ccedil;&atilde;o do WordPress, quando o usuário fizer isso ou aquilo ou filtrar conteúdos antes que sejam enviados para a tela. </p>
	<h4>O que é um plugin?</h4>
	<p>Um plugin, por defini&ccedil;&atilde;o, é um programa que se conecta em outro para ampliar as funcionalidades ou resolver problemas deste segundo. Normalmente um plugin para WordPress adiciona ou modifica algo no conteúdo ou na apresenta&ccedil;&atilde;o do blog e oferece uma interface para configura&ccedil;&otilde;es e/ou outras a&ccedil;&otilde;es na administra&ccedil;&atilde;o do WP. </p>
	<p>Ao construir um plugin para qualquer aplicativo, há certos cuidados que deveríamos tomar. </p>
	<ul>
<li><strong>Evite colis&otilde;es de nomes de fun&ccedil;&otilde;es e variáveis</strong><br />é prudente usar um prefixo em todos os nomes, como &quot;myplug_&quot;</li>
	<li><strong>N&atilde;o modifique arquivos originais do programa</strong><br />para n&atilde;o haver problemas se o plugin for desinstalado</li>
	<li><strong>Crie um sistema de desinstala&ccedil;&atilde;o </strong><br />evitando deixar arquivos perdidos ou dados inúteis poluindo a database se o plugin for desinstalado</li>
	<li><strong>Evite erros desnecessários de imcompatibilidade</strong><br />testando pela exist&ecirc;ncia de variáveis, fun&ccedil;&otilde;es e classes antes de tentar usá-las no seu código</li>
</ul>
	<h4>A estrutura do plugin</h4>
	<p>Para ser aceito como um plugin utilizável, há apenas uma exig&ecirc;ncia: é preciso criar um cabe&ccedil;alho segundo certas regras, como descrito <a href="http://codex.wordpress.org/Writing_a_Plugin#File_Headers" target="_blank">aqui (em ingl&ecirc;s)</a>. Veja um exemplo:</p>
	<div class="codigo">&lt;?php <br />/* <br />Plugin Name: Nome do Plugin <br />Plugin URI: homepage do plugin <br />Description: Descri&ccedil;&atilde;o do plugin. <br />Version: Número da vers&atilde;o, como 1.0 <br />Author: Nome do autor do plugin <br />Author URI: Homepage do autor do plugin<br />*/ <br />?&gt; </div>
	<p>Após inserir esses dados no seu arquivo (.php) e colocá-lo em &quot;&#8230;/wp-contents/plugins/&quot; ele já estará disponível na página de gerenciamento de plugins da administra&ccedil;&atilde;o do WP. </p>
	<p>Esse cabe&ccedil;alho deve ser colocado apenas no arquivo principal do plugin e deve estar no diretório citado acima, solto ou em um subdiretório, como em &quot;&#8230;/wp-contents/plugins/myplug/myplug.php&quot;. N&atilde;o importa o nome que voc&ecirc; der ao arquivo, o WP vai procurar por algo semelhante ao cabe&ccedil;alho mostrado acima em todos os arquivos PHP no diretório pluins e em seus subdiretórios (apenas um nível). </p>
	<p>Naturalmente, um plugin pode ter vários arquivos, mas tudo deve ser detonado a partir do arquivo principal, que contém o cabe&ccedil;alho. É ele que vai ser executado se o plugin estiver ativado. </p>
	<h4>O que faz o seu plugin?</h4>
	<p>Existem centenas de plugins para WordPress disponíveis na web, alguns super bem feitos, outros nem tanto&#8230; Antes de iniciar seu plugin, busque na rede. Talvez haja algo pronto que atenda &agrave;s suas necessidades. </p>
	<p>Mas se voc&ecirc; teve uma idéia genial ou tem uma necessidade específica, mantenha em mente o seu objetivo e m&atilde;os &agrave; obra! </p>
	<h4>Entendendo os Hooks</h4>
	<p>Há dois tipos de ganchos para usar em seu plugin: </p>
	<ul>
<li><strong>Actions</strong> (a&ccedil;&otilde;es) <a href="http://codex.wordpress.org/Plugin_API#Actions" target="_blank">refer&ecirc;ncia (ingl&ecirc;s)</a><br />As actions nos d&atilde;o a possibilidade de executar fun&ccedil;&otilde;es em situa&ccedil;&otilde;es determinadas da execu&ccedil;&atilde;o do WordPress, como ao escrever um post, ao editar um post, etc. </li>
	<li><strong>Filters</strong> (filtros) <a href="http://codex.wordpress.org/Plugin_API#Filters" target="_blank">refer&ecirc;ncia (ingl&ecirc;s)</a> <br />Os filters permitem literalmente filtrar a sáida de dados do WP. Podemos por exemplo procurar por &quot;:)&quot; no texto dos posts e substituir por um smile em imagem (claro que isso já existe&#8230;) . Nesse caso, nossa fun&ccedil;&atilde;o recebe o texto do post depois de processado pelo WP e antes de ser impresso na tela, processa e retorna, só ent&atilde;o o texto é exibido.</li>
</ul>
	<p>Para usar actions e filters existem duas fun&ccedil;&otilde;es específicas, que recebem par&acirc;metros iguais:</p>
	<div class="codigo"><a href="http://codex.wordpress.org/Function_Reference/add_action" target="_blank">add_action</a>(&#8217;<a href="http://codex.wordpress.org/Plugin_API#Actions" target="_blank">action_id</a>&#8216;, &#8216;nome_da_sua_fun&ccedil;&atilde;o&#8217;); <br /><a href="http://codex.wordpress.org/Function_Reference/add_filter" target="_blank">add_filter</a>(&#8217;<a href="http://codex.wordpress.org/Plugin_API#Filters" target="_blank">filter_id</a>&#8216;, &#8216;nome_da_sua_fun&ccedil;&atilde;o&#8217;);</div>
	<p>Há dois par&acirc;metros opcionais relativos &agrave; prioridade para a execu&ccedil;&atilde;o da fun&ccedil;&atilde;o e aos par&acirc;metros recebidos por sua fun&ccedil;&atilde;o, mas nem falaremos deles - apenas os dois primeiros s&atilde;o obrigatórios e s&atilde;o suficientes. Quando sua fun&ccedil;&atilde;o for executada, estará literalmente &quot;dentro&quot; do WordPress, com acesso a fun&ccedil;&otilde;es e variáveis. Antes de sair escrevendo, consulte a refer&ecirc;ncia de fun&ccedil;&otilde;es do WP e, se necessário, vá olhar a fun&ccedil;&atilde;o sobre a qual tiver dúvidas. Isso evitará a constru&ccedil;&atilde;o de fun&ccedil;&otilde;es redundantes, diminuindo consideravelmente seu código - o WP tem muitas fun&ccedil;&otilde;es úteis e disponíveis. Quanto &agrave;s variáveis, vale dar uma pesquisada para encontrar os dados que procura&#8230; tudo está &quot;flutuando&quot; nas variáveis globais do WP. </p>
	<p>A linha de código abaixo vai retornar um resultado enorme, mas vai te ajudar a achar o que procura. Muitos dos valores est&atilde;o em objetos, como em $post, que contém os dados de um post, e é importante lembrar que para acessar as propriedades n&atilde;o funciona a fórmula do array, como em $post[&#8217;ID&#8217;], o correto é $post-&gt;ID. </p>
	<div class="codigo">// No início do seu plugin:<br />// Descomente para ver os dados ao seu alcance: </p>
	<p>// die(print_r($GLOBALS, true)); </p>
	<p>// Para recuperar um dos valores globais, n&atilde;o <br />// esque&ccedil;a de colocar dentro de sua fun&ccedil;&atilde;o:<br />// global $varn; <br />// (torna acessível o valor em $GLOBALS[&quot;varn&quot;])</div>
	<p>Ok, com os hooks posso executar qualquer coisa para implementar a funcionalidade proposta pelo meu plugin. Mas e para inserir uma página na administra&ccedil;&atilde;o do WP? </p>
	<h4>Inserindo uma página na administra&ccedil;&atilde;o do WordPress </h4>
	<p>Aqui a liberdade é total. Podemos criar um novo item no menu principal e depois criar subpáginas para esse tópico ou simplesmente criar uma subpágina para um item existente, como em Options, por exemplo - muito usado pelos plugins. Para fazer isso, usamos as fun&ccedil;&otilde;es:</p>
	<p class="codigo"><a href="http://codex.wordpress.org/Adding_Administration_Menus#Top-Level_menu" target="_blank">add_menu_page</a>(page_title, menu_title, access_level/capability, file, [function]);</p>
	<p>add_menu_page adiciona um item ao menu principal. Essa op&ccedil;&atilde;o nas últimas vers&otilde;es do WP pode ser desabilitada pelo administrador, portanto deve ser usada com cautela. </p>
	<p class="codigo"><a href="http://codex.wordpress.org/Adding_Administration_Menus#Sub-Menus" target="_blank">add_submenu_page</a>(parent, page_title, menu_title, access_level/capability, file, [function]); </p>
	<p>add_submenu_page adiciona um item a um tópico do menu principal, seja uma das páginas padr&atilde;o do WP ou um tópico criado com add_menu_page(). </p>
	<p>Veja os par&acirc;metros:</p>
	<ul>
<li>parent -&gt; o arquivo relativo ao tópico do menu principal - apenas para add_submenu_page() </li>
	<li>page_title -&gt; valor que será aplicado ao título da página </li>
	<li>menu_title -&gt; Rótulo do item que será inserido no menu </li>
	<li>access_level/capability -&gt; nível ou capacidade do usuário<br />Aqui definimos que usuários ter&atilde;o acesso &agrave;s funcionalidades do nosso plugin (os níveis v&atilde;o de 0 a 10 e as capacidades s&atilde;o: administrator, editor, author, contributor e subscriber).</li>
	<li>file -&gt; o endere&ccedil;o do arquivo PHP que é a interface do plugin ou um ID (uma string de identifica&ccedil;&atilde;o) para a página, se voc&ecirc; optou por usar o par&acirc;metro seguinte (function) </li>
	<li>function -&gt; o nome da fun&ccedil;&atilde;o que inclui ou mostra a iterface do plugin. </li>
</ul>
	<h4>Guardando seus dados </h4>
	<p>Seu plugin pode usar a database de duas formas:</p>
	<ul>
<li><strong><a href="http://codex.wordpress.org/Creating_Tables_with_Plugins" target="_blank">Criando tabelas no banco de dados</a></strong>
<p>Para criar suas próprias tabelas, é preciso seguir certas normas. </p>
	<ul>
<li>Talvez seja prudente antes de qualquer coisa tentar entender a classe wpdb - <a href="http://codex.wordpress.org/Function_Reference/wpdb_Class" target="_blank">aqui (em ingl&ecirc;s)</a> </li>
	<li>N&atilde;o esque&ccedil;a de que o administrador pode configurar um prefixo para as tabelas no banco, portanto é importante usar esse prefixo que está em $wpdb-&gt;prefix. </li>
	<li>Use o hook &quot;activate_[arquivo_do_plugin]&quot; para chamar a fun&ccedil;&atilde;o de instala&ccedil;&atilde;o</li>
	<li>Aqui é mais importante que nunca ter uma fun&ccedil;&atilde;o de desinstala&ccedil;&atilde;o, chamada através do hook &quot;deactivate_[arquivo_do_plugin]&quot; </li>
</ul>
	<p>&nbsp;</p>
</li>
	<li><strong><a href="http://codex.wordpress.org/Writing_a_Plugin#WordPress_Options_Mechanism" target="_blank">Usando as fun&ccedil;&otilde;es nativas do WordPress</a> </strong>
<p>O WordPress oferece algumas fun&ccedil;&otilde;es para os plugins armazenarem informa&ccedil;&otilde;es no banco de dados, o chamado &quot;Mecanismo de op&ccedil;&otilde;es&quot;, que nos permite guardar variáveis serializadas no banco de dados. Essas variáveis podem ser de vários tipos, acho que até objetos (se voc&ecirc; usar a propriedade mágica __SLEEP), sei lá. Veja as fun&ccedil;&otilde;es que implementam a idéia: </p>
	<ul>
<li><a href="http://codex.wordpress.org/Function_Reference/add_option" target="_blank">add_option</a>(option_name, value, [description], [autoload])</li>
	<li><a href="http://codex.wordpress.org/Function_Reference/get_option" target="_blank">get_option</a>(option_name)</li>
	<li><a href="http://codex.wordpress.org/Function_Reference/update_option" target="_blank">update_option</a>(option_name, value, [description], [autoload])</li>
	<li><a href="http://codex.wordpress.org/Function_Reference/delete_option" target="_blank">delete_option</a>(option_name)</li>
</ul>
	<p>&nbsp;</p>
	<p><strong>Os par&acirc;metros</strong></p>
As fun&ccedil;&otilde;es recebem par&acirc;metros semelhantes, sendo que description e autoload s&atilde;o aplicáveis apenas
<ul>
<li>option_name -&gt; nome da op&ccedil;&atilde;o. </li>
	<li>value -&gt; valor (inicial ou novo valor) da op&ccedil;&atilde;o. </li>
	<li>description -&gt; Uma descri&ccedil;&atilde;o da op&ccedil;&atilde;o sem muito uso prático. (opcional) </li>
	<li>autoload -&gt; pode-se usar esse par&acirc;metro para definir se a op&ccedil;&atilde;o será carregada automaticamente ou n&atilde;o. Também sem muito uso. (opcional) </li>
</ul>
</li>
</ul>
	<h4>Usando Javascript e CSS em seu plugin</h4>
	<p>O WordPress oferece duas fun&ccedil;&otilde;es para incluir o seu script automaticamente, carregando até bibliotecas como o prototype se voc&ecirc; especificar, mas eu n&atilde;o pesquisei nem usei essas fun&ccedil;&otilde;es (wp_print_scripts, wp_register_script, wp_deregister_script e wp_enqueue_script - todas sem refer&ecirc;ncia oficial).</p>
	<p>Mas sem usar essas fun&ccedil;&otilde;es, como fazer? Simples. Como já foi dito, temos acesso &agrave; todos os &quot;momentos&quot; da execu&ccedil;&atilde;o do WP - isso significa que podemos escolher quando (e aqui quando quer dizer aonde) nossa fun&ccedil;&atilde;o será executada. Estamos dentro do WordPress por assim dizer, qualquer print ou echo irá imprimir na página diretamente, ent&atilde;o basta procurar o hook certo e imprimir o que precisamos na se&ccedil;&atilde;o HEAD da página e o hook para isso é &quot;<a href="http://codex.wordpress.org/Hook_Reference/wp_head" target="_blank">wp_head</a>&quot; para as páginas do site e &quot;admin_head&quot; para as páginas da administra&ccedil;&atilde;o. Faríamos ent&atilde;o algo assim:</p>
	<div class="codigo">&#8230;<br />add_action(&quot;wp_head&quot;, &quot;addHeadContents&quot;);</p>
	<p>function addHeadContents() {<br />?&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />@import url(../css/myplug.css);<br />&lt;/style&gt;<br />&lt;script type=&quot;text/javascript&quot;&gt;<br />function myplug() {<br />var mypageRe = /minha_pagina\.php([\?#].+)?$/;<br />&nbsp; &nbsp;if(mypageRe.test(location.href) &amp;&amp; !_recebido)&nbsp;alert(&quot;Benvindo!&quot;);&nbsp;<br />} <br />&lt;/script&gt;<br />&lt;?php<br />} <br />&#8230;</div>
	<p>Simples, né? </p>
	<h4>Internacionalizando seu plugin</h4>
	<p>Isso é necessário se voc&ecirc; deseja compartilhar seu plugin com o resto do planeta e n&atilde;o apenas com os&nbsp;que falam&nbsp;portugu&ecirc;s. O mais correto, de qualquer modo, seria escrever o plugin em ingl&ecirc;s e ent&atilde;o traduzir para o portugu&ecirc;s brasileiro, para que seus clientes possam entender.</p>
	<p>O sistema utilizado é o <a href="http://www.gnu.org/software/gettext/" target="_blank">gettext</a> da <a href="http://www.gnu.org/" target="_blank">GNU</a> e há duas fun&ccedil;&otilde;es que voc&ecirc; deve lembrar, a __() que retorna o texto original (em inl&ecirc;s) traduzido para a linguagem selecionada pelo administrador do sistema e _e() que imprime a tradu&ccedil;&atilde;o diretamente na tela. Mas para os plugins, é preciso criar um text domain (uma palavra-chave que identifique seu plugin), no nosso exemplo, &quot;myplug&quot; - veja adiante. Ent&atilde;o&#8230;</p>
	<div class="codigo">&lt;?php<br />// invés de escrever<br />$action = &quot;Write&quot;; <br />// escreveremos<br />$action = __(&quot;Write&quot;, &quot;myplug&quot;); <br />?&gt;<br />&lt;!&#8211; invés de escrever &#8211;&gt; <br />&lt;p&gt;Define your settings&lt;/P&gt; <br />&lt;!&#8211; escreveremos &#8211;&gt; <br />&lt;p&gt;<br />&lt;?php _e(&quot;Define your settings&quot;, &quot;myplug&quot;); ?&gt;<br />&lt;/P&gt;</div>
	<p>Voc&ecirc; pode desenvolver seu plugin até o final sem se preocupar, apenas onde houver um texto legível, use as fórmulas acima. Mas a coisa ainda n&atilde;o funciona, pois precisamos agora carregar o domínio criado (myplug) e indicando o caminho para o diretório onde estará o arquivo myplug-pr_BR.mo, que criaremos em seguida. Para isso voc&ecirc; precisará de um editor específico para arquivos .POT, .PO e .MO. Eu uso e recomendo o <a href="http://sourceforge.net/projects/poedit/" target="_blank">poEdit</a>, mas n&atilde;o vou me alongar mais sobre ele - veja <a href="http://www.google.com.br/search?num=50&#038;hl=pt-BR&#038;safe=off&#038;rls=GGLJ%2CGGLJ%3A2006-39%2CGGLJ%3Apt-BR&#038;q=po+mo+pot+traduzir&#038;btnG=Pesquisar&#038;meta=lr%3Dlang_pt" target="_blank">aqui</a> ou <a href="http://codex.wordpress.org/User:Skippy/Creating_POT_Files" target="_blank">aqui (em ingl&ecirc;s)</a> .</p>
	<p>Após criar o arquivo POT inicial, basta atualizar que o programa vai ler e mostrar cada texto que foi enviado para as fun&ccedil;&otilde;es __() e _e(). Traduza e salve. Isso irá gerar o arquivo .MO, que deve ter um nome assim:</p>
	<p class="codigo">text-domain_do_pligin-linguagem escolhida.mo</p>
	<p>Como por exemplo: myplug-pt_BR.mo. <br />Agora basta carregar o text-domian criado com a seguinte linha de código:</p>
	<p class="codigo">$dir_name = preg_replace(&quot;/^.+(\\\\|\/)/&quot;, &quot;&quot;, dirname(__FILE__));<br />load_plugin_textdomain(&quot;myplug&quot;, &quot;wp-content/plugins/&quot;.$dir_name); </p>
	<p>Agora tudo deve estar funcionando.</p>
	<p>Acho que isso vai ajudar bastante os que est&atilde;o iniciando com o WP, esse programa fantástico. Boa programa&ccedil;&atilde;o e tenha sempre em mente a nota de rodapé do site do WordPress: CODE IS POETRY! </p>
	<h4>Alguns links interessantes (em ingl&ecirc;s)</h4>
	<ul>
<li><a href="http://codex.wordpress.org/" target="_blank">codex.wordpress.org</a></li>
	<li><a href="http://codex.wordpress.org/Function_Reference" target="_blank">Functions reference</a></li>
	<li><a href="http://codex.wordpress.org/Template_Tags" target="_blank">WordPress Template Tags</a> </li>
	<li><a href="http://codex.wordpress.org/Function_Reference/wpdb_Class" target="_blank">WPDB class reference</a> </li>
	<li><a href="http://codex.wordpress.org/Writing_a_Plugin" target="_blank">Writing a Plugin</a> </li>
	<li><a href="http://codex.wordpress.org/Plugin_API" target="_blank">WordPress Plugin API</a> </li>
	<li><a href="http://codex.wordpress.org/Plugin_API#Actions" target="_blank">WordPress Actions</a> </li>
	<li><a href="http://codex.wordpress.org/Plugin_API#Filters" target="_blank">WordPress Filters</a> </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/08/09/como-construir-um-plugin-para-o-wordpress/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Plugins para WordPress</title>
		<link>http://cauguanabara.blogsome.com/2007/08/05/plugins-para-wordpress/</link>
		<comments>http://cauguanabara.blogsome.com/2007/08/05/plugins-para-wordpress/#comments</comments>
		<pubDate>Mon, 06 Aug 2007 00:07:30 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>PHP</category>
		<guid>http://cauguanabara.blogsome.com/2007/08/05/plugins-para-wordpress/</guid>
		<description><![CDATA[	Desde que comecei a blogar e a ter contato com o WP (menos de um ano) tenho me interessado cada vez mais por esse programa que n&atilde;o é apenas um gerenciador de blogs, mas um gerenciador de conteúdos bastante completo. Também n&atilde;o é para menos, como diz esse texto do Rafael, o WP é um [...]]]></description>
			<content:encoded><![CDATA[	<p>Desde que comecei a blogar e a ter contato com o WP (menos de um ano) tenho me interessado cada vez mais por esse programa que n&atilde;o é apenas um gerenciador de blogs, mas um gerenciador de conteúdos bastante completo. Também n&atilde;o é para menos, como diz <a href="http://www.netlus.com.br/por-que-reinventar-a-roda/" target="_blank">esse texto do Rafael</a>, o WP é um produto da intelig&ecirc;ncia coletiva e fica difícil criar sozinho algo para competir com isso.</p>
<a id="more-35"></a>
<p>Eu tenho um sistema de gerenciamento de conteúdo que chamei de WebEdit (nada original&#8230;) e embora ele ofere&ccedil;a uma ou duas funcionalidades que o WordPress n&atilde;o tem, me rendi e comecei a pensar em vender sites baseados no WP. Mas para fazer isso, precisava de alguns detalhes específicos para sites específicos. Fui buscar plugins para fazer o que eu presisava, mas me surpreendi ao descobrir que dentre os zilh&otilde;es de plugins para WP disponíveis poucos s&atilde;o realmente confiáveis e desses nenhum fazia o que eu queria (a n&atilde;o ser dois que eram comerciais). Aí cheguei &agrave; conclus&atilde;o óbvia que até uma crian&ccedil;a veria: para vender sites baseados em WP é preciso dominar os templates e plugins. </p>
	<p>O que eu precisava me parecia algo simples: usar os arquivos enviados como áreas de download e ter um sisteminha de mala-direta. Comecei analisando o plugin Organizer para resolver minha promeira quest&atilde;o - ele é bem maneiro, mas eu precisava de título e descri&ccedil;&atilde;o para cada arquivo e de um sistema para exibir esses arquivos como uma área de downloads. Acabei fazendo uma coisa que n&atilde;o se deve fazer, modificando os arquivos originais do plugin que n&atilde;o fui eu que fiz&#8230; bem, com isso cheguei a uma vers&atilde;o n&atilde;o oficial do Organizer, o Organizer modified.</p>
	<p>Quanto &agrave; mala-direta, achei alguns para enviar emails aos usuários outros &agrave; venda, bem, já estava no ritmo e resolvi escrever o meu próprio plugin. Por isso é que há tanto tempo n&atilde;o escrevo nada por aqui. Mas aqui estou eu e com um plugin para WP novinho em folha, o WPMailing. Pedi asilo para ele no novo site oficial de plugins do WP, o <a href="http://wordpress.org/extend/" target="_blank">http://wordpress.org/extend</a>, mas vou disponibilizar uma vers&atilde;o dele aqui.</p>
	<p>O que se pode fazer com o WPMailing:</p>
	<ul>
<li>Criar e gerenciar grupos de usuários<br />(os grupos s&atilde;o, na verdade, tags - um mesmo usuário pode estar em vários) </li>
	<li>Enviar e-mails para os usuários por grupo, capacidade, nível ou login</li>
	<li>Enviar e-mails com arquivos em anexo, se necessário </li>
	<li>Usar valores personalizados do usuário que vai receber o e-mail</li>
	<li>Usar valores de uma publica&ccedil;&atilde;o (post ou página) no e-mail</li>
	<li>Receber um relatório sobre o envio após cada e-mail enviado</li>
	<li>Pode-se usar os plugins Xinha4WP ou Dean&#8217;s FCKEditor </li>
</ul>
	<p>Baixe os plugins: </p>
	<ul>
<li><a href="http://cauguanabara.jsbrasil.com/scripts/wpmailing.zip">WPMailing</a> </li>
	<li><a href="http://cauguanabara.jsbrasil.com/scripts/organizer_mod.zip">Organizer modified</a> (baseado no <a href="http://imthi.com/organizer/" target="_blank">Organizer</a>)</li>
</ul>
	<p>Abra&ccedil;o a todos, Cau Guanabara </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/08/05/plugins-para-wordpress/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Já ouviu falar em WysiWiki?</title>
		<link>http://cauguanabara.blogsome.com/2007/06/07/ja-ouviu-falar-em-wysiwiki/</link>
		<comments>http://cauguanabara.blogsome.com/2007/06/07/ja-ouviu-falar-em-wysiwiki/#comments</comments>
		<pubDate>Thu, 07 Jun 2007 17:46:21 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Web 2.0</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2007/06/07/ja-ouviu-falar-em-wysiwiki/</guid>
		<description><![CDATA[	Outro dia escrevi aqui sobre um script para traduzir HTML para WikiFormat e vice-versa. Bem, fiz esse script mas depois de pronto achei que era perda de tempo&#8230; ninguém ia usar aquilo. O fato é que cheguei &agrave; conclus&atilde;o que esse sistema só ia funcionar bem num editor tipo wysiwyg, que alternasse entre a renderiza&ccedil;&atilde;o [...]]]></description>
			<content:encoded><![CDATA[	<p>Outro dia escrevi aqui sobre um script para <a href="http://cauguanabara.blogsome.com/2007/04/28/wiki-format-formatacao-sem-tags/">traduzir HTML para WikiFormat</a> e vice-versa. Bem, fiz esse script mas depois de pronto achei que era perda de tempo&#8230; ninguém ia usar aquilo. O fato é que cheguei &agrave; conclus&atilde;o que esse sistema só ia funcionar bem num editor tipo wysiwyg, que alternasse entre a renderiza&ccedil;&atilde;o HTML e o código wiki em vez do HTML. </p>
<a id="more-34"></a>
<p>Apesar de parecer algo meio ambicioso para um cara sozinho, comecei a montar meu editor. Já possuía duas pe&ccedil;as fundamentais: o script de tradu&ccedil;&atilde;o e um <a href="http://cauguanabara.jsbrasil.com/scripts/toolbar/" target="_blank">script para construir a barra de ferramentas</a>, só me faltava o editor em si. Resolvi tentar e, para meu espanto, um m&ecirc;s depois o editor já existe. Cheio de falhas ainda, mas funcionando. </p>
	<p>Como sabemos , essa é a fase mais chata de qualquer projeto&#8230; aparar arestas é um trabalho de chin&ecirc;s e fica pior quando n&atilde;o entendemos profundamente o tema de trabalho. Eu já tinha feito alguns plugins para o editor Xinha, mas n&atilde;o entrei na parte mais hard, onde acontece a edi&ccedil;&atilde;o em si. O controle de textRanges e selections é algo inteiramente novo para mim. Bem, já n&atilde;o inteiramente&#8230;</p>
	<p>Construí um <a href="http://cauguanabara.jsbrasil.com/scripts/wysiwiki/demo/" target="_blank">site</a> e disponibilizei o WikiEditor para testes, tentando fazer outra coisa que nunca havia feito, apesar de ter desenvolvido inúmeros projetos durante os últimos anos: tratar o projeto como deve ser, com uma base na web, um changelog, controle de vers&atilde;o (nunca tinha utilizado&#8230;), etc. Tentei achar um host que oferecesse o Trac grátis, mas ainda nada. Tentei o sourceForge, mas meu ingr&ecirc;is n&atilde;o deu&#8230; </p>
	<p>O WikiEditor é ainda um neném, mas me parece que tem algum futuro possível. D&ecirc; uma olhada, fa&ccedil;a uns testes e, se quiser, comente, entre em contato.</p>
	<p>O sistema está disponível aqui: <a href="http://cauguanabara.jsbrasil.com/scripts/wysiwiki/demo/" target="_blank">http://cauguanabara.jsbrasil.com/scripts/wysiwiki/demo/</a></p>
	<p>ou se preferir navegar pelo código: <a href="http://cauguanabara.jsbrasil.com/scripts/wysiwiki/" target="_blank">http://cauguanabara.jsbrasil.com/scripts/wysiwiki/</a></p>
	<p>Abra&ccedil;o, Cau Guanabara.</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/06/07/ja-ouviu-falar-em-wysiwiki/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Drag e drop em Javascript</title>
		<link>http://cauguanabara.blogsome.com/2007/06/03/drag-e-drop-em-javascript/</link>
		<comments>http://cauguanabara.blogsome.com/2007/06/03/drag-e-drop-em-javascript/#comments</comments>
		<pubDate>Sun, 03 Jun 2007 03:01:50 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Tutoriais</category>
		<guid>http://cauguanabara.blogsome.com/2007/06/03/drag-e-drop-em-javascript/</guid>
		<description><![CDATA[	Poder arrastar e soltar elementos HTML na página é quase sempre um grande ganho em interatividade e design, além de, em muitos casos, permitir a troca das inc&ocirc;modas janelas popup por divs flutuantes, que podem ser movidos pelo usuário.
	Vou mostrar aqui uma forma bastante simples e funcional de fazer isso em Javascript, com tr&ecirc;s fun&ccedil;&otilde;es [...]]]></description>
			<content:encoded><![CDATA[	<p>Poder arrastar e soltar elementos HTML na página é quase sempre um grande ganho em interatividade e design, além de, em muitos casos, permitir a troca das inc&ocirc;modas janelas popup por divs flutuantes, que podem ser movidos pelo usuário.</p>
	<p>Vou mostrar aqui uma forma bastante simples e funcional de fazer isso em Javascript, com tr&ecirc;s fun&ccedil;&otilde;es apenas, mas antes de mostrar o código, vou explicar a idéia da coisa e desmistificar logo o &quot;complicadíssimo drag and drop&quot;, antes que voc&ecirc; se decepcione com o tamanho do código&#8230;</p>
<a id="more-33"></a>
<p>Bem, nossas fun&ccedil;&otilde;es v&atilde;o explorar tr&ecirc;s eventos: onmousedown, onmousemove e onmouseup. Essa é a anatomia do &quot;pegar, arrastar e soltar&quot;. Mas haverá certas condi&ccedil;&otilde;es para um elemento ser arrastável, pois o script precisa saber se o elemento em foco no onmousedown deve ou n&atilde;o seguir o ponteiro do mouse se ele andar (onmousemove) antes do onmouseup. Para isso, estabelecemos um nome de classe (CSS) padr&atilde;o que transforma o elemento num elemento arrastável e esse nome é &quot;drag&quot;. A classe drag pode ou n&atilde;o existir. Aqui usamos ela para definir o cursor como &quot;move&quot;. Além disso, é preciso definir uma variável com o ID do elemento a ser arrastado, para o caso (frequente) de arrastar um elemento a partir de outro, como uma janela é arrastada a partir de sua borda superior.</p>
	<p>Vamos come&ccedil;ar declarando algumas variáveis necessárias e definindo os comportamentos relativos ao mouse na fun&ccedil;&atilde;o initDragDrop: </p>
	<div class="codigo">function initDragDrop() {<br />__dragX = 0; // cursor X <br />__dragY = 0; // cursor Y <br />__dragId = &quot;&quot;; // ID do el. a ser movido <br />__dragging = false; // true se há um el. sendo movido <br />document.body.onmousedown = __dragDown;<br />document.body.onmousemove = __dragMove;<br />document.body.onmouseup = function() { __dragging = false; };<br />} </div>
	<p>Repare que as variáveis foram declaradas sem a instru&ccedil;&atilde;o var, pois assim elas ser&atilde;o globais e estar&atilde;o disponíveis para outras fun&ccedil;&otilde;es. <br />Sempre é melhor usar uma rotina tipo addEvent para definir os eventos. Da forma que está feito aqui, se houvesse algum comportamento definido para esses eventos, eles seriam substituídos pelos nossos.<br />Como trabalhamos com o elemento body, é preciso esperar o carregamento da página, portanto initDragDrop deve ser chamada no onload da página. </p>
	<p>Desde a chamada da fun&ccedil;&atilde;o acima, __dragMove passa a monitorar a variável __dragging, que só é true desde o momento em que clicamos em um elemento com a classe &quot;drag&quot; setada (__dragDown) até soltarmos o bot&atilde;o do mouse (fun&ccedil;&atilde;o an&ocirc;nima definida para o evento onmouseup). Se __dragging é true, ent&atilde;o passa a definir a posi&ccedil;&atilde;o do cursor para o elemento __dragEl, preservando a posi&ccedil;&atilde;o do mouse sobre o elemento.</p>
	<div class="codigo">function __dragMove(e) {<br />if(typeof __dragging == &quot;undefined&quot; || !__dragging) return;<br />e = e ? e : window.event;<br />__dragEl.style.left = (e.clientX - __dragX)+&quot;px&quot;;<br />__dragEl.style.top = (e.clientY - __dragY)+&quot;px&quot;;<br />}; </div>
	<p>Para __dragDown definir __dragging como true, dois testes devem ser feitos. O elemento clicado deve ter a classe drag e __dragId deve estar definido com um ID válido. Se o ID é válido, __dragEl passa a apontar para o elemento com esse ID. </p>
	<div class="codigo">function __dragDown(e) {<br />e = e ? e : window.event;<br />__dragEl = document.getElementById(__dragId) || null;<br />var _target = document.all ? e.srcElement : e.target;<br />if(!__dragEl || !(/drag/.test(_target.className))) return;<br />__dragX = e.clientX - __dragEl.offsetLeft;<br />__dragY = e.clientY - __dragEl.offsetTop;<br />__dragging = true;<br />};</div>
	<p>Ent&atilde;o, além da classe drag, colocaremos no elemento a ser arrastado (ou naquele que será a &quot;al&ccedil;a de arraste&quot;) um comportamento no evento onmouseover definindo a variável __dragId. Veja o HTML:</p>
	<div class="codigo">&lt;script type=&quot;text/javascript&quot;&gt;<br />// tudo que foi mostrado acima &#8230;<br />&lt;/script&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />#Layer1 {<br />position:absolute;<br />left:20px;<br />top:110px;<br />width:100px;<br />height:100px;<br />z-index:1;<br />background-color: #0099CC;<br />}<br />#Layer2 {<br />position:absolute;<br />left:20px;<br />top:220px;<br />width:90px;<br />height:90px;<br />z-index:2;<br />background-color: #66CC99;<br />padding:5px;<br />}<br />#Layer3 {<br />width:50px;<br />background-color:#FFCC66;<br />padding:5px;<br />font-size:10px;<br />text-align:center;<br />}<br />.drag { cursor:move; }<br />&lt;/style&gt;<br />&lt;/head&gt;<br />&lt;body onload=&quot;initDragDrop()&quot;&gt;<br />&lt;div class=&quot;drag&quot; id=&quot;Layer1&quot; onmouseover=&quot;__dragId = &#8216;Layer1&#8242;&quot;&gt;&lt;/div&gt;<br />&lt;div id=&quot;Layer2&quot;&gt;&lt;div id=&quot;Layer3&quot; class=&quot;drag&quot; onmouseover=&quot;__dragId = &#8216;Layer2&#8242;&quot;&gt;move&lt;/div&gt;&lt;/div&gt;<br />&lt;p&gt;Drag e drop - exemplo&lt;/p&gt;<br />&lt;/body&gt;<br />&lt;/html&gt; </div>
	<p>Note que o primeiro div no mouseover aponta para si mesmo, enquanto o segundo será movido a partir do div com ID &quot;Layer3&quot;. </p>
	<p>Simples demais, n&atilde;o? <a href="http://cauguanabara.jsbrasil.com/scripts/testdrag.html" target="_blank">Veja aqui uma página de testes</a>. </p>
	<p>Abra&ccedil;o, Cau Guanabara.</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/06/03/drag-e-drop-em-javascript/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Duas questões sobre javascript e CSS</title>
		<link>http://cauguanabara.blogsome.com/2007/04/30/duas-questoes-sobre-javascript-e-css/</link>
		<comments>http://cauguanabara.blogsome.com/2007/04/30/duas-questoes-sobre-javascript-e-css/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 23:36:03 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Tutoriais</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2007/04/30/duas-questoes-sobre-javascript-e-css/</guid>
		<description><![CDATA[	Acessar o CSS com javascript é algo que fazemos com frequ&ecirc;ncia e que n&atilde;o envolve grandes mistérios, mas há certas coisas que raramente precisamos fazer e acabamos esquecendo até que aquilo é possível. Desculpem, estou escrevendo na 3&ordf; pessoa mas na verdade estou falando apenas por mim&#8230;&nbsp;Nesse texto vou responder &agrave;s minhas próprias dúvidas, tentando [...]]]></description>
			<content:encoded><![CDATA[	<p>Acessar o CSS com javascript é algo que fazemos com frequ&ecirc;ncia e que n&atilde;o envolve grandes mistérios, mas há certas coisas que raramente precisamos fazer e acabamos esquecendo até que aquilo é possível. Desculpem, estou escrevendo na 3&ordf; pessoa mas na verdade estou falando apenas por mim&#8230;&nbsp;Nesse texto vou responder &agrave;s minhas próprias dúvidas, tentando exorcisar o comodismo, mas também por acreditar que outros podem ganhar com as respostas que encontrei.</p>
	<p>O CSS declarado inline, dentro da própria TAG, está facilmente acessível ao javascript, tanto para ler quanto para modificar. Podemos também ler e modificar com facilidade o valor da propriedade className das TAGs, alternando entre grupos de regras css pelos nomes das classes correspondentes. Mas, até pouco tempo atrás, havia para mim dois pontos incógnitos, duas perguntas que me perseguiam: &quot;como modificar regras dentro de uma classe?&quot; e &quot;como obter as regras que incidem em determinado elemento por heran&ccedil;a?&quot;. Bem, sou um autodidata e é essa curiosidade que me faz andar para frente, portanto, pesquisei e, como sempre, descobri que é simples. Aliás, essa é uma li&ccedil;&atilde;o que posso dar aos iniciantes que s&atilde;o autodidatas como eu: difícil é aquilo que ainda n&atilde;o aprendemos a fazer, o resto é fácil. N&atilde;o se deixe intimidar. </p>
<a id="more-32"></a>
<p>Como essas quest&otilde;es me incomodaram por bastante tempo, achei que valia escrever esse tutorial. Vamos lá, vou responder a elas da melhor maneira que conseguir.</p>
<span class="negrito">Como modificar regras dentro de uma classe CSS?</span>
<p>Bem, naturalmente o javascript n&atilde;o pode modificar o que está escrito (hard-coded) no arquivo, mas entre a leitura das classes CSS declaradas na página e a renderiza&ccedil;&atilde;o dos elementos a partir delas, o navegador faz mais do que sonha a nossa v&atilde; filosofia&#8230; e o fato é que o documento é rederizado com base em um objeto que contém as regras CSS lidas e n&atilde;o no texto-base do documento exibido. E este objeto (document.styleSheets) pode ser lido e modificado! Sua anatomia é complexa e prá variar (mesmo nesses tempos de padroniza&ccedil;&atilde;o), muda de um navegador para outro. Mais correto seria dizer &quot;de um navegador para os outros&quot;&#8230; mas deixa prá lá. Vamos tentar concentrar em áreas acessíveis aos dois (Mozilla e IE). </p>
	<p>A primeira propriedade que precisamos entender é o length, que está disponível em todos os browsers e faz refer&ecirc;ncia aos elementos de estilo existentes no ducumento. Estou falando das duas TAGs que s&atilde;o usadas para esse fim: &lt;STYLE&gt; e &lt;LINK&gt;. No documento que voc&ecirc; está vendo há o seguinte CSS: </p>
	<div class="codigo">&lt;!&#8211; o arquivo test.css contém 3 regras definidas<br />&nbsp;&nbsp;&nbsp;&nbsp; para as TAGs body, h1 e h2 &#8211;&gt; <br />&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;test.css&quot; /&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />.codigo {<br />padding:8px;<br />width: 90%;<br />height:auto;<br />font-family:&quot;Courier New&quot;, &quot;Lucida Console&quot;;<br />font-size: 1.1em;<br />background-color: #FAFAFA; <br />height: auto;<br />border:3px dashed #CCC;<br />margin:20px 10px 20px 10px;<br />overflow:auto;<br />}<br />&lt;/style&gt;</div>
	<p>Bem, temos um elemento STYLE e um elemento LINK, portanto a propriedade document.styleSheets.length será igual a 2. A eventual presen&ccedil;a de um @import url(&#8230;) dentro de um elemento STYLE n&atilde;o iria interferir na propriedade length, mas numa outra propriedade, da qual <strong>n&atilde;o</strong> trataremos aqui: imports. </p>
	<p>Os elementos do objeto s&atilde;o id&ecirc;nticos para regras adquiridas de arquivos CSS externos ou de elementos STYLE declarados na própria página e a forma de reconhec&ecirc;-los é pela propriedade href, que n&atilde;o existe em TAGs STYLE. A propriedade href do objeto document.styleSheets[_INDICE_], por outro lado, existirá em todos os elementos, mas para as TAGs STYLE o IE devolverá uma string vazia e o Mozilla, a URL do arquivo atual (&#8230;?). <br />Outra forma é usar o atributo owningElement (IE) / ownerNode (Moz), que aponta para uma refer&ecirc;ncia ao nódulo DOM relativo &agrave; TAG em quest&atilde;o. Daí basta usar o atributo tagName. Veja:</p>
	<div class="codigo">var isIE = (/\bmsie\b/i.test(navigator.userAgent)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; document.all)); // é Internet Explorer?</p>
	<p>// propriedades que mudam de nome do IE para o Mozilla&#8230; <br />var rulesName = isIE ? &#8216;rules&#8217; : &#8216;cssRules&#8217;;<br />var domNode = isIE ? &#8216;owningElement&#8217; : &#8216;ownerNode&#8217;;</p>
	<p>function showCSS() {<br />var stl = document.styleSheets;<br />&nbsp; // para cada elemento de estilo na página<br />&nbsp; for(var i = 0; i &lt; stl.length; i++) { <br />&nbsp; alert(&#8217;Elemento &#8216;+i+&#8217;: &#8216;+stl[i][domNode].tagName+<br />&nbsp; &nbsp; &nbsp; &nbsp; &#8216;\nRegras: &#8216;+stl[i][rulesName].length);<br />&nbsp; &nbsp; // para cada regra desse elemento<br />&nbsp; &nbsp; for(var g = 0; g &lt; stl[i][rulesName].length; g++) { <br />&nbsp; &nbsp; // o seletor<br />&nbsp; &nbsp; var selector = stl[i][rulesName][g].selectorText; <br />&nbsp; &nbsp; // o cssText<br />&nbsp; &nbsp; var csstext = stl[i][rulesName][g].style.cssText; <br />&nbsp; &nbsp; // os replaces apenas colocam quebras de linha <br />&nbsp; &nbsp; // e garantem um ponto-e-vírgula no final<br />&nbsp; &nbsp; csstext = csstext.replace(/;?\s*$/,&#8217;;'); <br />&nbsp; &nbsp; csstext = csstext.replace(/;\s*/g,&#8217;;\n&#8217;); <br />&nbsp; &nbsp; alert(selector+&#8217; {\n&#8217;+csstext+&#8217;}');<br />&nbsp; &nbsp; }<br />&nbsp; }<br />}</div>
	<p>Dessa forma, já pegamos os valores que queríamos e já podemos modificar as classes e regras em geral pelo atributo cssText (a declara&ccedil;&atilde;o textual de <strong>todas</strong> as propriedades contidas em determinada regra). A senten&ccedil;a abaixo&#8230; </p>
	<div class="codigo">document.styleSheets[0][rulesName][0].style.cssText = &#8216;font-family:verdana; font-size:10px;&#8217;; </div>
seria aceita e modificaria o tipo de fonte da regra BODY. Mas podemos modificar cada propriedade separadamente, como fazemos com o objeto style das tags. Veja:
<p>&nbsp;</p>
	<div class="codigo">// isso também funcionaria&#8230; <br />var obj = document.styleSheets[0][rulesName][0]; <br />obj.style.backgroundColor = &#8216;#000&#8242;; <br />obj.style.color = &#8216;#FFF&#8217;;</div>
	<p>E com isso repondemos &agrave; nossa primeira quest&atilde;o, certo? <br />Veja <a href="http://cauguanabara.jsbrasil.com/scripts/cssapi/" target="_blank">aqui um script mais completo</a> para manipular os estilos na página. </p>
	<p>Mas ainda restou a outra pergunta&#8230; </p>
<span class="negrito">Como obter as regras CSS herdadas por determinado elemento?</span>
<p>A real dificuldade aqui é que n&atilde;o basta ler os estilos inline e as classes CSS declarados na TAG, pois um elemento pode, além disso, herdar do seu elemento-pai ou de um ancestral qualquer, uma grande quantidade de regras que, apesar de n&atilde;o estarem explicitamente declaradas na TAG, incidem sobre a renderiza&ccedil;&atilde;o visual do elemento. </p>
	<p>Bem, essa resposta é mais simples mas, mais uma vez, formas diferentes para navegadores diferentes&#8230; O IE disponibiliza uma propriedade no nódulo DOM dos elementos, a currentStyle que engloba todos os estilos a incidir sobre o elemento. Já no Mozilla precisamos usar um método do objeto document.defaultView, o getComputedStyle(). Bem, para facilitar vamos construir uma fun&ccedil;&atilde;ozinha crossbrowser, a getCurrentStyle(). Veja: </p>
	<div class="codigo">function getCurrentStyle(elem) { <br />// a express&atilde;o &quot;(VALOR || false)&quot; tem o efeito <br />// de um try/catch. Se VALOR n&atilde;o existir, <br />// retorna false ao invés de dar erro. <br />&nbsp; if(elem.currentStyle || false) <br />&nbsp; &nbsp; return elem.currentStyle; <br />&nbsp; else <br />&nbsp; &nbsp; return (document.defaultView.getComputedStyle(elem, null) || false); <br />}</div>
	<p>O elemento acima é um PRE apenas com a classe codigo definida e o id &quot;codetest&quot;. Na classe codigo n&atilde;o há defini&ccedil;&atilde;o para a cor da fonte, mas ela é exibida com a cor &quot;#333&quot; por heran&ccedil;a da da classe definida para a TAG BODY. Veja na prática: </p>
	<div class="codigo">alert(getCurrentStyle(document.getElementById(&#8217;codetest&#8217;)).color);</div>
	<p>O objeto de retorno da fun&ccedil;&atilde;o acima pode ser enorme, pois inclui todas as propriedades específicas de cada navegador e, no caso do Mozilla, até fun&ccedil;&otilde;es. Por isso nosso exemplo foi direcionado a uma propriedade escolhida (color) e recomendo que voc&ecirc; fa&ccedil;a da mesma forma, para evitar dores de cabe&ccedil;a. Sen&atilde;o, teste o valor de cada item e ignore strings vazias e fun&ccedil;&otilde;es&#8230; isso vai melhorar um pouco a confus&atilde;o. </p>
	<p><strong>Aten&ccedil;&atilde;o!</strong><br />Este tutorial leva em considera&ccedil;&atilde;o apenas os navegadores da família Mozilla e o Internet Explorer. </p>
	<p>Escrevi este texto em casa, sem pensar em publicar aqui no blog, por isso fui mesclando o texto com javascript para ter exemplos <em>alive,</em>&nbsp;mas as restri&ccedil;&otilde;es do wordpress n&atilde;o permitem javascript. Além disso, os estilos declarados eram específicos para os testes pensados, enfim&#8230;</p>
	<p>O resultado disso tudo é que a &quot;vers&atilde;o completa desse post&quot; está em uma página separada. Aqui temos apenas uma cópia sem correspond&ecirc;ncia com o JS ou CSS dessa página.</p>
	<p><strong><a title="Abrir em nova janela" href="http://cauguanabara.jsbrasil.com/scripts/cssjs/" target="_blank">Clique aqui para ler o texto com exemplos</a></strong></p>
	<p>Abra&ccedil;o a todos, Cau Guanabara</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/04/30/duas-questoes-sobre-javascript-e-css/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Wiki-format - formatação sem TAGs</title>
		<link>http://cauguanabara.blogsome.com/2007/04/28/wiki-format-formatacao-sem-tags/</link>
		<comments>http://cauguanabara.blogsome.com/2007/04/28/wiki-format-formatacao-sem-tags/#comments</comments>
		<pubDate>Sat, 28 Apr 2007 15:43:19 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>Web 2.0</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2007/04/28/wiki-format-formatacao-sem-tags/</guid>
		<description><![CDATA[	
Os termos wiki (pronunciado &quot;wiquie&quot; ou &quot;uikie&quot; no Alfabeto fonético internacional) e WikiWiki s&atilde;o utilizados para identificar um tipo específico de colec&ccedil;&atilde;o de documentos em hipertexto ou o software colaborativo usado para criá-lo. [veja mais&#8230; ]

O texo acima foi retirado da wikipedia e diz, em outras palavras, que o termo &quot;wiki&quot; é utilizado para definir [...]]]></description>
			<content:encoded><![CDATA[	<p><em><br />
<blockquote><em>Os termos wiki (pronunciado &quot;wiquie&quot; ou &quot;uikie&quot; no Alfabeto fonético internacional) e WikiWiki s&atilde;o utilizados para identificar um tipo específico de colec&ccedil;&atilde;o de documentos em hipertexto ou o software colaborativo usado para criá-lo. [<a href="http://pt.wikipedia.org/wiki/Wiki" target="_blank">veja mais&#8230; </a>]</em></blockquote>
</em>
<p>O texo acima foi retirado da wikipedia e diz, em outras palavras, que o termo &quot;wiki&quot; é utilizado para definir websites colaborativos como a própria wikipedia (wikipedia, livremente interpretado, significa &quot;enciclopédia colaborativa&quot;) ou os aplicativos usados para gerar esses sites. </p>
<a id="more-30"></a>
<p>Definido o que é &quot;wiki&quot; vamos ao &quot;<a href="http://en.wikipedia.org/wiki/Wiki#Pages_and_editing" target="_blank">wiki-format</a>&quot; ou &quot;formato wiki&quot;. Juntamente com essa idéia de <em>colaborativizar</em> a internet, surgiu um problema: como gerar o HTML necessário para ser exibido quando um usuário leigo quiser criar ou editar algum conteúdo? Os editores de HTML online s&atilde;o coisa nova e poucos funcionam a contento&#8230; Surgiu a idéia de gerar a formata&ccedil;&atilde;o HTML a partir de certas combina&ccedil;&otilde;es de caracteres comuns como apóstrofos, acentos, vírgulas, etc. </p>
	<p>Existe uma gama enorme de aplicativos (web-based e de desktop) para gerar e manter conteúdos participativos na internet (<a href="http://en.wikipedia.org/wiki/List_of_wiki_software" target="_blank">veja aqui alguns</a>) e a quase totalidade deles trabalha com algum tipo de formata&ccedil;&atilde;o wiki, embora os sinais escolhidos variem um pouco - mas poucos ou nenhum em javascript. Descobri por que precisei de um tradutor wiki para usar em um sistema de comentários que é parte de um outro projeto&#8230; bem, n&atilde;o importa. O fato é que n&atilde;o achei nada em javascript que pudesse utilizar, ent&atilde;o resolvi escrever o meu próprio <em>wiki&lt;=&gt;HTML translator</em>. Para isso tive primeiro que pensar num vocabulário, nos símbolos que representariam cada tag e que tags seriam permitidas. Acabei me baseando naquele que conhecia um pouco melhor, o <a href="http://trac.edgewall.org/wiki/WikiFormatting" target="_blank">sistema usado</a> no projeto <a href="http://trac.edgewall.org/" target="_blank">Trac</a>, um gerenciador de projetos de software, aliás muito maneiro. </p>
	<p>O sistema que desenvolvi tem recursos limitados em rela&ccedil;&atilde;o ao wiki format do Trac citado acima, mas é bastante funcional e, por ser em javascript, permite editar conteúdos no próprio navegador, vizualizar e modificar quantas vezes quiser antes de enviar ao servidor.</p>
	<p>As raz&otilde;es para adotar o wiki format s&atilde;o muitas:</p>
	<ul>
<li>A inser&ccedil;&atilde;o de tags na página diretamente pelo visitante é um risco e deve ser evitado. Na medida em as tags inseridas s&atilde;o geradas automaticamente, esse risco desaparece. </li>
	<li>O risco de um desastre estético na sua página reduz consideravelmente.</li>
	<li>O wiki format, ao contrário dos editores WYSIWYG, for&ccedil;a o usuário a criar um conteúdo sem&acirc;ntico. O resultado pode ser um pouco mais pobre, mas estará 100% dentros dos padr&otilde;es e com uma constru&ccedil;&atilde;o semanticamente correta. </li>
	<li>O usuário leigo pode aprender alguns símbolos simples bem mais facilmente do que compreender o HTML e seu funcionamento a ponto de usá-lo.</li>
	<li>Os editores de HTML online ainda deixam muito a desejar&#8230; </li>
</ul>
	<p>O wikitext.js também inclui um sisteminha bem legal para codificar a resposta de wiki2html() em ASCII e decodificar o ASCII na resposta de html2wiki(), se desejar. Além disso, há a op&ccedil;&atilde;o de usar CSS para exibir o resultado de forma mais estética. Fiquei pensando em como fazer isso e achei que a forma mais fácil era simplesmente colocar o resultado HTML dentro de um div com um id definido (como &quot;wiki&quot;), dessa forma podemos formatar, por exemplo, todos os cabe&ccedil;alhos criados (h1 a h4) com classes como as mostradas a seguir. </p>
	<div class="codigo">.wiki h1 { font-family:verdana; font-size:2.1em; }<br />.wiki h2 { font-family:verdana; font-size:1.8em; }<br />.wiki h3 { font-family:verdana; font-size:1.5em; }<br />.wiki h4 { font-family:verdana; font-size:1.2em; }</div>
	<p>&nbsp;</p>
<a href="http://cauguanabara.jsbrasil.com/scripts/wikiformat/" target="_blank">Baixe aqui o script e veja um glossário dos símbolos adotados</a>.
<p>Veja aqui um aplicativo muito legal do Aurélio, <em><strong>o cara</strong></em> das express&otilde;es regulares: <a href="http://txt2tags.sourceforge.net/pt/" target="_blank">http://txt2tags.sourceforge.net/pt/</a>. Este é um aplicativo em Python para gerar vários formatos a partir de textos <em>wiki-formatados</em>.</p>
	<p>Abra&ccedil;os a todos, Cau Guanabara </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/04/28/wiki-format-formatacao-sem-tags/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Formas de integrar PHP e Javascript</title>
		<link>http://cauguanabara.blogsome.com/2007/04/14/formas-de-integrar-php-e-javascript/</link>
		<comments>http://cauguanabara.blogsome.com/2007/04/14/formas-de-integrar-php-e-javascript/#comments</comments>
		<pubDate>Sat, 14 Apr 2007 16:11:40 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>PHP</category>
	<category>Tutoriais</category>
		<guid>http://cauguanabara.blogsome.com/2007/04/14/formas-de-integrar-php-e-javascript/</guid>
		<description><![CDATA[	Diversas vezes respondi dúvidas sobre como integrar essas duas linguagens nos fóruns da rede e é um tema que me interessa bastante, pois hoje gosto mesmo é de programar em JS, mas n&atilde;o dá prá fugir de certas funcionalidades no servidor, como consultar bancos de dados, gravar e ler arquivos, etc. 
	Antes de tudo, lembro [...]]]></description>
			<content:encoded><![CDATA[	<p>Diversas vezes respondi dúvidas sobre como integrar essas duas linguagens nos fóruns da rede e é um tema que me interessa bastante, pois hoje gosto mesmo é de programar em JS, mas n&atilde;o dá prá fugir de certas funcionalidades no servidor, como consultar bancos de dados, gravar e ler arquivos, etc. </p>
	<p>Antes de tudo, lembro que já escrevi um <a href="http://cauguanabara.blogsome.com/2007/02/28/mesclar-php-e-html-print-echo-e-outras/">post sobre como mesclar PHP com HTML</a> que voc&ecirc; deveria ler antes de come&ccedil;ar.</p>
<a id="more-29"></a>
<p>A primeira coisa é lembrar que estamos falando de níveis diferentes. O PHP é interpretado no servidor e o JS no navegador. Ou seja, quando o javascript for executado, o PHP já terá cumprido o seu papel. Veja isso: </p>
	<div class="codigo">se vc escrever isso no seu documento &#8230;<br />&lt;script type=&#8217;text/javascript&#8217;&gt;<br />function gethost() {<br />return &quot;http://&lt;?=getenv(&#8217;HTTP_HOST&#8217;)?&gt;/&quot;;<br />}<br />&lt;/script&gt;</p>
	<p>&#8230;ao pedir o fonte, verá isso (supondo que estamos em www.sample.com): <br />&lt;script type=&#8217;text/javascript&#8217;&gt;<br />function gethost() {<br />return &quot;http://www.sample.com/&quot;;<br />}<br />&lt;/script&gt;</div>
	<p>E é assim que o navegador vai fazer - quando o JS for interpretado, o PHP já n&atilde;o existirá no documento, restando apenas o resultado do seu processamento. </p>
Com o PHP podemos modificar o texto do documento <strong>antes</strong> que ele seja enviado ao browser. Já o código Javascript só passa a existir funcionalmente <strong>depois</strong> que o browser interpretar o documento enviado.
<p>&nbsp;</p>
	<p class="negrito">Imprimindo Javascript com PHP </p>
	<p>Essa é a forma mais usada e acabamos de ver um exemplo dela no código mostrado acima. Basta escrever o código JS com as fun&ccedil;&otilde;es de impress&atilde;o do PHP. Mas existe um formato que tem se popularizado bastante ultimamente e que facilita enormemente esse trabalho, o <a href="http://www.json.org/" target="_blank">JSON</a> (<strong>J</strong>ava<strong>S</strong>cript <strong>O</strong>bject <strong>N</strong>otation), com <a href="http://gggeek.altervista.org/sw/article_20061113.html" target="_blank">várias bibliotecas</a> prontas para baixar. <a href="http://cauguanabara.jsbrasil.com/scripts/show.php?file=json.php" target="_blank">Aqui tem um script meu</a> (muito simples, mas bem funcional) para traduzir PHP &lt;-&gt; JSON. </p>
	<p class="negrito">Resumidamente, o JSON é o seguinte&#8230;</p>
	<div class="codigo">// sabemos que o JS possui uma sintaxe reduzida para<br />// cria&ccedil;&atilde;o de arrays e objetos, assim: <br />var arr = new Array();<br />// é exatamente o mesmo que<br />var arr = [];<br />// e que<br />var obj = new Object(); <br />// é exatamente o mesmo que<br />var obj = {}; <br />// ou<br />var arr1 = new Array(&quot;a&quot;, 123); <br />// é exatamente o mesmo que<br />var arr1 = [&quot;a&quot;, 123];<br />// e que<br />var obj = new Object(); <br />obj.prop1 = &quot;a&quot;;<br />obj.prop2 = 123; <br />// é exatamente o mesmo que<br />var obj = {&quot;prop1&quot;: &quot;a&quot;, &quot;prop2&quot;: 123}; </div>
	<p>Entendido isso, digamos que o JSON é simplesmente escrever arrays e objetos Javascript na sintaxe reduzida, mas trabalhar com essa constru&ccedil;&atilde;o na forma de string. Isso é utilizado para transporte de dados, num formato leve e muito prático - principalmente para a finalidade que daremos a ele nesse caso. </p>
	<div class="codigo">// independente da biblioteca escolhida&#8230;<br />$arr = array(&quot;a&quot;, 123);<br />$arr2 = array(&quot;prop1&quot; =&gt; &quot;a&quot;, &quot;prop2&quot; =&gt; 123); <br />// $arr traduzida para o JSON seria uma string assim <br />&quot;[&#8217;a',123]&quot; <br />// $arr2 traduzida para o JSON seria uma string assim <br />&quot;{&#8217;prop1&#8242;: &#8216;a&#8217;, &#8216;prop2&#8242;: 123}&quot;</div>
	<p>Vamos ent&atilde;o abstrair (&#8230;) uma fun&ccedil;&atilde;o tojson(), que representará a passagem de uma variável pela library escolhida, ok? </p>
	<div class="codigo">&lt;?php<br />$userinfo = array(&#8217;name&#8217; =&gt; &#8216;fulano&#8217;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8216;email&#8217; =&gt; &#8216;user@server&#8217;); <br />$uinfjson = tojson($userinfo); // traduzida para JSON<br />?&gt; <br />&#8230;<br />&lt;script type=&quot;text/javascript&quot;&gt; <br />var userinfo = &lt;?=$uinfjson?&gt;;<br />&lt;/script&gt; </div>
	<p>O resultado do exemplo acima, como será lido pelo browser:</p>
	<div class="codigo">&lt;script type=&quot;text/javascript&quot;&gt; <br />var userinfo = {&#8217;name&#8217;:'fulano&#8217;,'email&#8217;:'user@server&#8217;};<br />&lt;/script&gt; </div>
	<p>Avariável userinfo é agora um object JS contendo os valores enviados pelo PHP. Como o formato JSON é baseado no (id&ecirc;ntico ao) formato da sintaxe reduzida do Javascript, n&atilde;o há nada mais a fazer, basta imprimir como veio - isso será um javascript válido. </p>
	<p class="negrito">Pontos de interse&ccedil;&atilde;o entre PHP e JS</p>
	<p>Apesar da diferen&ccedil;a de níveis de execu&ccedil;&atilde;o, como já foi dito, há dois pontos que est&atilde;o acessíveis tanto para o PHP quanto para o Javascript e que podem muito bem ser usados como forma de comunica&ccedil;&atilde;o entre os dois. </p>
	<p><strong>O primeiro</strong> de que falarei é a QUERY STRING na URL do documento em quest&atilde;o. Para o PHP ela está disponível através da superglobal $_GET (ou $_REQUEST ou $HTTP_GET_VARS) e para o Javascript na URL, que pode ser conseguida em location.href. A diferen&ccedil;a é que para o PHP as variáveis já vem tratadas, mas o Javascript só tem acesso &agrave; query string bruta, mas há meios de contornar isso. Veja <a href="http://cauguanabara.blogsome.com/2007/02/14/receber-dados-de-formulario-com-javascript/">aqui um post</a> em que mostro como pegar essas variáveis com Javascript. </p>
	<p>Isso significa que, se n&atilde;o carregarmos outra página, as variáveis GET que estiverem disponíveis no PHP também estar&atilde;o para o Javascript depois de carregada a página no browser. Mas também poderíamos fazer algo assim:</p>
	<div class="codigo">$tosend = peguealgoimportante();<br />header(&#8217;Location: arq_do_js.html?algo=&#8217;.$tosend);<br />exit; </div>
	<p>A variável algo com o valor retornado pela fun&ccedil;&atilde;o PHP peguealgoimportante() poderá ser lida pelo Javascript na página arq_do_js.html.</p>
	<p><strong>O segundo</strong> ponto s&atilde;o os COOKIES. S&atilde;o os mesmos para o PHP e o JS. O PHP oferece fun&ccedil;&otilde;es nativas para manipular cookies mas, prá variar, o JS n&atilde;o. <a href="http://cauguanabara.jsbrasil.com/scripts/cookie.js">Veja aqui algumas fun&ccedil;&otilde;es</a> para manipular cookies em Javascript. </p>
	<p>Podemos setar cookies com o PHP (setcookie() e setrawcookie()) e resgatá-los no navegador com o JS. Ou setar com Javascript e chamar um PHP, que poderá ler os cookies e trabalhar com eles, através da superglobal $_COOKIE (ou $_REQUEST). </p>
	<p class="negrito">Uma outra maneira&#8230; </p>
	<p>O tipo de saída padr&atilde;o do PHP é &quot;text/html&quot;, mas podemos imprimir outros tipos de conteúdos, bastando setar o Content-type, com a fun&ccedil;&atilde;o header. Isso significa que podemos gerar um conteúdo Javascript a partir de um arquivo PHP. É inusitado e extremamente útil.</p>
	<div class="codigo">O HTML: <br />&lt;html&gt;<br />&#8230;<br />&lt;script type=&quot;text/javascript&quot; src=&quot;js.php&quot;&gt;&lt;/script&gt;<br />&#8230;<br />&lt;/html&gt; </div>
	<div class="codigo">O arquivo js.php <br />&lt;?php<br />header(&#8217;Content-type: text/javascript&#8217;);<br />$info = peguealgoimportante();<br />print &quot;alert(&#8217;$info&#8217;);&quot;; <br />?&gt; </div>
	<p>Maneiro isso, n&atilde;o? mas n&atilde;o para por aí&#8230; olha o que podemos fazer: </p>
	<div class="codigo">O HTML: <br />&lt;html&gt;<br />&#8230;<br />&lt;script type=&quot;text/javascript&quot; src=&quot;js.php?num=12&quot;&gt;&lt;/script&gt;<br />&#8230;<br />&lt;/html&gt; </div>
	<div class="codigo">O arquivo js.php <br />&lt;?php<br />header(&#8217;Content-type: text/javascript&#8217;);<br />$info = $_GET[&#8217;num&#8217;];<br />print &quot;alert(&#8217;$info&#8217;);&quot;; <br />?&gt; </div>
	<p>ou assim&#8230; acho que fica mais fácil. Intercalar o JS com as TAGs PHP ao invés de usar fun&ccedil;&otilde;es de impress&atilde;o é uma boa estratégia, pois evita a confus&atilde;o que é imprimir aspas dentro de aspas. Outra é que podemos mudar a extens&atilde;o do arquivo para .JS temporariamente e editar o JS com a sintaxe real&ccedil;ada no DW, por exemplo. </p>
	<div class="codigo">&lt;?php<br />header(&#8217;Content-type: text/javascript&#8217;);<br />$info = $_GET[&#8217;num&#8217;];<br />?&gt; <br />alert(&#8217;&lt;?=$info?&gt;&#8217;);</div>
	<p>Isso funciona! podemos passar par&acirc;metros por GET na URL do script PHP e como estamos usando o content-type = text/javascript, o browser n&atilde;o terá problemas em interpretar a resposta como JS. </p>
	<p class="negrito">Mas e para fazer isso sem recarregar a página? </p>
	<p>Também é possível, mas só com ajax. N&atilde;o é complicado, mas voc&ecirc; deveria estudar um pouco sobre ajax antes de tentar esse método&#8230;</p>
	<p>Essa aqui é a fun&ccedil;&atilde;o mais simples possível para usar ajax:</p>
	<div class="codigo">function readFile(url) {<br />var req = document.all ? new ActiveXObject(&quot;Microsoft.XMLHTTP &quot;) : new XMLHttpRequest();<br />req.open(&#8217;GET&#8217;, url, false); req.send(null); <br />&nbsp;&nbsp;// espera enquanto a requisi&ccedil;&atilde;o é processada&#8230;<br />&nbsp;&nbsp;// confiss&atilde;o: esta linha é uma idéia que n&atilde;o foi<br />&nbsp;&nbsp;// testada&#8230; mas deve funcionar&#8230; <br />&nbsp;&nbsp;while(req.readyState &lt; 4) void(0);<br />return req.status == 200 ? req.responseText : false;<br />}</div>
	<p>usaríamos ent&atilde;o dessa forma: </p>
	<div class="codigo">&#8230;<br />&lt;input type=button value=clique onclick=&quot;<br />var val = this.form.tex.value; <br />var resp = readFile(&#8217;meuphp.php?value=&#8217;+val); <br />alert(resp);&quot; /&gt;<br />&#8230; </div>
	<p>O que fosse impresso por meuphp.php seria recebido como texto na variável resp, no javascript. </p>
	<p>Devem haver outras técnicas que desconhe&ccedil;o&#8230; se voc&ecirc; conhece, comente.</p>
	<p>Abra&ccedil;o a todos, Cau Guanabara </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/04/14/formas-de-integrar-php-e-javascript/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Eu não sei programar sem ERs</title>
		<link>http://cauguanabara.blogsome.com/2007/04/02/eu-nao-sei-programar-sem-ers/</link>
		<comments>http://cauguanabara.blogsome.com/2007/04/02/eu-nao-sei-programar-sem-ers/#comments</comments>
		<pubDate>Mon, 02 Apr 2007 03:23:27 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
	<category>Javascript</category>
	<category>PHP</category>
		<guid>http://cauguanabara.blogsome.com/2007/04/02/eu-nao-sei-programar-sem-ers/</guid>
		<description><![CDATA[	Estava pensando nisso outro dia. Eu n&atilde;o sei mesmo programar sem ERs, talvez por ter iniciado com o Perl (a primeira linguagem a popularizar as ERs), mas certamente pela praticidade que elas representam na hora de manipular strings.
	Na época em que o Perl come&ccedil;ou a ficar famoso era comum ouvir comentários por parte de programadores [...]]]></description>
			<content:encoded><![CDATA[	<p>Estava pensando nisso outro dia. Eu n&atilde;o sei mesmo programar sem ERs, talvez por ter iniciado com o Perl (a primeira linguagem a popularizar as ERs), mas certamente pela praticidade que elas representam na hora de manipular strings.</p>
	<p>Na época em que o Perl come&ccedil;ou a ficar famoso era comum ouvir comentários por parte de programadores de outras linguagens sobre aquelas<em> &quot;linhas enigmáticas e indecifráveis do Perl&quot;</em>, querendo se referir &agrave;s tais ERs. Hoje as Express&otilde;es Regulares est&atilde;o em todos os lugares. Se voc&ecirc; está lendo este artigo, deve ser um desenvolvedor web, portanto usa ou já usou o famoso Dreamweaver. Pois bem, na janela de busca e substitui&ccedil;&atilde;o existe a op&ccedil;&atilde;o &quot;use regular expression&quot; (minha vers&atilde;o é em ingl&ecirc;s&#8230;), já reparou? e é uma m&atilde;o-na-roda, pode crer. Nas linguagens ent&atilde;o&#8230; praticamente todas tem suporte para ERs. Repare no exemplo abaixo: </p>
<a id="more-28"></a><br />
<div class="codigo">&lt;?php<br />// exemplo.php<br />$found = &#8216;n&atilde;o encontrado&#8230;&#8217;; <br />$keyword = preg_quote($_REQUEST[&#8217;keyword&#8217;]); <br />$first_letter = preg_quote($_REQUEST[&#8217;first_letter&#8217;]); <br />$conn = mysql_connect(&#8217;localhost&#8217;, &#8216;user&#8217;,'passw&#8217;);<br />mysql_select_db(&#8217;registros&#8217;); <br />$sql = &quot;SELECT * FROM allregs WHERE val REGEXP &quot;;<br />$sql .= &quot;&#8217;^$first_letter&#8217;&quot;; // ER! <br />$res = mysql_query($sql, $conn); <br />&nbsp;&nbsp;while($arr = mysql_fetch_row($res)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;// ER! <br />&nbsp;&nbsp;&nbsp;&nbsp;if(preg_match(&quot;/\b&quot;.$keyword.&quot;\b/i&quot;, $arr[&#8217;val&#8217;])) {<br />&nbsp;&nbsp;&nbsp;&nbsp;$found = &#8216;encontrado!&#8217;; <br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;} <br />?&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;script&gt;<br />var found = &quot;&lt;?=$found?&gt;&quot;; <br />var first_letter = &quot;&lt;?=$_REQUEST[&#8217;first_letter&#8217;]?&gt;&quot;;<br />var keyword = &quot;&lt;?=$_REQUEST[&#8217;keyword&#8217;]?&gt;&quot;;<br />&nbsp;&nbsp;if(/^n&atilde;o/.test(found)) alert(&#8217;no no no&#8230;&#8217;); // ER! <br />&nbsp;&nbsp;else alert(&#8217;Ok, achamos um valor iniciado por &#8216;+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;first_letter+&#8217; e contendo &#8216;+keyword);<br />&lt;/script&gt;<br />&lt;/head&gt;<br />&lt;body /&gt; <br />&lt;/html&gt;</div>
	<p>&nbsp;</p>
	<p>Nosso exemplo n&atilde;o teria muita utilidade na prática, mas reparou que existem ERs nos tr&ecirc;s níveis (MySQL, PHP e Javascript)? pois é, é assim que eu penso ao programar. &Agrave;s vezes até para transformar algum atributo de uma TAG ou mesmo criar e inserir novas TAGs no documento, eu prefiro o innerHTML, para manipular o texto com ERs, que o DOM (o que seria mais &#8216;natural&#8217;).</p>
	<p>Já ouvi que sou maluco e que o método tradicional (strpos, substr, etc. (PHP) ou indexOf, etc. (JS)) é muito mais fácil. Desculpem mas eu discordo redondamente. Com ERs eu escrevo menos e e consigo resultados mais eficientes. </p>
	<p>No meu <a href="http://cauguanabara.jsbrasil.com/tutorphp/index.html" target="_blank">tutorial</a> há um capítulo onde falo do básico sobre ERs no PHP, dando destaque &agrave;s fun&ccedil;&otilde;es compatíveis com o Perl [<a href="http://cauguanabara.jsbrasil.com/tutorphp/html/er.html" target="_blank">leia</a>], mas o <a href="http://aurelio.wordpress.com/" target="_blank">Aurélio</a>, guru das express&otilde;es regulares, já tinha feito muito melhor. É dele o <a href="http://aurelio.net/er/livro/" target="_blank">primeiro livro brasileiro sobre express&otilde;es regulares </a>, disponível <a href="http://guia-er.sourceforge.net/index.html" target="_blank">online</a> também (o livro é muito legal, de fácil entendimento). Consulte o Aurélio para saber mais sobre como usar ERs. </p>
	<p>As express&otilde;es regulares foram concebidas por dois neurologistas em 1943 num estudo sobre o funcionamento dos neur&ocirc;nios humanos que, anos mais tarde, foi retomado por um matemático que criou as nota&ccedil;&otilde;es, os símbolos para representar esses padr&otilde;es - que só caíram nas gra&ccedil;as da informática mais de 20 anos após sua concep&ccedil;&atilde;o. O fato se deu em ambiente Linux, o que explica a rela&ccedil;&atilde;o com o Perl, nativo desse mesmo habitat. Tudo isso está dito no guia de consulta do Aurélio, já citado, mas repito aqui por achar, no mínimo, curiosa essa história.</p>
	<p>Aprender ERs nunca será perda de tempo, pois há suporte amplo para elas na maior parte das linguagens e elas est&atilde;o baseadas em conceitos sólidos - n&atilde;o v&atilde;o mudar com a próxima vers&atilde;o de se-lá-o-que-for. Além disso, elas tornam seu programa mais inteligente, capaz de ler e modificar um texto de um modo mais semelhante ao modo humano.</p>
	<p>É isso aí, foi apenas o desabafo de um programador que n&atilde;o se conforma com essa demora&#8230; por qu&ecirc; elas n&atilde;o s&atilde;o mais populares ?!? </p>
	<p>Para terminar, vou repetir: n&atilde;o sei programar sem ERs. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/04/02/eu-nao-sei-programar-sem-ers/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Mesclar PHP e HTML - print, echo e outras&#8230;</title>
		<link>http://cauguanabara.blogsome.com/2007/02/28/mesclar-php-e-html-print-echo-e-outras/</link>
		<comments>http://cauguanabara.blogsome.com/2007/02/28/mesclar-php-e-html-print-echo-e-outras/#comments</comments>
		<pubDate>Thu, 01 Mar 2007 02:10:07 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>PHP</category>
	<category>Tutoriais</category>
		<guid>http://cauguanabara.blogsome.com/2007/02/28/mesclar-php-e-html-print-echo-e-outras/</guid>
		<description><![CDATA[	Este é um tema com o qual todos que aprendem PHP tem que conviver desde o início dos estudos. O HTML é a linguagem oficial, o tipo de saída padr&atilde;o do PHP (text/html), mas há certos detalhes que n&atilde;o devem ser esquecidos. Vou me esfor&ccedil;ar para lembrar do que me atrapalhava há alguns anos (ou [...]]]></description>
			<content:encoded><![CDATA[	<p>Este é um tema com o qual todos que aprendem PHP tem que conviver desde o início dos estudos. O HTML é a linguagem oficial, o tipo de saída padr&atilde;o do PHP (text/html), mas há certos detalhes que n&atilde;o devem ser esquecidos. Vou me esfor&ccedil;ar para lembrar do que me atrapalhava há alguns anos (ou ainda atrapalha&#8230;) e tentar explicar.</p>
	<p class="negrito">As fun&ccedil;&otilde;es print() e echo() </p>
	<p>Servem basicamente para a mesma coisa, com algumas diferen&ccedil;as&#8230;</p>
<a id="more-27"></a>
<ul>
<li>echo é capaz de receber mais de um par&acirc;metro, mostrando a concatena&ccedil;&atilde;o dos mesmos. </li>
	<li>echo tem uma forma abreviada para usar dentro do HTML (&lt;?=&quot;abc&quot;?&gt;) . </li>
	<li>print oferece o modo &quot;<a href="http://www.php.net/manual/pt_BR/language.types.string.php#language.types.string.syntax.heredoc" target="_blank">heredoc</a>&quot; que permite misturar HTML, variáveis e aspas indistintamente, mas é bem pouco usado. </li>
	<li>print retorna o valor mostrado. $str = print &quot;teste&quot;; -&gt; imprime <strong>e</strong> coloca em $str o valor &quot;teste&quot;. echo n&atilde;o retorna nada. </li>
	<li>Ambos s&atilde;o constru&ccedil;&otilde;es da linguagem, portanto podem ser chamados com ou sem os par&ecirc;nteses, mas para enviar mais de um par&acirc;metro para echo, o uso de par&ecirc;nteses é problemático. </li>
	<li><a href="http://www.faqts.com/knowledge_base/view.phtml/aid/1/fid/40" target="_blank">Veja uma explica&ccedil;&atilde;o das diferen&ccedil;as entre print e echo</a> (em ingl&ecirc;s). </li>
</ul>
	<div class="codigo">// exemplos válidos<br />echo(&quot;olá&quot;);<br />echo &quot;tamo aí&quot;;<br />// mesclado com HTML (a sintaxe curta<br />// do PHP deve estar habilitada):<br />&lt;?=$variavel?&gt; ou &lt;b&gt;&lt;?=&quot;teste&quot;?&gt;&lt;/b&gt; </p>
	<p>print(&quot;olá&quot;);<br />print &quot;tamo aí&quot;;<br />print &lt;&lt;&lt;FINAL<br />Aqui posso usar aspas de qualquer tipo,<br />quebras de linha, &lt;b&gt;TAGs&lt;/b&gt;, $variaveis e tudo<br />mais. Para acabar, basta usar a palavra definida <br />depois de &#8216;&lt;&lt;&lt;&#8217;, numa linha sem espa&ccedil;os adicionais e<br />terminada por &quot;;&quot;<br />FINAL; </div>
	<p class="negrito">O uso das aspas simples e duplas</p>
	<p>A escolha do tipo de aspas usado com as fun&ccedil;&otilde;es de impress&atilde;o (print e echo) é fundamental, pois o resultado pode ser bastante diferente. <br />Com aspas duplas (&quot;) podemos usar variáveis e caracteres especiais, como &#8216;\n&#8217; (para criar uma quebra de linha), já entre aspas simples tudo é literalmente impresso. Veja: </p>
	<div class="codigo">$num = 5;</p>
	<p>print &quot;Maria comprou $num tomates&quot;; <br />// imprime:<br />// Maria comprou 5 tomates</p>
	<p>print &#8216;Maria comprou $num tomates&#8217;;<br />// imprime:<br />// Maria comprou $num tomates</p>
	<p>print &quot;linha 1\nLinha 2&quot;; <br />/* imprime:<br />linha 1<br />Linha 2<br />*/</p>
	<p>print &#8216;linha 1\nLinha 2&#8242;; <br />/* imprime:<br />linha 1\nLinha 2<br />*/ </p>
	<p>// para imprimir quebras de linha com aspas simples ou <br />// duplas , podemos usar o caracter literal<br />print &quot;Linha 1<br />Linha 2<br />Linha 3&quot;; </div>
	<p class="negrito">Para imprimir aspas dentro de aspas</p>
	<p>Entre aspas simples podemos usar aspas duplas &agrave; vontade - e vice versa. Para usar duplas dentro de duplas ou simples dentro de simples, é preciso &#8216;escapá-las&#8217; com uma contra-barra (\&#8217; ou \&quot;) . <a href="http://www.php.net/manual/pt_BR/language.types.string.php#language.types.string.syntax.double" target="_blank">Veja aqui</a>. </p>
	<div class="codigo">print &quot;aqui posso usar &#8216;aspas simples&#8217;&quot;; <br />// ou <br />print &#8216;aqui posso usar \&#8217;aspas simples\'&#8217;; <br />// imprimem:<br />// aqui posso usar &#8216;aspas simples&#8217;</p>
	<p>print &#8216;mas e as &quot;duplas&quot; ???&#8217;;<br />// ou <br />print &quot;mas e as \&quot;duplas\&quot; ???&quot;;<br />// imprimem:<br />// mas e as &quot;duplas&quot; ???</p>
	<p>print &#8216;aqui posso usar &#8216;aspas simples'&#8217;; <br />// ou <br />print &quot;mas e as &quot;duplas&quot; ???&quot;;<br />// gerariam um erro </div>
	<p class="negrito">Misturando strings e variáveis </p>
	<p>Com as aspas duplas, já vimos que podemos mesclar diretamente, sem concatena&ccedil;&atilde;o, mas isso deixa de ser verdadeiro para variáveis complexas como elementos de arrays multidimensionais ou propriedades de objetos. </p>
	<div class="codigo">print &quot;veja: $arr[1][&#8217;elem&#8217;]&quot;;<br />echo &quot;um obj: $obj-&gt;prop-&gt;prop2&quot;; </div>
Os exemplos acima n&atilde;o funcionariam como esperado. Mas existe um meio de contornar isso: o uso dos caracteres &#8216;{&#8217; e &#8216;}&#8217; (chaves - apenas entre aspas duplas). Isso é chamado no manual do PHP de<a href="http://www.php.net/manual/pt_BR/language.types.string.php" target="_blank"> sintaxe complexa</a> e pode ser usada com o sinal $ imediatamente antes ou imediatamente depois de &#8216;{&#8217;, assim:<br />
<div class="codigo">// válidos <br />print &quot;veja: {$arr[1][&#8217;elem&#8217;]}&quot;;<br />echo &quot;um obj: {$obj-&gt;prop-&gt;prop2)&quot;; <br />// ou <br />print &quot;veja: ${arr[1][&#8217;elem&#8217;]}&quot;;<br />echo &quot;um obj: ${obj-&gt;prop-&gt;prop2)&quot;;</div>
	<p>Com isso podemos evitar muitas concatena&ccedil;&otilde;es desnecessárias e chatinhas de escrever, poupando tempo no ato de programar. A sintaxe complexa também vale para o modo heredoc, com print(). </p>
	<p class="negrito">Mesclar PHP e HTML </p>
	<p>Até aqui falamos de PHP, mas como a interface com o usuário é, em quase todos os casos, em HTML, estamos o tempo todo combinando os dois. Qual é a melhor maneira de fazer isso? Bem, a primeira coisa a lembrar é que PHP e HTML s&atilde;o interpretados em níveis diferentes: o PHP no servidor, antes do envio da resposta HTML, que será interpretada (com seus Javascripts, CSS, etc&#8230;) pelo browser. Isso equivale a dizer que podemos escrever livermente o HTML/JS/CSS/etc. com PHP, pois quando estes forem renderizados/executados pelo navegador, o PHP já terá cumprido o seu papel e de tudo que estava entre TAGs PHP só restará o que foi impresso. </p>
	<p>Veja algumas formas possíveis:</p>
	<div class="codigo">&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;&lt;?php print &quot;Título da página&quot;; ?&gt;&lt;/title&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />Isso é permitido (usar HTML puro interpolado com TAGs PHP) - o div só aparece se a condi&ccedil;&atilde;o no if for verdadeira: <br />&lt;?php if(getenv(&#8217;HTTP_HOST&#8217;) == &#8216;localhost&#8217;) { ?&gt;<br />&lt;div class=&quot;home&quot;&gt;Estamos em casa!&lt;/div&gt; <br />&lt;?php } ?&gt; <br />&lt;p&gt;E aqui o modo reduzido, um &#8216;atalho&#8217; para a fun&ccedil;&atilde;o echo(). Imaginemos que $variavel contém algum texto&#8230;&lt;/p&gt;<br />&lt;?=$variavel?&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</div>
	<p>Mostramos acima uma forma de mostrar conteúdos sem usar nenhuma fun&ccedil;&atilde;o de impress&atilde;o, a interpola&ccedil;&atilde;o entre PHP e HTML. Ao passo que encapsulamos a abertura do if em uma TAG PHP e seu fechamento em outra, podemos trabalhar com HTML puro dentro do escopo desse if e esse conteúdo é suprimido se a condi&ccedil;&atilde;o for falsa, mas&#8230; </p>
	<p>Se queremos, por exemplo, criar uma sequ&ecirc;ncia de links e fazemos uma fun&ccedil;&atilde;o para isso, a princípio n&atilde;o podemos usar a interpola&ccedil;&atilde;o simples, pois isso manda diretamente para a tela. A n&atilde;o ser que usemos as&#8230; </p>
	<p class="negrito">Fun&ccedil;&otilde;es de controle de fluxo </p>
	<p>Com as fun&ccedil;&otilde;es ob_* do PHP é possível trabalhar com o HTML puro sem enviar diretamente para a tela. Podemos capturar a saída HTML para uma variável. Veja:</p>
	<div class="codigo">&lt;?php<br />function makeLinks() {<br />global $files, $siteurl;<br />ob_start(); // interrompe a saída <br />&nbsp;foreach($files as $fname) {<br />&nbsp;?&gt;<br />&nbsp;&lt;li class=&quot;lin&quot;&gt;<br />&nbsp;&lt;a href=&quot;&lt;?=$siteurl.&#8217;/&#8217;.$fname?&gt;&quot;&gt;&lt;?=$fname?&gt;&lt;/a&gt;<br />&nbsp;&lt;/li&gt;<br />&nbsp;&lt;?php<br />&nbsp;}<br />// recupera e retorna o que saiu desde ob_start() <br />return ob_get_clean();<br />}<br />?&gt; <br />&lt;ul&gt;<br />&lt;?=makeLinks()?&gt;<br />&lt;/ul&gt;</div>
	<p>A fun&ccedil;&atilde;o acima normalmente seria algo assim: </p>
	<div class="codigo">&lt;?php<br />function makeLinks() {<br />global $files, $siteurl;<br />$ret = &quot;&quot;; <br />&nbsp;foreach($files as $fname) {<br />&nbsp;$ret .= &#8216;&lt;li class=&quot;lin&quot;&gt;<br />&nbsp;&lt;a href=&quot;&#8217;.$siteurl.&#8217;/&#8217;.$fname.&#8217;&quot;&gt;&#8217;.$fname.&#8217;&lt;/a&gt;<br />&nbsp;&lt;/li&gt;&#8217;;<br />&nbsp;}<br />return $ret;<br />}<br />?&gt; <br />&lt;ul&gt;<br />&lt;?=makeLinks()?&gt;<br />&lt;/ul&gt;</div>
	<p>Eu acho mais vantagem a interpola&ccedil;&atilde;o por poder editar o HTML num editor no modo visual, sem precisar criar trechos complexos de HTML na munheca. Bem, acho que é isso. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/02/28/mesclar-php-e-html-print-echo-e-outras/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Definições de cores para a web</title>
		<link>http://cauguanabara.blogsome.com/2007/02/15/definicoes-de-cores-para-a-web/</link>
		<comments>http://cauguanabara.blogsome.com/2007/02/15/definicoes-de-cores-para-a-web/#comments</comments>
		<pubDate>Thu, 15 Feb 2007 18:36:30 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>Tutoriais</category>
	<category>Design</category>
		<guid>http://cauguanabara.blogsome.com/2007/02/15/definicoes-de-cores-para-a-web/</guid>
		<description><![CDATA[	Durante anos tive uma estamparia, tipo empresa de um homem só, onde eu fazia tudo. No início, comprava cores variadas em potes pequenos - para ter uma paleta mais rica. Mas o fato é que isso ficava bem caro e a solu&ccedil;&atilde;o foi come&ccedil;ar a comprar apenas 5 cores e misturá-las para chegar a outras [...]]]></description>
			<content:encoded><![CDATA[	<p>Durante anos tive uma estamparia, tipo empresa de um homem só, onde eu fazia tudo. No início, comprava cores variadas em potes pequenos - para ter uma paleta mais rica. Mas o fato é que isso ficava bem caro e a solu&ccedil;&atilde;o foi come&ccedil;ar a comprar apenas 5 cores e misturá-las para chegar a outras tonalidades. Essas cores, segundo um livro que consultei na época, deveriam ser: ciano, magenta, amarelo, além do branco e do preto.</p>
	<p>Era uma divers&atilde;o misturar e tentar atingir a cor que eu queria. Consultava uma tabela de cores, via a porcentagem de cada uma das primárias e transportava isso para meus potes de tinta - quase sempre era preciso acrescentar uma pitada de branco ou preto. Esse método me dava uma nova tinta, uma cor &quot;chapada&quot;, por isso a necessidade do branco de vez em quando&#8230; mas o sistema usado nas gráficas para imprimir separa as tr&ecirc;s cores primárias e acrescenta uma camada corretiva de preto, imprimindo uma sobre a outra separadamente (o branco é o papel no fundo). É o sistema CMYK (<strong>C</strong>ian, <strong>M</strong>agenta, <strong>Y</strong>ellow e blac<strong>K</strong>). A teoria é que a soma C+M+Y, os tr&ecirc;s a 100%, seria igual a preto - mas na prática isso n&atilde;o se mostra verdadeiro, por isso a camada K foi adicionada.</p>
<a id="more-26"></a>
<p>Até aqui falamos de cor-pigmento, ou seja a cor de uma determinada superfície, que depende da luz branca para aparecer. A idéia é que uma superfície colorida ao receber a luz branca, reflete o seu tom, &quot;absorvendo&quot; as outras tonalidades do espectro, mas existe outro tipo de cor: a cor-luz. </p>
	<p>Esta é como é, n&atilde;o depende de ser iluminada para ser vista. Os tons do p&ocirc;r-do-Sol, por exemplo, ou as cores que voc&ecirc; v&ecirc; no seu monitor. Pois é, o monitor trabalha com cor-luz e aqui a teoria é bem diferente. Trabalhar com cores-luz significa usar o sistema RGB - <strong>R</strong>ed, <strong>G</strong>reen e <strong>B</strong>lue (vermelho, verde e azul), um outro sistema, que inversamente ao anterior, determina que a soma das primárias R+G+B a 100% é igual a branco! O preto aqui se manifesta pela aus&ecirc;ncia de luz. Esse é o sistema com que vamos trabalhar: RGB e para expressar uma cor RGB em documentos HTML usamos normalmente o modo hexadecimal ou, para o CSS, podemos também definir uma cor diretamente em RGB. Vamos inicialmente entender o RGB, depois o hexadecimal. </p>
	<p>Para formar determinada cor, trabalhamos com 3 &quot;canais de cor&quot;, R, G e B. Ao alterar a porcentagem de cada canal de cor, alteramos o resultado final da cor exibida. Como foi dito, R+G+B a 100% = branco, portanto, R+G+B a 0% = preto. <br />Bem, os valores numéricos para cada canal v&atilde;o de zero (0%) a 255 (100%), portanto os exemplos acima seriam (para CSS) escritos assim: </p>
	<ul>
<li>preto: &quot;rgb(0,0,0)&quot; </li>
	<li>branco: &quot;rgb(255,255,255)&quot; </li>
</ul>
	<p>A partir daí podemos, por dedu&ccedil;&atilde;o simples, perceber que para representar as primárias &quot;puras&quot;, bastaria partir do preto, adicionando apenas um canal a 100%:</p>
	<ul>
<li>vermelho (R): &quot;rgb(255,0,0)&quot; </li>
	<li>verde (G): &quot;rgb(0,255,0)&quot;</li>
	<li>azul (B): &quot;rgb(0,0,255)&quot;; </li>
</ul>
	<p>Se usarmos o método &quot;inverso&quot;, partindo do branco e subtraindo apenas um dos canais, chegamos &agrave;s cores CMY do sistema CMYK:</p>
	<ul>
<li>ciano (C): &quot;rgb(0,255,255)&quot; </li>
	<li>magenta (M): &quot;rgb(255,0,255)&quot; </li>
	<li>amarelo (Y): &quot;rgb(255,255,0)&quot; </li>
</ul>
	<p>Outra é que sempre que todos os canais tiverem o mesmo valor (como no branco e no preto), estaremos falando de tons de cinza. Se imaginarmos um gráfico para representar os tr&ecirc;s canais, entenderemos que a cor surge da curva, enquanto a reta é cinza. Apenas para dar uma idéia mais clara sobre o que estou falando: </p>
	<p><img height="120" alt="cores" src="http://cauguanabara.jsbrasil.com/img/coresgraf.jpg" width="140" border="0" /></p>
	<p>Já ficou mais fácil entender como funciona a coisa, n&atilde;o? Agora é só come&ccedil;ar a usar valores intermediários para se conseguir as outras cores. N&atilde;o é muito diferente de misturar tintas&#8230; Ok, vamos agora entender o sistema hexadecimal, que será apenas uma outra forma de escrever uma cor RGB, dividida por canais, só que com os valores representados de forma hexadecimal.</p>
	<p>N&atilde;o vou entrar em detalhes sobre o <a href="http://pt.wikipedia.org/wiki/Sistema_hexadecimal" target="_blank">sistema hexadecimal</a> mas vamos ver como traduzir um valor decimal para hexadecimal usando Javascript. Num <a href="http://cauguanabara.blogsome.com/2007/01/19/achando-a-cor-oposta">post recente</a>, mostro fun&ccedil;&otilde;es para converter rgb &lt;-&gt; hexadecimal, aqui vou mostrar apenas o cerne da coisa. </p>
	<p>Os valores hexadecimais s&atilde;o 16: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E e F. As letras foram usadas para representar números de dois dígitos com apenas um caracter. <br />Veja: A = 10, B = 11, C = 12 , &#8230;, F = 15. </p>
	<p>O sistema hexadecimal é largamente utilizado em computa&ccedil;&atilde;o (n&atilde;o apenas nas cores) por representar uma economia considerável de de memória e de processamento. Veja o que achei na wikipedia (<a href="http://pt.wikipedia.org/wiki/Sistema_hexadecimal" target="_blank">&#8230;/wiki/Sistema_hexadecimal</a>):</p>
<em><br />
<blockquote><em>A utiliza&ccedil;&atilde;o do sistema hexadecimal nos computadores, deve-se a que um dígito hexadecimal representa quatro dígitos binários (4 bits = 1 nibble); portanto, dois dígitos hexadecimais representam oito dígitos binários (8 bits = 1 byte), que, como é sabido, é a unidade básica de armazenamento de informa&ccedil;&atilde;o.</em></blockquote>
</em>
<p>O sistema matemático de convers&atilde;o para hexadecimal n&atilde;o é algo t&atilde;o complicado&#8230; Veja <a href="http://www.guiadohardware.net/comunidade/decimal/145279/#post1088373" target="_blank">neste comentário</a> ou <a href="http://www.icea.gov.br/ead/anexo/21301.htm" target="_blank">nesta página mais completa.</a></p>
	<p>O formulário abaixo usa Javascript para traduzir um valor RGB (0-255) decimal para hexadecimal. Tudo acontece no evento onsubmit do form (veja o código abaixo). </p>
	<div class="codigo">&lt;form onsubmit=&quot;<br />// dc -&gt; valor decimal digitado (ou &#8216;null&#8217;) <br />var dc = /^\-?\d+$/.test(this.dec.value) ? <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parseInt(this.dec.value) : &#8216;null&#8217;; <br />if(dc == &#8216;null&#8217;) alert(&#8217;Isto n&atilde;o é um número decimal&#8217;);<br />if(dc &lt; 0 || dc &gt; 255) {<br />alert(&#8217;Este n&atilde;o é um valor RGB válido&#8217;);<br />dc = &#8216;null&#8217;;<br />}<br />// Aqui usamos o método Number.toString() passando<br />// o núm. 16 como par&acirc;metro. Isso faz retornar uma<br />// string equivalente em hexadecimal <br />var hx = dc.toString(16).toUpperCase();<br />// se retornar um único caracter, colocamos o &#8216;0&#8242; antes.<br />// Cada canal de cor trabalha com dois dígitos, <br />// obrigatoriamente.<br />this.hex.value = hx.length &lt; 2 ? &#8216;0&#8242;+hx : hx;<br />this.dec.focus();<br />this.dec.select();<br />return false;&quot;&gt;<br />decimal &lt;input type=&quot;text&quot; name=&quot;dec&quot; size=&quot;10&quot; value=&quot;255&quot;&gt; <br />&lt;input type=&quot;submit&quot; value=&quot; &gt;&gt; &quot; /&gt;<br />&lt;input type=&quot;text&quot; name=&quot;hex&quot; size=&quot;10&quot;&gt; hexadecimal<br />&lt;/form&gt;</div>
	<p><a href="javascript:rgbhex();">Tradutor RGB &lt;=&gt; hexadecimal</a> </p>
Agora que podemos traduzir valores RGB para hex., vamos analisar o modo hexadecimal de representa&ccedil;&atilde;o das cores. Uma cor é representada por uma sequ&ecirc;ncia de 6 caracteres [0-9a-fA-F], precedida de &quot;#&quot;, como em &quot;#FFFFFF&quot;.
<p>Retirando-se o &quot;#&quot; , os seis caracteres restantes representam os 3 canais RGB, nessa sequ&ecirc;ncia, dois a dois. Por ex. em &quot;#66AAFF&quot; o canal R está representado por &quot;66&quot;, o G por &quot;AA&quot; e o B por &quot;FF&quot;. Se voc&ecirc; clicou no bot&atilde;o acima, já viu que 255 em hex. é igual a &quot;FF&quot;. Ent&atilde;o já podemos deduzir que &quot;#FFFFFF&quot; é o mesmo que &quot;rgb(255,255,255)&quot; (branco) e que &quot;rgb(0,0,0)&quot; é igual a &quot;#000000&quot; (preto). Como seriam ent&atilde;o as primárias em hexadecimal?</p>
	<ul>
<li>vermelho (R): &quot;#FF0000&quot;</li>
	<li>verde (G): &quot;#00FF00&quot;</li>
	<li>azul (B): &quot;#0000FF&quot;</li>
</ul>
	<p>ou, para as primárias do sistema CMYK: </p>
	<ul>
<li>ciano (C): &quot;#00FFFF&quot;</li>
	<li>magenta (M): &quot;#FF00FF&quot;</li>
	<li>amarelo (Y): &quot;#FFFF00&quot; </li>
</ul>
	<p>Como em RGB, agora basta usar tons maiores que &quot;00&quot; e menores que &quot;FF&quot; para obter qualquer outra cor. aqui está uma <a href="http://www.psyclops.com/tools/rgb/" target="_blank">ferramenta legal</a> para botar em prática o que foi dito aqui.</p>
	<p>No mais, bom carnaval 2007!!!! </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/02/15/definicoes-de-cores-para-a-web/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Receber dados de formulário com Javascript</title>
		<link>http://cauguanabara.blogsome.com/2007/02/14/receber-dados-de-formulario-com-javascript/</link>
		<comments>http://cauguanabara.blogsome.com/2007/02/14/receber-dados-de-formulario-com-javascript/#comments</comments>
		<pubDate>Wed, 14 Feb 2007 18:17:48 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2007/02/14/receber-dados-de-formulario-com-javascript/</guid>
		<description><![CDATA[	
N&atilde;o, o Javascript n&atilde;o faz isso&#8230; voc&ecirc; precisa de um script de servidor (tipo ASP, PHP, etc.) para receber e tratar esses dados.

Isso é verdade, mas uma verdade relativa&#8230; a princípio, o Javascript n&atilde;o pode mesmo fazer isso, mas pode ler a URL completa do documento atual. 
	Tá mas e daí? Para quem fez essa [...]]]></description>
			<content:encoded><![CDATA[	<p><em><br />
<blockquote><em>N&atilde;o, o Javascript n&atilde;o faz isso&#8230; voc&ecirc; precisa de um script de servidor (tipo ASP, PHP, etc.) para receber e tratar esses dados.</em></blockquote>
</em>
<p>Isso é verdade, mas uma verdade relativa&#8230; a princípio, o Javascript n&atilde;o pode mesmo fazer isso, mas pode ler a URL completa do documento atual. </p>
	<p><strong>Tá mas e daí? </strong><br />Para quem fez essa pergunta, vou primeiro explicar que, como quem quer aprender Javascript já deveria saber, existem dois métodos básicos para enviar dados ao servidor:</p>
	<blockquote><ul>
<li><strong>POST</strong> <br />Usando POST, os dados v&atilde;o embutidos nos headers (cabe&ccedil;alhos) HTTP que s&atilde;o trocados entre o servidor e o navegador web (escondido do usuário).</li>
	<li><strong>GET</strong> <br />Por GET os dados s&atilde;o enviados como parte da URL, após o sinal &#8216;?&#8217;.</li>
</ul></blockquote>
	<p>Se podemos ler a URL ent&atilde;o temos acesso aos dados enviados por GET, bastando tratá-los para poder ler e usar. Vamos dar um exemplo prático, come&ccedil;ando pelo envio dos dados.</p>
<a id="more-25"></a>
<p>Podemos simplesmente criar um formulário e definir o atributo &quot;method&quot; para &quot;get&quot;, assim:</p>
	<div class="codigo">&lt;form method=&quot;get&quot; action=&quot;file.html&quot;&gt;<br />&lt;p&gt;<br />&lt;label for=&quot;nome&quot;&gt;Nome:&lt;/label&gt;<br />&lt;input type=&quot;text&quot; name=&quot;nome&quot; id=&quot;nome&quot; /&gt;<br />&lt;/p&gt;<br />&lt;p&gt;<br />&lt;label for=&quot;email&quot;&gt;E-mail:&lt;/label&gt;<br />&lt;input type=&quot;text&quot; name=&quot;email&quot; id=&quot;email&quot; /&gt;<br />&lt;/p&gt;<br />&lt;p align=&quot;right&quot;&gt;<br />&lt;input type=&quot;submit&quot; value=&quot;Enviar&quot; /&gt;<br />&lt;/p&gt;<br />&lt;/form&gt;</div>
	<p>Mas podemos também criar a query string manualmente. Há tr&ecirc;s fun&ccedil;&otilde;es em Javascript para codificar esses dados:</p>
	<ul>
<li>escape -&gt; desatualizada. Codifica os dados em hexadecimal</li>
	<li>encodeURIComponent -&gt; codifica uma string para ser enviada (UTF-8)</li>
	<li>encodeURI -&gt; codifica uma URI inteira para ser enviada (UTF-8)</li>
</ul>
	<p>Supondo que os dados s&atilde;o do &quot;jo&atilde;o&quot;, com o email &quot;jo@o.com&quot;. Nesse caso, o valor enviado pelo formulário seria uma string (iniciada por &quot;?&quot; e seguida por pares nome-valor, unindo o nome ao valor por &quot;=&quot; e um par ao outro por &quot;&amp;&quot;) colocada ao final da URI definida na propriedade action do formulário, resultando em algo assim: </p>
	<blockquote><p>file.html?nome=jo%E3o&amp;email=jo@o.com </p></blockquote>
	<p>Mas e se quisermos criar um link dinamicamente? </p>
	<div class="codigo">var nome = &quot;jo&atilde;o&quot;; <br />var email = &quot;jo@o.com&quot;; <br />var file = &quot;file.html&quot;; <br />// aqui precisamos usar a fun&ccedil;&atilde;o de codifica&ccedil;&atilde;o<br />var uri = file + &quot;?nome=&quot; +encodeURIComponent(nome)<br />&nbsp; &nbsp; &nbsp; &nbsp; + &quot;&amp;email=&quot; +encodeURIComponent(email);<br />location.href = uri; </div>
	<p>Repare que o resultado do script acima é ligeiramente diferente do anterior (formulário):</p>
	<blockquote><p>file.html?nome=jo%C3%A3o&amp;email=jo%40o.com</p></blockquote>
	<p>Isso ocorre por qu&ecirc; o método nativo utilizado ao submeter um formulário codifica em ASCII hexadecimal e o script acima resulta numa string codificada em UTF-8, que é mais universal. Bem, ok. Os dados foram enviados&#8230; vamos receb&ecirc;-los!</p>
	<p>Vamos construir uma fun&ccedil;&atilde;o que l&ecirc; a URI e retorna os pares nome/valor encontrados, na forma de um objeto. A fun&ccedil;&atilde;o está toda comentada. Lá vai&#8230;</p>
	<div class="codigo">function getVars() {<br />var ret = {}; // objeto a ser retornado <br />// a URI completa<br />var uri = location.href;<br />&nbsp;&nbsp;// se n&atilde;o há query string, retorna nulo<br />&nbsp;&nbsp;if(!(/\?/.test(uri))) return null;<br />// separa a query string (o que vem depois de &#8216;?&#8217;) <br />var qs = uri.split(&#8217;?')[1]; <br />// separando os pares nome/valor<br />var pairs = qs.split(&#8217;&amp;&#8217;);<br />&nbsp;&nbsp;// para cada par&#8230;<br />&nbsp;&nbsp;for(var i = 0; i &lt; pairs.length; i++) {<br />&nbsp;&nbsp;var nv = pairs[i].split(&#8217;='); <br />&nbsp;&nbsp;ret[nv[0]] = decodeURIComponent(nv[1]); <br />&nbsp;&nbsp;} <br />return ret; <br />}</div>
	<p>Importante ressaltar que, no caso de haver múltiplos inputs com o mesmo nome, apenas o último irá valer. </p>
	<p><a href="http://cauguanabara.jsbrasil.com/scripts/jsget/" target="_blank">Veja aqui um script mais complexo</a> para gerar e receber variáveis GET. Neste há suporte para o método utilizado pelo PHP para trabalhar com grupos de checkboxes (normalmente), onde basta acrescentar &#8216;[]&#8217; ao nome que será repetido nos inputs, que o sistema receberá esses dados como um array contendo todos os valores dos campos de mesmo nome, terminados por &#8216;[]&#8217; . </p>
	<p>Basta agora atribuir o resultado da fun&ccedil;&atilde;o a uma variável, assim:</p>
	<div class="codigo">var _GET = getVars(); <br />// _GET agora é um objeto com os valores, assim:<br />// {&#8217;nome&#8217;: &#8216;jo&atilde;o&#8217;, &#8216;email&#8217;: &#8216;jo@ao.com&#8217; }</div>
	<p>Como a URL da página está disponível desde o primeiro momento, n&atilde;o é preciso usar o evento onload. Podemos simplesmente executar antes da página carregar. </p>
	<p>É isso aí e bom carnaval!!! </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/02/14/receber-dados-de-formulario-com-javascript/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Achando a cor oposta</title>
		<link>http://cauguanabara.blogsome.com/2007/01/19/achando-a-cor-oposta/</link>
		<comments>http://cauguanabara.blogsome.com/2007/01/19/achando-a-cor-oposta/#comments</comments>
		<pubDate>Fri, 19 Jan 2007 17:59:50 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Funções</category>
	<category>Design</category>
		<guid>http://cauguanabara.blogsome.com/2007/01/19/achando-a-cor-oposta/</guid>
		<description><![CDATA[	Acabei de construir uma fun&ccedil;&atilde;ozinha muito útil em Javascript para inverter uma determinada cor, que pode ser enviada&nbsp;em rgb ou hexadecimal. Resolvi compartilhar com voc&ecirc;s.
	Minha situa&ccedil;&atilde;o era a seguinte: eu precisava marcar, sobressaltar partes de um texto, mas n&atilde;o sabia qual seria a cor desse texto. Bem, para isso existe o valor &#8216;highlight&#8217;, mas ele [...]]]></description>
			<content:encoded><![CDATA[	<p>Acabei de construir uma fun&ccedil;&atilde;ozinha muito útil em Javascript para inverter uma determinada cor, que pode ser enviada&nbsp;em rgb ou hexadecimal. Resolvi compartilhar com voc&ecirc;s.</p>
	<p>Minha situa&ccedil;&atilde;o era a seguinte: eu precisava marcar, sobressaltar partes de um texto, mas n&atilde;o sabia qual seria a cor desse texto. Bem, para isso existe o valor &#8216;highlight&#8217;, mas ele n&atilde;o é aconselhado pela W3C&#8230; e nem sempre o resultado é ir para a cor oposta a do texto, embora resolva os problemas de baixo contraste. Mas o W3C falou, tá falado. Usei, a princípio, cores fixas (fundo azul marinho e fonte branca). N&atilde;o ficava mal, mas seria mais elegante usar a cor oposta&#8230; e&nbsp;fiquei com isso na cabe&ccedil;a: como inverter uma cor?</p>
<a id="more-23"></a>
<p>Bem, tanto o sistema hexadecimal quanto o rgb trabalham com as cores básicas - vermelho, verde e azul - com um valor mínimo (hex:00, rgb:0) e um&nbsp;máximo (hex:FF, rgb:255)&nbsp;para cada uma. Tendo o início e o final do &#8216;espectro&#8217;, poderíamos subtrair o valor enviado do valor máximo, obtendo um valor &#8216;oposto&#8217;&#8230; naturalmente, optamos por usar o sistema RGB, que trabalha apenas com valores numéricos (0-255). </p>
	<p>A primeira coisa que precisava eram fun&ccedil;&otilde;es para traduzir rgb para hexadecimal e vice-versa. Achei aqui umas fun&ccedil;&otilde;es que usei a um tempo atrás, provavelmente retiradas do HTMLArea (atual Xinha), para o qual construí alguns plugins. Lá v&atilde;o elas:</p>
	<div class="codigo">// rgb2hex -&gt; traduz uma cor definida em RGB para o sistema Hexadecimal<br />// r -&gt; vermelho (0-255)<br />// g -&gt; verde (0-255)<br />// b -&gt; azul (0-255)<br />// retorno: retorna a cor em hexadecimal<br />var rgb2hex = function(r,g,b) {<br />return &#8216;#&#8217;+hex(r)+hex(g)+hex(b);<br />&nbsp;function hex(dec) { <br />&nbsp; &nbsp;if(typeof(dec) != &#8216;number&#8217; || dec &lt; 0 || dec &gt; 255) return(&quot;&#8211;&quot;);<br />&nbsp;var chars = &quot;0123456789ABCDEF&quot;, md = dec % 16; &nbsp;<br />&nbsp;return chars.charAt((dec - md) / 16) + chars.charAt(md);<br />&nbsp;}<br />}</p>
	<p>// hex2rgb -&gt; traduz uma cor definida em Hexadecimal para o sistema RGB<br />// str -&gt; cor em hexadecimal<br />// cssret -&gt; se definido como true, ao invés de retornar um objeto, a fun&ccedil;&atilde;o <br />// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retornará uma string assim: &#8216;rgb(120, 120, 120)&#8217;<br />var hex2rgb = function(str, cssret) {<br />var&nbsp;ret = {}, hexStr = str.replace(/^#?/,&quot;&quot;); <br />&nbsp;if(!/^([\dA-Fa-f]{2})([\dA-Fa-f]{2})([\dA-Fa-f]{2})$/.test(hexStr)) return str;<br />ret.r = parseInt(&quot;0x&quot; + RegExp.$1);<br />ret.g = parseInt(&quot;0x&quot; + RegExp.$2);<br />ret.b = parseInt(&quot;0x&quot; + RegExp.$3); <br />return cssret ? &#8216;rgb(&#8217;+ret.r+&#8217;, &#8216;+ret.g+&#8217;, &#8216;+ret.b+&#8217;)&#8217; : ret;<br />} </div>
	<p>Agora basta fazer a fun&ccedil;&atilde;o para inverter. Trata-se de uma a&ccedil;&atilde;o simples, mas a fun&ccedil;&atilde;o acabou ficando grande pois trabalha com valores em Hex e RGB, retornando um tipo semelhante ao que foi enviado, mas sempre na forma de uma string. </p>
	<p>O valor enviado &agrave; fun&ccedil;&atilde;o invertColor pode ser como os exemplos a seguir:</p>
	<ul>
<li>invertColor(&quot;#CC0000&quot;) -&gt; retornaria algo como &quot;#0000CC&quot;</li>
	<li>invertColor(&quot;FFFF00&quot;) -&gt; retornaria algo como &quot;#0000FF&quot;</li>
	<li>invertColor(&quot;#FF0&quot;) -&gt; retornaria algo como &quot;#0000FF&quot;</li>
	<li>invertColor(&quot;FF0&quot;) -&gt; retornaria algo como &quot;#0000FF&quot;</li>
	<li>invertColor(120, 120, 0) -&gt; retornaria algo como &quot;rgb(135, 135, 255)&quot;</li>
	<li>invertColor(&quot;rgb(120, 120, 0)&quot;) -&gt; retornaria algo como &quot;rgb(135, 135, 255)&quot;</li>
</ul>
	<p>Lá vai a fun&ccedil;&atilde;o:</p>
	<div class="codigo">function invertColor() {<br />var args = invertColor.arguments; //alert(&#8217;&quot;&#8217;+args[0]+&#8217;&quot;&#8217;);<br />var regs = {&#8217;hex&#8217;: /^#?[A-Fa-f0-9]{6}/, &#8216;hex3&#8242;: /^#?([A-Fa-f0-9])([A-Fa-f0-9])([A-Fa-f0-9])/, <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#8217;rgbstr&#8217;: /rgb\(([\d\s,]+)\)/};<br />var r = 0, g = 0, b = 0, typ = &#8216;&#8217;;<br />&nbsp;if(args.length == 1) { //alert(1);<br />&nbsp; &nbsp;if(regs.hex.test(args[0])) {<br />&nbsp; &nbsp;typ = &#8216;hex&#8217;;<br />&nbsp; &nbsp;var rgb = hex2rgb(args[0]);<br />&nbsp; &nbsp;r = rgb.r; g = rgb.g; b = rgb.b;<br />&nbsp; &nbsp;} else if(regs.hex3.test(args[0])) {<br />&nbsp; &nbsp;typ = &#8216;hex&#8217;;<br />&nbsp; &nbsp;var str = RegExp.$1+RegExp.$1+RegExp.$2+RegExp.$2+RegExp.$3+RegExp.$3;<br />&nbsp; &nbsp;var rgb = hex2rgb(str);<br />&nbsp; &nbsp;r = rgb.r; g = rgb.g; b = rgb.b;<br />&nbsp; &nbsp;} else if(regs.rgbstr.test(args[0])) {<br />&nbsp; &nbsp;typ = &#8216;rgb&#8217;;<br />&nbsp; &nbsp;var arr = RegExp.$1.split(/\s*,\s*/);<br />&nbsp; &nbsp;r = Number(arr[0]), g = Number(arr[1]), b = Number(arr[2]);<br />&nbsp; &nbsp;}<br />&nbsp;} else if(args.length == 3) { //alert(2);<br />&nbsp;typ = &#8216;rgb&#8217;;<br />&nbsp;r = Number(args[0]), g = Number(args[1]), b = Number(args[2]);<br />&nbsp;}<br />return typ == &#8216;hex&#8217; ? rgb2hex(255 - r, 255 - g, 255 - b) <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &#8216;rgb(&#8217;+(255 - r)+&#8217;, &#8216;+(255 - g)+&#8217;, &#8216;+(255 - b)+&#8217;)';<br />} </div>
	<p>Segue um exemplo para testar a fun&ccedil;&atilde;o:</p>
	<div class="codigo">&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot; /&gt;<br />&lt;title&gt;Untitled Document&lt;/title&gt;<br />&lt;script type=&quot;text/javascript&quot; src=&quot;colors.js&quot;&gt;&lt;/script&gt;<br />&lt;script type=&quot;text/javascript&quot;&gt;<br />function ini() {<br />var divs = document.getElementsByTagName(&#8217;div&#8217;);<br />&nbsp; for(var i = 0; i &lt; divs.length; i++) {<br />&nbsp;alert(divs[i].style.backgroundColor+&#8217; &lt;=&gt; &#8216;+invertColor(divs[i].style.backgroundColor));<br />&nbsp;divs[i].style.color = invertColor(divs[i].style.backgroundColor);<br />&nbsp;}<br />}<br />&lt;/script&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />.box {<br />width:300px;<br />margin:2px auto;<br />font-weight:bold; <br />font-size:40px;<br />text-align:center;<br />padding:5px;<br />}<br />&lt;/style&gt;<br />&lt;/head&gt;
<p>&lt;body onload=&quot;ini()&quot;&gt;<br />&lt;div style=&quot;background-color:#333;&quot; class=&quot;box&quot;&gt;texto na cor oposta&lt;/div&gt;<br />&lt;div style=&quot;background-color:#FFFF00;&quot; class=&quot;box&quot;&gt;texto na cor oposta&lt;/div&gt;<br />&lt;div style=&quot;background-color:rgb(0,200,0);&quot; class=&quot;box&quot;&gt;texto na cor oposta&lt;/div&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</p>
</div>
	<p>É isso aí. Espero que seja útil para voc&ecirc;.</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/01/19/achando-a-cor-oposta/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Mostrando os  posts do seu blog em seu website</title>
		<link>http://cauguanabara.blogsome.com/2007/01/01/mostrando-os-posts-do-seu-blog-em-seu-website/</link>
		<comments>http://cauguanabara.blogsome.com/2007/01/01/mostrando-os-posts-do-seu-blog-em-seu-website/#comments</comments>
		<pubDate>Mon, 01 Jan 2007 04:40:19 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>PHP</category>
	<category>Tutoriais</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2007/01/01/mostrando-os-posts-do-seu-blog-em-seu-website/</guid>
		<description><![CDATA[	Tem tempo que n&atilde;o escrevo nada por aqui&#8230; Bem, fim de ano é sempre uma confus&atilde;o, né? Mas para coroar um ano produtivo estou aqui, escrevendo em pleno 31 de dezembro!
	Desde que comecei a blogar (já descobri que trata-se de um vício), tinha vontade de mostrar links para os últimos posts do blog no meu [...]]]></description>
			<content:encoded><![CDATA[	<p>Tem tempo que n&atilde;o escrevo nada por aqui&#8230; Bem, fim de ano é sempre uma confus&atilde;o, né? Mas para coroar um ano produtivo estou aqui, escrevendo em pleno 31 de dezembro!</p>
	<p>Desde que comecei a blogar (já descobri que trata-se de um vício), tinha vontade de mostrar links para os últimos posts do blog no meu site. Procurei no forum do blogsome e pela rede, mas n&atilde;o achei nada interessante (sei que deve haver algo). Enfim, resolvi fazer meu próprio script, mas como acessar os dados num banco de dados que n&atilde;o me dá acesso? Quando achei a solu&ccedil;&atilde;o me senti até um pouco burro. Claro, os feeds RSS. Lá está o conteúdo que eu queria e bem acessível (sem comentários). Vamos por partes, como faria Jack.</p>
<a id="more-22"></a>
<p>O script deve mostrar uma rela&ccedil;&atilde;o de links como no próprio blog, mas há certas funcionalidades no blog que devem ser reproduzidas aqui: </p>
	<ul>
<li>Definir um tamanho máximo para o título, sem dividir palavras.</li>
	<li>Definir um número máximo de links na lista.</li>
	<li>Definir se o link abre na mesma ou em outra janela.</li>
	<li>Poder apresentar essa lista de links de várias formas.</li>
	<li>Poder definir a codifica&ccedil;&atilde;o do resultado (ISO, UTF, etc.).</li>
	<li>Poder usar em qualquer blog WordPress (e outros?) </li>
</ul>
	<p>Tudo isso vai ser definido através de valores enviados via POST/GET (para usar com ajax) ou em variáveis declaradas antes de incluir o arquivo (para sistemas em PHP). No trecho abaixo vamos procurar por esses valores nos dois caminhos citados acima: em variáveis nomeadas e em $_REQUEST (POST + GET + COOKIE): </p>
	<div class="codigo">/* variáveis de configura&ccedil;&atilde;o */</p>
	<p>// codifica&ccedil;&atilde;o - padr&atilde;o: &#8216;ISO-8859-1&#8242;<br />$charset = !empty($charset) ? $charset : <br />(empty($_REQUEST[&#8217;charset&#8217;]) ? &#8216;ISO-8859-1&#8242; : $_REQUEST[&#8217;charset&#8217;]);</p>
	<p>// target para os links - padr&atilde;o: &#8216;_self&#8217;<br />$target = !empty($target) ? $target : <br />(empty($_REQUEST[&#8217;target&#8217;]) ? &#8216;_self&#8217; : $_REQUEST[&#8217;target&#8217;]);</p>
	<p>// tag de abertura - padr&atilde;o: &#8216;&#8217;<br />$oarround = !empty($around) ? &#8216;&lt;&#8217;.$around.&#8217;&gt;&#8217; : <br />(empty($_REQUEST[&#8217;arround&#8217;]) ? &#8216;&#8217; : &#8216;&lt;&#8217;.$_REQUEST[&#8217;arround&#8217;].&#8217;&gt;&#8217;);</p>
	<p>// tag de fechamento - padr&atilde;o: &#8216;&#8217;<br />$carround = !empty($around) ? &#8216;&lt;/&#8217;.$around.&#8217;&gt;&#8217; : <br />(empty($_REQUEST[&#8217;arround&#8217;]) ? &#8216;&#8217; : &#8216;&lt;/&#8217;.$_REQUEST[&#8217;arround&#8217;].&#8217;&gt;&#8217;);</p>
	<p>// limite de links na lista - padr&atilde;o: 0 (sem limite) <br />$limit = !empty($limit) ? $limit : <br />(empty($_REQUEST[&#8217;limit&#8217;]) ? 0 : (int)$_REQUEST[&#8217;limit&#8217;]);</p>
	<p>// limite de caracteres no link - padr&atilde;o: 0 (sem limite) <br />$maxchars = !empty($maxchars) ? $maxchars : <br />(empty($_REQUEST[&#8217;maxchars&#8217;]) ? 0 : (int)$_REQUEST[&#8217;maxchars&#8217;]);</p>
	<p>// URL do blog - obrigatório <br />$wp_url = !empty($blog) ? $blog : <br />(empty($_REQUEST[&#8217;blog&#8217;]) ? false : $_REQUEST[&#8217;blog&#8217;]);</div>
	<p>O sistema vai trabalhar com o feed, portanto precisamos transformar a URL do blog de forma que aponte para o XML que contém o RSS. No WordPress, basta acrescentar a string &#8216;/feed/&#8217; no final da URL. &#8216;http://seublog.wordpress.com&#8217; vira &#8216;http://seublog.wordpress.com/feed/&#8217; e pronto, temos todo o conteúdo em RSS.<br />Talvez esse sistema possa ser usado com outros servidores de weblogs apenas mudando o trecho abaixo&#8230; </p>
	<div class="codigo">// Se a URL enviada aponta para um XML,<br />// deixaremos ela como está, sen&atilde;o colocamos o &#8216;/feed/&#8217;.<br />// Se a URL enviada já é do feed, n&atilde;o haverá erro. <br />if($wp_url &amp;&amp; preg_match(&quot;/^[^\n]+$/&quot;,$wp_url) &amp;&amp; !preg_match(&quot;/\.xml$/&quot;,$wp_url)) <br />$wp_url = preg_replace(&quot;/(\/feed)?\/*$/&quot;, &quot;&quot;, $wp_url).&quot;/feed/&quot;;</div>
	<p>Faremos agora uma fun&ccedil;&atilde;ozinha para reduzir os títulos dos posts, como acontece no WordPress, para manter um padr&atilde;o de tamanho na lista de links. O caso é que n&atilde;o basta usar substr(). N&atilde;o queremos cortar palavras&#8230;.</p>
	<div class="codigo">// Recebe uma string e um inteiro representando<br />// o limite máximo de caracteres na string de retorno.<br />// Se a string de entrada excede o limite, palavras<br />// s&atilde;o retiradas do final até que ela atinja o tamanho<br />// esperado. Ent&atilde;o ela é retornada, seguida de &#8216;&#8230;&#8217; <br />function truncate($str, $lim) {<br />$ret = &quot;&quot;;<br />$arr = preg_split(&quot;/\s+/&quot;,$str);<br />&nbsp;foreach($arr as $word) {<br />&nbsp;$old = trim($ret); <br />&nbsp;$ret .= &quot; $word&quot;;<br />&nbsp;&nbsp;if($lim &gt; 0 &amp;&amp; strlen(trim($ret)) &gt;= $lim) return &quot;$old&#8230;&quot;;<br />&nbsp;}<br />return $str;<br />}</div>
	<p>Precisamos agora de um sisteminha para ler o conteúdo que está em um arquivo XML e interpretá-lo. Essa será a fun&ccedil;&atilde;o principal e já temos tudo que iremos precisar para que ela funcione. </p>
	<p>Sempre que preciso ler um XML acabo baixando um script pronto e usando sem entender direito como ele trabalha&#8230; mas dessa vez fiz diferente. Incrível a economia de código que esse pequeno esfor&ccedil;o proporcionou. Bem, segue a fun&ccedil;&atilde;o, toda comentada: </p>
	<div class="codigo">// retorna uma string contendo uma lista de links para<br />// os posts recentes do blog indicado<br />function getBlog($xml = false) {<br />// traz as var. de configura&ccedil;&atilde;o<br />global $charset, $target, $oarround, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$carround, $limit, $maxchars;<br />// $xml pode ser uma URL ou um XML completo<br />$data = (preg_match(&quot;/&lt;\?xml/&quot;,$xml) || !$xml) ? <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$xml : join('&#8217;,file($xml));<br />&nbsp;&nbsp;if(!$data) return &#8216;Erro na leitura do XML&#8217;;<br />// eliminando espa&ccedil;os entre tags ou<br />// em tags com conteúdos vazios<br />$data = preg_replace(&quot;/&gt;[\s\r\n\t]*&lt;/&quot;, &quot;&gt;&lt;&quot;, $data, -1);<br />$items = &quot;&quot;; // string de retorno<br />$vals = array(); // vai receber o conteúdo do XML <br />// vai receber as refer&ecirc;ncias para usar $vals<br />$index = array(); <br />// cria o parser na codifica&ccedil;&atilde;o definida<br />$parser = xml_parser_create($charset);<br />// evita problemas&#8230;<br />xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $charset);<br />xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);<br />// transfere o conteúdo para o array $vals, colocando<br />// uma refer&ecirc;ncia dos índices em $index<br />if(!@xml_parse_into_struct($parser, $data, &amp;$vals, &amp;$index)) <br />return &quot;Erro na estrutura do XML&quot;;<br />xml_parser_free($parser); <br />// for a partir de 1, para excluir o título do blog.<br />// A 1&ordf; ocorr&ecirc;ncia de uma tag TITLE é como filha de <br />// CHANNEL, mas só nos interessa TITLE se for filha <br />// de ITEM. Como CHANNEL só pode ter uma tag TITLE,<br />// o método de come&ccedil;ar o loop do 1 funcionou bem.<br />for($i = 1; $i &lt; count($index[&#8217;TITLE&#8217;]); $i++) {<br />// título<br />$f_title = $vals[$index[&#8217;TITLE&#8217;][$i]][&#8217;value&#8217;]; <br />// título reduzido<br />$f_trunc = truncate($f_title, $maxchars); <br />// URL do link<br />$f_link = $vals[$index[&#8217;LINK&#8217;][$i]][&#8217;value&#8217;]; <br />// alimenta $items com um link completo<br />$items .= $oarround.&#8217;&lt;a href=&quot;&#8217;.$f_link.&#8217;&quot; target=&quot;&#8217;.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$target.&#8217;&quot; title=&quot;&#8217;.$f_title.&#8217;&quot;&gt;&#8217;.$f_trunc.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8217;&lt;/a&gt;&#8217;.$carround.&#8217; &#8216;;<br />&nbsp;&nbsp;// interrompe se o limite foi atingido<br />&nbsp;&nbsp;if($limit &gt; 0 &amp;&amp; $i &gt;= $limit) break;<br />}<br />return $items;<br />}</div>
	<p>Restou apenas executar isso tudo. É, essa fun&ccedil;&atilde;o n&atilde;o vai ser chamada de algum lugar, o script deve se executar ao ser incluído ou chamado via XMLHttpRequest.</p>
	<div class="codigo">print $wp_url ? getBlog($wp_url) : <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Informe a URL do blog&quot;; </div>
	<p>Agora basta juntar isso tudo e está feito! eu chamei de wp-posts.php, mas voc&ecirc; pode chamá-lo como quiser. </p>
	<p>Veja dois exemplos de como usar o sistema:</p>
	<div class="codigo">// Javascript - assumindo que $(&#8217;recentposts&#8217;) aponta <br />// para um &lt;UL&gt; e que ajax é nosso objeto Ajax<br />function getPosts() {<br />$(&#8217;recentposts&#8217;).innerHTML = &#8216;&lt;li&gt;Carregando&#8230;&lt;/li&gt;&#8217;;<br />var ajx = new ajax();<br />ajx.sendLoad(&quot;../php/wp-posts.php?blog=blog.xml&amp;arround=li&amp;maxchars=20&amp;charset=UTF-8&amp;limit=12&quot;, null, <br />//ajx.sendLoad(&quot;http://site.com/wp-posts.php?&quot;+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;blog=http://blog.blogsome.com&quot;+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&amp;arround=li&quot;+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&amp;maxchars=20&quot;+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&amp;charset=UTF-8&quot;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function(txt) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8217;recentposts&#8217;).innerHTML = txt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />} </p>
	<p>&lt;?php<br />// PHP<br />$blog = &#8216;http://blog.blogsome.com/&#8217;;<br />$maxchars = 20;<br />$limit = 6;<br />$around = &#8216;li&#8217;;<br />include &quot;wp-posts.php&quot;;<br />?&gt;</div>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2007/01/01/mostrando-os-posts-do-seu-blog-em-seu-website/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Acessibilidade em interfaces web</title>
		<link>http://cauguanabara.blogsome.com/2006/12/18/acessibilidade-em-interfaces-web/</link>
		<comments>http://cauguanabara.blogsome.com/2006/12/18/acessibilidade-em-interfaces-web/#comments</comments>
		<pubDate>Tue, 19 Dec 2006 01:44:03 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Web 2.0</category>
		<guid>http://cauguanabara.blogsome.com/2006/12/18/acessibilidade-em-interfaces-web/</guid>
		<description><![CDATA[	Este é um tema t&atilde;o falado ultimamente, que é difícil achar alguém que n&atilde;o conhece (de nome) a tal da acessibilidade. Outro dia vi na TV um anúncio (n&atilde;o lembro de que entidade) ensinando ao público o que é acessibilidade. Mas ainda é fácil perceber que a preocupa&ccedil;&atilde;o em fornecer acesso &agrave; pessoas com algum [...]]]></description>
			<content:encoded><![CDATA[	<p>Este é um tema t&atilde;o falado ultimamente, que é difícil achar alguém que n&atilde;o conhece (de nome) a tal da acessibilidade. Outro dia vi na TV um anúncio (n&atilde;o lembro de que entidade) ensinando ao público o que é acessibilidade. Mas ainda é fácil perceber que a preocupa&ccedil;&atilde;o em fornecer acesso &agrave; pessoas com algum tipo de defici&ecirc;ncia (<a href="http://www.acessibilidade.org.br/ibge.htm" target="_blank">que n&atilde;o s&atilde;o poucas</a>) ainda n&atilde;o é algo levado muito a sério. &Agrave;s vezes executar uma a&ccedil;&atilde;o simples torna-se impossível gra&ccedil;as a um pequeno detalhe que poderia ter sido projetado levando em conta as nescessidades dessas pessoas - muitas vezes sem custo adicional. </p>
	<p>Até pouco tempo atrás, eu mesmo nunca tinha pensado a respeito, mas agora parei para fazer isso e percebi o quanto é importante - além de ser respeitoso e educado com aqueles que tem alguma dificuldade e que tem (ao menos teoricamente) o direito de acesso a tudo que é público. Mas como traduzir esses conceitos de <a href="http://www.serpro.gov.br/acessibilidade/oque.php" target="_blank">acessibilidade</a> para um website? </p>
<a id="more-21"></a>
<p>Bem, no site do <a title="Serviço Federal de Processamento de Dados" href="http://www.serpro.gov.br/acessibilidade/">SERPRO</a> há alguma informa&ccedil;&atilde;o, uma <a href="http://www.imasters.com.br/artigo/3134/acessibilidade/acessibilidade_web/">matéria bem legal</a> no <a href="http://www.imasters.com.br/" target="_blank">imasters</a> e muita coisa disponível na rede. Se fizer uma busca em ingl&ecirc;s ent&atilde;o, é uma festa e a raz&atilde;o é simples: estamos falando de um dos pilares do movimento denominado &#8216;web 2.0&#8242;. Mas, apesar de todos já sabermos disso, há muito poucos sites totalmente acessíveis na web. </p>
	<p class="negrito">O que é importante para um website ser acessível?</p>
	<p>Um site acessível é aquele que pode ser utilizado nas mais diversas situa&ccedil;&otilde;es e apresenta certas características especiais. Apresento abaixo uma lista dos itens considerados importantes</p>
	<ol>
<li>imagens, gráficos, audio e vídeo devem ter descri&ccedil;&otilde;es alternativas</li>
	<li>o texto deve ter contraste com o fundo e poder ser ampliado</li>
	<li>deve poder ser visto e entendido sem as imagens </li>
	<li>links e elementos de formulário devem estar dispostos com lógica</li>
	<li>deve poder ser visto e entendido sem o CSS</li>
	<li>o conteúdo de tabelas deve fazer sentido lido linha a linha</li>
	<li>deve poder ser usado sem javascript</li>
</ol>
	<p>Bem, algumas das regras acima s&atilde;o fáceis e n&atilde;o s&atilde;o usadas apenas por simples desconhecimento, acredito. Outras nem tanto&#8230; vamos uma a uma.</p>
	<p class="negrito">Imagens, gráficos, audio e vídeo devem ter descri&ccedil;&otilde;es alternativas</p>
	<p>Fácil. Basta n&atilde;o esquecer de preencher o atributo &#8216;alt&#8217; nas imagens e ter legendas para os vídeos e audios (como um link ao lado, que leva a um texto descritivo). As imagens e a nescessidade do alt s&atilde;o muito faladas e todos já sabemos, só n&atilde;o sabíamos que o motivo é a acessibilidade. Pois é, o alt n&atilde;o serve apenas para os casos em que as imagens n&atilde;o carregam, mas também para os que n&atilde;o podem v&ecirc;-las.</p>
	<p>Com o advento do atributo &#8216;title&#8217;, restou uma certa confus&atilde;o quanto &agrave; tag img. ALT ou TITLE - qual usar? pra que serve cada um? Bem, o &#8216;title&#8217; nas imagens tem a mesma finalidade que em qualquer outra tag: exibir um texto descritivo. Já o &#8216;alt&#8217; está associado &agrave; acessibilidade. Se ambos existirem, ao parar o mouse sobre a imagem o &#8216;title&#8217; aparece, mas se a imagem n&atilde;o puder ser exibida, o &#8216;alt&#8217; é que será mostrado. </p>
	<p class="negrito">O texto deve ter contraste com o fundo e poder ser ampliado</p>
	<p>O contraste é uma exig&ecirc;ncia para satisfazer aos portadores de daltonismo, que tem dificuldade para reconhecer as cores, especialmente as combina&ccedil;&otilde;es de cores opostas verde-vermelho e azul-amarelo. </p>
	<p>Quanto a poder ser ampliado, estamos falando do<a href="http://www.maujor.com/tutorial/medidascss.php" target="_blank"> tipo de medida</a> escolhido para as fontes na página. Como sabemos, o usuário pode ampliar ou reduzir o tamanho do texto exibido na página, para os casos de miopia ou outra defici&ecirc;ncia visual parcial - a menos que na folha de estilos do site o tamanho das fontes esteja definido em medidas absolutas, como pixels, pontos ou milímetros, por exemplo. A medida em pixels, na verdade é classificada como relativa, mas a sua relatividade se refere &agrave; defini&ccedil;&atilde;o de vídeo, n&atilde;o ao tamanho de fonte herdado - por isso, para a nossa finalidade, n&atilde;o funciona. </p>
	<p>A solu&ccedil;&atilde;o é se basear na folha de estilos do navegador, usando as medidas relativas porcentagem, em e ex. Esses tr&ecirc;s medidas trabalham em cima do tamanho herdado de fonte - e poder&atilde;o ser modificados se o usuário precisar.</p>
	<p class="negrito">O site deve poder ser visto e entendido sem as imagens </p>
	<p>Muitos usuários com defici&ecirc;ncia visual usam browsers que l&ecirc;em apenas o texto ou outros dispositivos que ignoram as imagens, por isso nunca escreva nas imagens - escreva em texto - e se precisar fazer isso, capriche na descri&ccedil;&atilde;o.</p>
	<p>No caso de estar usando um sistema anti spam tipo captcha (&quot;digite aqui a palavra que voc&ecirc; v&ecirc; na imagem ao lado&#8230;&quot;), onde n&atilde;o se pode usar o atributo alt ou title, n&atilde;o esque&ccedil;a de disponibilizar a mesma palavra em forma de áudio, para deficientes visuais. </p>
	<p class="negrito">Os links e elementos de formulário devem estar dispostos com lógica</p>
	<p>Há pessoas que por algum motivo n&atilde;o podem usar o mouse e v&atilde;o navegar pelo seu site através do teclado. Aqui nos deparamos com a necessidade da sem&acirc;ntica correta. Espera-se que os itens clicáveis da sua interface sejam apenas links ou elementos de formulário, que s&atilde;o acessíveis com o uso de Tab, Shift + Tab e Enter.</p>
	<p>Se por algum motivo a disposi&ccedil;&atilde;o dos links em seu HTML - na ordem em que foram escritos, n&atilde;o na ordem em que aparecem na página - n&atilde;o seguirem uma seq&uuml;&ecirc;ncia lógica, use o atributo <a href="http://www.w3.org/TR/html4/interact/forms.html#adef-tabindex" target="_blank">&#8216;tabindex&#8217;</a> para definir a ordem de acesso. </p>
	<p class="negrito">O site deve poder ser visto e entendido sem o CSS</p>
	<p>Pelo mesmo motivo citado no item acima, em certos casos o CSS é dispensável, ent&atilde;o, simplesmente n&atilde;o é renderizado. Sabemos que a seq&uuml;&ecirc;ncia em que os elementos s&atilde;o escritos no documento HTML pode n&atilde;o ter nada a ver com a forma que s&atilde;o exibidos, com layers e floats e tudo mais que o CSS oferece. Apesar disso, é preciso que o texto tenha sentido na seq&uuml;&ecirc;ncia mesma em que aparece no HTML, pois esses dispositivos l&ecirc;em apenas o texto em sua ordem original.</p>
	<p class="negrito">O conteúdo das tabelas deve fazer sentido lido linha a linha </p>
	<p>No tipo de leitura citado acima (do documento HTML e n&atilde;o da tela), as tabelas ser&atilde;o lidas como est&atilde;o escritas, uma TD depois da outra formando uma linha e uma TR depois da outra. Ou seja, os dados ser&atilde;o lidos da esquerda para a direita, TD por TD e de cima para baixo, TR por TR. Portanto se o conteúdo dessa tabela só faz sentido quando interpretado em colunas, ele aparecerá &#8216;truncado&#8217;, misturado e impossível de ser compreendido. </p>
	<p class="negrito">O site deve poder ser usado sem javascript</p>
	<p>O Javascript, mais que o CSS, é passível de ser desabilitado. Muita gente faz isso por simples quest&otilde;es de seguran&ccedil;a. Outros pelos mesmos motivos dos itens acima. Aqui chegamos a um tema ainda pouco comentado mas de vital import&acirc;ncia: <a href="http://www.imasters.com.br/artigo/4298/javascript/tudo_sobre_javascript_nao-obstrutivo_-_parte_01/" target="_blank">Javascript n&atilde;o-obstrutivo</a>. O que é isso?</p>
	<p>É simples de entender: sua forma de usar o Javascript n&atilde;o deve impedir a página de funcionar caso o mesmo esteja desligado. Por exemplo, sabemos que para estarmos semanticamente corretos, devemos construir nossos menus com elementos &lt;A&gt;, mas um link assim n&atilde;o serve pra nada sem o Javascript:</p>
	<div class="codigo">&lt;a href=&quot;javascript://&quot; onclick=&quot;_go(&#8217;index.html&#8217;);&quot;&gt;link&lt;/a&gt; </div>
	<p>Já este pode ser usado também sem ele:</p>
	<div class="codigo">&lt;a href=&quot;index.html&quot; onclick=&quot;_go(&#8217;index.html&#8217;); return false;&quot;&gt;link&lt;/a&gt;</div>
	<p>No segundo exemplo, executamos a fun&ccedil;&atilde;o e desabilitamos o href com a express&atilde;o &#8216;return false;&#8217;. Caso n&atilde;o haja JS, o link e irá funcionar normalmente. Outra situa&ccedil;&atilde;o é quando, através do menu de contexto, usamos a op&ccedil;&atilde;o &#8216;Copiar link&#8217; ou &#8216;Copiar atalho&#8217;. No exemplo acima, enviaríamos para a área de transfer&ecirc;ncia a string &#8216;javascript://&#8217;, que de nada serviria. O mesmo se aplica para o comando de abrir o link em uma nova janela.</p>
	<p>Quando seu javascript for responsável por mostrar alguma informa&ccedil;&atilde;o relevante, use a tag noscript para explicar o conteúdo que n&atilde;o p&ocirc;de ser exibido. Aqui nos deparamos com um problema: noscript costuma causar problemas de valida&ccedil;&atilde;o como XHTML 1.0 e precisamos decidir o que é mais importante, validar ou dar acesso.</p>
	<p>Se há áreas que só aparecem via javascript, com mudan&ccedil;as din&acirc;micas no CSS, crie essas áreas visíveis e as esconda no onload da página. Assim, se n&atilde;o houver Javascript, elas estar&atilde;o visíveis (e acessíveis). </p>
	<p>O t&atilde;o utilizado &#8216;menu de salto&#8217; (um select com fun&ccedil;&atilde;o definida no evento onchange) é também um obstáculo para quem navega pelo teclado, pois ao mudar o campo, o onchange é acionado e o usuário que n&atilde;o conhece o uso da combina&ccedil;&atilde;o Alt + seta para abrir o menu, nunca passará do primeiro item - e a grande maioria n&atilde;o conhece. </p>
	<p>Enfim, a falta do Javascript n&atilde;o pode inviabilizar a navega&ccedil;&atilde;o. Leia essa matéria já indicada acima, é uma verdadeira aula sobre <em>non-obtrusive javascript</em>, dividida em 5 episódios: <a href="http://www.imasters.com.br/artigo/4298/javascript/tudo_sobre_javascript_nao-obstrutivo_-_parte_01/" target="_blank">http://www.imasters.com.br/artigo/4298/javascript/tudo_sobre_javascript_nao-obstrutivo_-_parte_01/</a></p>
	<p class="negrito">Outras&#8230;</p>
	<p>Fora isso tudo, n&atilde;o esque&ccedil;a de declarar o idioma em que o conteúdo está escrito, com o atributo <em>lang</em> na tag </p>
	<div class="codigo">&lt;html &#8230; lang=&quot;pt-br&quot;&gt;</div>
e o charset correspondente &agrave; codifica&ccedil;&atilde;o real do documento, com a tag<br />
<div class="codigo">&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot; /&gt;</div>
Siga as especifica&ccedil;&otilde;es da <a href="http://www.w3.org/" target="_blank">w3c</a> e n&atilde;o complique &agrave; toa. Seja direto e use frases e descri&ccedil;&otilde;es simples e de fácil entendimento.
<p>Todas as regras de <a href="http://www.usabilidoido.com.br/afinal_o_que_e_usabilidade.html" target="_blank">usabilidade</a> também s&atilde;o aplicáveis e importantes aqui, como:</p>
	<ul>
<li>O menu principal deve estar acessível de qualquer lugar do site</li>
	<li>Um retorno para a página principal sempre visível</li>
	<li>Abrir conteúdos externos ao site em novas janelas</li>
	<li>Oferecer um mapa do site com links diretos </li>
	<li>Usar textos descritivos nos links, com title </li>
	<li>etc, etc e etc&#8230;</li>
</ul>
	<p class="negrito">Valida&ccedil;&atilde;o</p>
	<p>Existem servi&ccedil;os online para validar a acessibilidade de um website, inclusive um em portugu&ecirc;s, o <a href="http://www.dasilva.org.br/" target="_blank">DaSilva</a>. Veja também o <a href="http://webxact.watchfire.com/" target="_blank">WebXACT</a>e outros <a href="http://www.serpro.gov.br/acessibilidade/g_validacao.php" target="_blank">aqui</a>. Mas já vou avisando: validar totalmente um site é quase impossível quando se usa muito JS/DOM/CSS, mas dá dicas interessantes quanto &agrave;s nossas faltas.</p>
	<p class="negrito">Acessibilidade é uma quest&atilde;o de respeito pelo próximo</p>
	<p>&#8230; além de ser uma exig&ecirc;ncia do novo modelo de internet - aliás, do novo modelo de mundo. </p>
	<p>Web 2.0 sem acessibilidade n&atilde;o rola. Da mesma forma que um supermercado n&atilde;o pode deixar de ter rampas de acesso, o conteúdo de um website n&atilde;o pode estar acessível apenas para um grupo, mesmo que este represente a maioria. </p>
	<p>Além disso, tem gente apostando que a acessibilidade é uma grande oportunidade de negócio, <a href="http://fatorw.com/2005/12/23/sites-acessiveis-oportunidades-de-negocios/">veja por qu&ecirc;</a> . </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/12/18/acessibilidade-em-interfaces-web/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Atalhos de teclado em aplicações web</title>
		<link>http://cauguanabara.blogsome.com/2006/12/13/atalhos-de-teclado-em-aplicacoes-web/</link>
		<comments>http://cauguanabara.blogsome.com/2006/12/13/atalhos-de-teclado-em-aplicacoes-web/#comments</comments>
		<pubDate>Wed, 13 Dec 2006 20:25:43 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Web 2.0</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2006/12/13/atalhos-de-teclado-em-aplicacoes-web/</guid>
		<description><![CDATA[	As &#8220;hotkeys&#8221; - ou atalhos de teclado - são um recurso muito legal e pouco utilizado em páginas da web. Aliás, pouca gente usa os atalhos em qualquer programa. Na maior parte das vezes o usuário não passa do Ctrl + X/C/V (recortar, copiar e colar). Mas eles são verdadeiros &#8220;atalhos&#8221;, cortando, muitas vezes, grande [...]]]></description>
			<content:encoded><![CDATA[	<p>As &#8220;hotkeys&#8221; - ou atalhos de teclado - são um recurso muito legal e pouco utilizado em páginas da web. Aliás, pouca gente usa os atalhos em qualquer programa. Na maior parte das vezes o usuário não passa do Ctrl + X/C/V (recortar, copiar e colar). Mas eles são verdadeiros &#8220;atalhos&#8221;, cortando, muitas vezes, grande parte do caminho que teríamos que percorrer para chegar ao comando desejado. <br />Além de, dentro dos preceitos da web 2.0, ser um recurso de usabilidade bastante desejável. O Google (símbolo máximo da&nbsp;tal de web 2.0), por exemplo, oferece alguns atalhos para comandos na interface do Gmail. </p>
<a id="more-20"></a></p>
	<p>O HTML nos oferece uma forma nativa de fazer isso: a propriedade accesskey. Originalmente aplicável em a, area, button, input, label, legend e textarea, depois foi liberado para todos os elementos renderizáveis. Usa-se então uma tecla (definida em accesskey) combinada com [Alt] ou [Ctrl], dependendo do browser, para mover o foco para o elemento, mas não funciona a contento. Depois, queremos executar comendos Javascript e não apenas mover o foco. </p>
	<p>Construí então um sisteminha para capturar e reconhecer esses eventos, transformando-os em strings facilmente interpretáveis, como &#8220;CTRL+Q&#8221; ou &#8220;SHIFT+CTRL+B&#8221;. Acabei por fazer uma função que retorna um objeto contendo quatro informações: a string em si, o número da tecla pressionada e dois valores boleanos para saber se as teclas [Ctrl] e [Shift] estão pressionadas. O usuário deve então criar uma função para receber e interpretar esse objeto, executando as ações relacionadas. Vamos ao código.</p>
	<p>Começamos criando duas variáveis: isIE, que diz se estamos no IE, e hotKeysOk, que é inicializada com o valor false e irá nos dizer se há uma função definida para executar os comandos. </p>
	<div class=codigo>isIE = (/msie/i.test(navigator.userAgent) &amp;&amp; document.all);<br />hotKeysOk = false;</div>
	<p>Bem, vamos então à função getHotKeys. É ela que detecta a ação de pressionar uma ou mais teclas e lê a combinação, transformando em texto e executando a função do usuário - que veremos adiante. Ao executar a função do usuário, enviará como parâmetro um objeto com a seguinte estrutura:</p>
	<div class=codigo>{<br />&#8220;str&#8221;: &#8220;string de retorno (como CTRL+I)&#8221;, // string <br />&#8220;code&#8221;: &#8220;número da tecla (keyCode)&#8221;, // nunber <br />&#8220;shift&#8221;: &#8220;se true, Shift esta pressionado&#8221;, // boolean <br />&#8220;ctrl&#8221;: &#8220;se true, Ctrl esta pressionado&#8221; // boolean<br />}</div>
	<p>A função em si: </p>
	<div class=codigo>function getHotKey(e) {<br />// capturando a keycode e as teclas Shift e Ctrl<br />var key = isIE ? event.keyCode : e.charCode;<br />var ctrl = isIE ? event.ctrlKey : e.ctrlKey;<br />var shif = isIE ? event.shiftKey : e.shiftKey;<br />var ret = &#8216;&#8217;;<br />&nbsp;&nbsp;// elimina caracteres acentuados e outros<br />&nbsp;&nbsp;if(key &gt; 126) return true;<br />&nbsp;&nbsp;if(shif) ret += &#8216;SHIFT+&#8217;;<br />&nbsp;&nbsp;if(ctrl) {<br />&nbsp;&nbsp;ret += &#8216;CTRL+&#8217;;<br />&nbsp;&nbsp;&nbsp;&nbsp;// se Ctrl está pressionado,<br />&nbsp;&nbsp;&nbsp;&nbsp;// o IE muda o keycode&#8230;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(isIE) key += 96;<br />&nbsp;&nbsp;}</p>
	<p>// recuperando o caracter literal<br />ret += String.fromCharCode(key).toUpperCase();</p>
	<p>&nbsp;&nbsp;// retirando o &#8216;SHIFT+&#8217; da string em <br />&nbsp;&nbsp;// caso de caracteres especiais<br />&nbsp;&nbsp;var er = /[\&#8221;!@#\$%¨&amp;\*\(\)\_+\^`\{\}\|\:\?]/;<br />&nbsp;&nbsp;if(er.test(ret.charAt(ret.length - 1))) <br />&nbsp;&nbsp;&nbsp;&nbsp;ret = ret.replace(/SHIFT\+/,'&#8217;);<br />&nbsp;&nbsp;// se por algum motivo a string<br />&nbsp;&nbsp;// não estiver correta, esvazia<br />&nbsp;&nbsp;if(!(/^(SHIFT\+)?(CTRL\+)?.$/.test(ret))) ret = &#8216;&#8217;;<br />&nbsp;&nbsp;// se a função do usuário está setada, executa<br />&nbsp;&nbsp;if(hotKeysOk) <br />&nbsp;&nbsp;&nbsp;&nbsp;execHotKeys({ &#8217;str&#8217;: ret, &#8216;code&#8217;: key, &#8216;upper&#8217;: shif, &#8216;ctrl&#8217;: ctrl });<br />} </div>
	<p>Ok, a função está toda comentada, mas e a execHotKeys? cadê? <br />Pois é, a função abaixo foi o meu modo de resolver isso. Crio a execHotKeys on-the-fly, a partir de uma função enviada como parâmetro à setHotKeysFunction. Ao fazer isso, podemos setar hotKeysOk para true. A função de interpretação já existe e a getHotKeys já sabe o seu nome: execHotKeys. </p>
	<div class=codigo>function setHotKeysFunction(func) {<br />&nbsp;&nbsp;if(!func || typeof(func) != &#8216;function&#8217;) <br />&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />&nbsp;&nbsp;else { hotKeysOk = true; execHotKeys = func; }<br />}</div>
	<p>Só faltou agora a função para interpretar os comandos de teclado e executá-los, a mesma recebida como parâmetro na função aí em cima. Essa funçãodeve estar pronta para receber e interpretar o objeto recebido. No nosso exemplo, ela apenas dá um alert mostrando os dados do objeto, mas podemos criar várias estratégias para reconhecer os comandos a partir dessas informações enviadas à função.<br />Esta é a função que está funcionando na página de exemplo: </p>
	<div class=codigo>// função do usuário<br />function myHotKeys(keyInfo) {<br />alert(&#8217;str: &#8216;+keyInfo.str+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8217;\ncode: &#8216;+keyInfo.code+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8217;\nupper: &#8216;+keyInfo.upper+<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8217;\nctrl: &#8216;+keyInfo.ctrl);<br />} </div>
	<p>Mas poderíamos fazer algo como isso: </p>
	<div class=codigo>// função do usuário<br />function myHotKeys(keyInfo) {<br />&nbsp;&nbsp;switch(keyInfo.str) {<br />&nbsp;&nbsp;case &#8220;CTRL+G&#8221;: /* comandos */ break;<br />&nbsp;&nbsp;case &#8220;SHIFT+CTRL+B&#8221;: /* comandos */ break;<br />&nbsp;&nbsp;case &#8220;A&#8221;: /* comandos */ break;<br />&nbsp;&nbsp;case &#8220;%&#8221;: /* comandos */ break;<br />&nbsp;&nbsp;case &#8220;5&#8243;: /* comandos */ break;<br />&nbsp;&nbsp;}<br />} </div>
	<p>Tudo bem, mas e para fazer isso funcionar? <br />Basta adicionar as duas linhas abaixo, definindo comportamentos para dois eventos na nossa janela: ao carregar a página (window.onload) definimos a nossa função myHotKeys (que irá executar os comandos) com setHotKeysFunction e ao pressionar uma tecla (document.onkeypress), chamamos a getHotKey que fará o resto do trabalho.</p>
	<div class=codigo>window.onload = function() { <br />setHotKeysFunction(myHotKeys); <br />}<br />document.onkeypress = getHotKey; </div>
	<p><strong>Atenção</strong>, a propriedade str no objeto enviado à sua função irá retratar a combinação de teclas como mostrado abaixo.</p>
	<ul>
	<li>A letras sempre são mostradas em maiúsculas, o que diferencia das minúsculas é a presença do SHIFT. </li>
	<li>Os caracteres não alfabéticos suprimem a substring SHIFT+ da string de retorno, mostrando apenas o próprio caracter</li>
	<li>Caracteres não alfabéticos não funcionam em combinação com Ctrl. </li>
	<li>Caracteres acentuados, como &#8220;Ç&#8221;, não são aceitos.</li>
	<li>As combinações que correspondem a atalhos do navegador, como Ctrl + A devem ser evitadas. O que acontece:
	<ul>
	<li>no IE são desabilitados</li>
	<li>na família Mozilla não impedem a execução da funcionalidade correspondente - as duas coisas acontecem </li>
</ul>
</li>
</ul>
	<p>Tabela com alguns exemplos: </p>
	<table cellSpacing=0 cellPadding=4 width=219 border=1>
	<tbody>
	<tr>
	<td align=middle>a</td>
	<td align=middle>A</td>
</tr>
	<tr>
	<td align=middle>A</td>
	<td align=middle>SHIFT+A</td>
</tr>
	<tr>
	<td align=middle>b</td>
	<td align=middle>B</td>
</tr>
	<tr>
	<td align=middle>Ctrl + t </td>
	<td align=middle>CTRL+T</td>
</tr>
	<tr>
	<td align=middle>Ctrl + T </td>
	<td align=middle>SHIFT+CTRL+T</td>
</tr>
	<tr>
	<td align=middle>$</td>
	<td align=middle>$</td>
</tr>
	<tr>
	<td align=middle>*</td>
	<td align=middle>*</td>
</tr>
	<tr>
	<td align=middle>7</td>
	<td align=middle>7</td>
</tr>
</tbody>
</table>
	<p><a href="http://cauguanabara.jsbrasil.com/scripts/hotkeys.html" target=_blank>Veja aqui uma página de exemplo</a></p>
	<p>É isso aí, abraço, Cau. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/12/13/atalhos-de-teclado-em-aplicacoes-web/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Novo site, com blog de cara nova</title>
		<link>http://cauguanabara.blogsome.com/2006/12/09/novo-site-com-blog-de-cara-nova/</link>
		<comments>http://cauguanabara.blogsome.com/2006/12/09/novo-site-com-blog-de-cara-nova/#comments</comments>
		<pubDate>Sat, 09 Dec 2006 23:52:09 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
		<guid>http://cauguanabara.blogsome.com/2006/12/09/novo-site-com-blog-de-cara-nova/</guid>
		<description><![CDATA[	Passei uns dias criando um novo site fazendo as mudan&ccedil;as que voc&ecirc; está vendo aqui no blog - queria que o blog fosse uma parte do meu site, vestido a caráter. Deu trabalho, mas ficou bem legal.O blog n&atilde;o está no meu domínio mas é parte do meu site, compartilha da mesma identidade visual e [...]]]></description>
			<content:encoded><![CDATA[	<p>Passei uns dias criando um novo <a href="http://cauguanabara.jsbrasil.com/" target="_self">site</a> fazendo as mudan&ccedil;as que voc&ecirc; está vendo aqui no blog - queria que o blog fosse uma parte do meu site, vestido a caráter. Deu trabalho, mas ficou bem legal.<br />O blog n&atilde;o está no meu domínio mas é parte do meu site, compartilha da mesma identidade visual e achei que isso funciona bem. </p>
	<p>Nunca quis ter um site pessoal, mas acabava sempre fazendo &quot;algo&quot; e colocando no ar. Nunca eram muito visitados (gra&ccedil;as a Deus) e, invariavelmente, eu os odiava na semana seguinte. Dessa vez acho que vai ser diferente, pois n&atilde;o estou pensando em um site apenas profissional, mas em um espa&ccedil;o para divulgar minhas idéias e tudo mais que me der na telha. </p>
<a id="more-17"></a>
<p><strong>No site &#8230;</strong></p>
	<p>&#8230; dá pra ter uma idéia da minha história e do meu trabalho, pra entrar em contato comigo, etc., mas o mais importante é um <a href="http://cauguanabara.jsbrasil.com/html/tutorial.html" target="_self">tutorial de PHP 4</a> que disponibilizei para consultas. Essa apostila foi criada para um curso que nunca se realizou, inclusive já publiquei no blog um capítulo dela. Prometo mudar a formata&ccedil;&atilde;o para algo mais a ver com o site. </p>
	<p>Além disso, em breve haverá um &quot;Guestbook&quot;, um modo para quem chegar poder deixar um comentário, enquanto isso, o blog é o local. </p>
	<p>É isso aí. Abra&ccedil;o, Cau </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/12/09/novo-site-com-blog-de-cara-nova/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Classificando o conteúdo de uma tabela  como num data-grid</title>
		<link>http://cauguanabara.blogsome.com/2006/12/01/classificando-o-conteudo-de-uma-tabela-como-num-data-grid/</link>
		<comments>http://cauguanabara.blogsome.com/2006/12/01/classificando-o-conteudo-de-uma-tabela-como-num-data-grid/#comments</comments>
		<pubDate>Fri, 01 Dec 2006 23:45:32 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2006/12/01/classificando-o-conteudo-de-uma-tabela-como-num-data-grid/</guid>
		<description><![CDATA[	Vou mostrar neste artigo uma fun&ccedil;&atilde;o para reorganizar as linhas de uma tabela a partir dos valores de suas colunas. Tive dúvidas sobre um título que dissesse isso em uma linha, mas achei que a idéia do data-grid ilustraria bem. A idéia é olhar a tabela por suas colunas e, a partir de um click [...]]]></description>
			<content:encoded><![CDATA[	<p>Vou mostrar neste artigo uma fun&ccedil;&atilde;o para reorganizar as linhas de uma tabela a partir dos valores de suas colunas. Tive dúvidas sobre um título que dissesse isso em uma linha, mas achei que a idéia do <em>data-grid</em> ilustraria bem. A idéia é olhar a tabela por suas colunas e, a partir de um click no elemento &lt;th&gt; correspondente, classificar e reorganizar as linhas pelos valores na coluna escolhida.</p>
	<p>Esse script foi criado a partir de um exemplo que consegui na internet há anos, n&atilde;o sei, mas se n&atilde;o me engano foi num site da Microsoft. N&atilde;o havia informa&ccedil;&otilde;es autorais, mas a verdade é que quando digo &quot;criado a partir de&quot; significa que mudei bem a coisa. <br />O legal da fun&ccedil;&atilde;o é que usa propriedades e métodos nativos do elemento &lt;table&gt; e de seus sub elementos, que quase n&atilde;o se v&ecirc; e n&atilde;o s&atilde;o muito utilizados - coisa antiga, da época em que &quot;Dom&quot; era só para quem tinha algum talento especial e &quot;Ajax&quot; n&atilde;o passava de material de limpeza (rsrsrs). </p>
<a id="more-16"></a>
<p>Pois é, mas voltando ao presente, a sem&acirc;ntica nos diz que as tabelas n&atilde;o s&atilde;o para criar estruturas de design, como se usava, mas para exibir dados &quot;tabulares&quot;, aqueles que estamos acostumados a ver em forma de &quot;planilhas&quot;, no Exel por exemplo. E junto com essa idéia, fun&ccedil;&otilde;es específicas foram criadas para que os dados exibidos tivessem alguma mobilidade. Propriedades como Table.rows, Table.cols, Table.tbody, Table.tBodies&#8230; quem usa isso? Bem, eu n&atilde;o. Mas adorei conhec&ecirc;-las.</p>
	<p>A fun&ccedil;&atilde;o sortTable() deve ser definida como uma propriedade do(s) elemento(s) &lt;table&gt; em quest&atilde;o, dessa forma todos os dados estar&atilde;o acessíveis, pois ser&atilde;o membros do mesmo objeto - isso deve acontecer no onload ou num script colocado abaixo do elemento, quando a tabela já existe efetivamente. Um detalhe importante é que precisaremos do também quase esquecido elemento &lt;tbody&gt;, que também possui a propriedade rows. Isso por qu&ecirc; dessa forma delimitamos o conteúdo a ser classificado, excluindo os cabe&ccedil;alhos das colunas - sen&atilde;o ao clicar, o &lt;th&gt; - que também é incluído no objeto rows, entra na dan&ccedil;a e pode ir para em qualquer linha, de acordo com seu texto. <br />A fun&ccedil;&atilde;o l&ecirc; o conteúdo do primeiro tbody da tabela - digo isso por que é lícito usar mais de um tbody em uma mesma tabela. N&atilde;o iria funcionar direito. </p>
	<p>Fazemos um loop pelas rows da tabela, colocando-os em um array, na mesma seq&uuml;&ecirc;ncia. Aí está o &quot;segredo&quot; da classifica&ccedil;&atilde;o: basta usar os métodos sort() e reverse() do objeto Array. Depois de rearrumar o array, refazemos a tabela a partir dele. Veremos que há duas fun&ccedil;&otilde;es necessárias para que sortTable funcione: generateCompareTRs - usada como par&acirc;metro para o método Array.sort - e getColValue, que só aparecerá mais adiante. Veja a fun&ccedil;&atilde;o principal: </p>
	<div class="codigo">function sortTable(iCol) {<br />var oTBody = this.tBodies[0]; // pega o tbody <br />var colDataRows = oTBody.rows; // pega as linhas <br />var oFragment = document.createDocumentFragment(); // será usado para refazer a ordem <br />var aTRs = []; // array para receber as linhas <br />&nbsp;&nbsp;for(var i = 0; i &lt; colDataRows.length; i++) aTRs[i] = colDataRows[i];</p>
	<p>&nbsp;&nbsp;if(this.sortCol == iCol) aTRs.reverse();<br />&nbsp;&nbsp;else aTRs.sort(generateCompareTRs(iCol));</p>
	<p>&nbsp;&nbsp;for (var i=0; i &lt; aTRs.length; i++) oFragment.appendChild(aTRs[i]);</p>
	<p>oTBody.appendChild(oFragment);<br />this.sortCol = iCol;<br />}</div>
	<p>A fun&ccedil;&atilde;o generateCompareTRs() recebe o índice da coluna que servirá como base para a classifica&ccedil;&atilde;o e retorna uma outra fun&ccedil;&atilde;o que será enviada para o método sort. Ela determina, segundo os valores a serem comparados, se a compara&ccedil;&atilde;o será numérica ou baseada em strings e a fun&ccedil;&atilde;o retornada será apropriada para os valores da coluna em quest&atilde;o. </p>
	<div class="codigo">function generateCompareTRs(iCol) {<br />&nbsp;&nbsp;var ret = function(oTR1, oTR2) { <br />&nbsp;&nbsp;&nbsp;&nbsp;if(typeof(getColValue(oTR1.cells[iCol])) == &quot;number&quot; &amp;&amp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typeof(getColValue(oTR2.cells[iCol])) == &quot;number&quot;) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return getColValue(oTR1.cells[iCol]) - getColValue(oTR2.cells[iCol]);<br />&nbsp;&nbsp;return &nbsp;&nbsp;getColValue(oTR1.cells[iCol]).localeCompare(getColValue(oTR2.cells[iCol]));<br />&nbsp;&nbsp;};<br />return ret; <br />};</div>
	<p>Além dela há também a fun&ccedil;&atilde;o getColValue(), que recebe um elemento &lt;td&gt; e busca por um conteúdo classificável. Veja a ordem de preced&ecirc;ncia no retorno da fun&ccedil;&atilde;o:</p>
	<ul>
<li>se há apenas texto, retorna o texto</li>
	<li>se há texto e TAGs, retorna apenas o texto</li>
	<li>se n&atilde;o há texto:
<ul>
<li>se há (na TD) o atributo &quot;title&quot;, retorna seu valor</li>
	<li>se o 1&ordm; elemento da TD é uma IMG:
<ul>
<li>se há o atributo &quot;title&quot;, retorna seu valor</li>
	<li>se há o atributo &quot;alt&quot;, retorna seu valor</li>
	<li>se n&atilde;o há alt nem title, retorna o atributo &quot;src&quot; da imagem</li>
</ul>
</li>
</ul>
</li>
	<li>se n&atilde;o é nenhum dos casos acima, retorna uma string vazia</li>
</ul>
	<p>Vejamos a getColValue():</p>
	<div class="codigo">function getColValue(col) {<br />var ret = col.innerHTML.replace(/&lt;[^&gt;]*&gt;/g,&quot;&quot;);<br />&nbsp;&nbsp;if(/^\s*$/.test(ret)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;if(/\w+/.test(col.title)) ret = col.title;<br />&nbsp;&nbsp;&nbsp;&nbsp;else if(/^img$/i.test(col.firstChild.tagName)) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = col.firstChild.title || col.firstChild.alt || col.firstChild.src;<br />&nbsp;&nbsp;else ret = &quot;&quot;;<br />&nbsp;&nbsp;}<br />return /^\d+$/.test(ret) ? parseInt(ret) : ret;<br />}</div>
	<p>Claro que se poderia fazer o mesmo usando apenas o DOM, mas é mais simples assim e estamos falando de IE 4 e NS 6 - praticamente n&atilde;o há falta de suporte dos navegadores. Contradizendo isso, a fun&ccedil;&atilde;o generateCompareTRs usa o método localeCompare, da vers&atilde;o 5.6 do Javascript&#8230; </p>
	<p>Independente de prefer&ecirc;ncias, considero a fun&ccedil;&atilde;o bastante útil e espero que seja de ajuda para alguém.</p>
	<p><a href="http://cauguanabara.jsbrasil.com/scripts/sorttable" target="_blank">Veja aqui uma página de testes</a></p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/12/01/classificando-o-conteudo-de-uma-tabela-como-num-data-grid/feed/</wfw:commentRss>
	</item>
		<item>
		<title>BadgerFish - traduzindo XML para JSON</title>
		<link>http://cauguanabara.blogsome.com/2006/11/28/badgerfish-traduzindo-xml-para-json/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/28/badgerfish-traduzindo-xml-para-json/#comments</comments>
		<pubDate>Tue, 28 Nov 2006 17:50:53 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
	<category>Javascript</category>
	<category>Web 2.0</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/28/badgerfish-traduzindo-xml-para-json/</guid>
		<description><![CDATA[	Há uns seis meses descobri o ‘BadgerFish’, uma convenção para traduzir arquivos XML para objetos Javascript em forma de strings JSON (para compreender o BadgerFish, aprenda primeiro o JSON: 1, 2, 3, 4). Trata-se de um conjunto de regras extremamente simples, descrito em uma página de pouco texto e é isso aí, não achei quase [...]]]></description>
			<content:encoded><![CDATA[	<p>Há uns seis meses descobri o ‘BadgerFish’, uma convenção para traduzir arquivos XML para objetos Javascript em forma de strings JSON (para compreender o BadgerFish, aprenda primeiro o <a href="http://www.json.org/" target=_blank>JSON</a>: <a href="http://pt.wikipedia.org/wiki/JSON" target=_blank>1</a>, <a href="http://labase.nce.ufrj.br/blog/izalmo/2006/06/02/1149270840000.html" target=_blank>2</a>, <a href="http://webdoispontozero.com/blog/?p=8" target=_blank>3</a>, <a href="http://juliogreff.wordpress.com/2006/11/02/json-validado/" target=_blank>4</a>). Trata-se de um conjunto de regras extremamente simples, descrito em uma <a href="http://badgerfish.ning.com/" target=_blank>página de pouco texto</a> e é isso aí, não achei quase nada mais. Depois achei essa <a href="http://ajaxian.com/archives/badgerfish-translating-xml-to-json" target=_blank>aqui</a>, que é apenas uma referência à outra, mas que tinha alguns comentários. <br />Na época criei uma comunidade no Orkut (), que nunca teve discussões (?!). Achei então que ainda não haveria discussões em português por enquanto em lugar nenhum e deixei pra lá, mas como o tema é mais atual que nunca, voltei a ele. <br />Hoje fiz uma busca no Google e até que agora há bastante coisa em inglês e japonês (&#8230;), mas numa busca por resultados em português, apenas dois resultados sem relevância. Uma outra busca no del.icio.us me devolveu apenas 7 páginas, Bloglines: nada, mas no Technorati a coisa já muda de figura&#8230; mas tudo em gringo. As novidades sempre surgem na blogsfera, já notou? </p>
<a id="more-15"></a></p>
	<p>Bem, já que ninguém se manifesta, vamos nós ao BadgerFish, concebido por <a href="http://www.sklar.com/" target=_blank>David Sklar</a>. <br />Segue uma tradução (de partes) da página original:</p>
<em></p>
	<blockquote><p><em></p>
	<p>BadgerFish é uma convenção para traduzir documentos XML para objetos JSON. Uma vez que você tem o XML em um objeto JSON, basta transformá-lo em um objeto Javascript e fica muito mais fácil manipulá-lo. <br />Se você está familiarizado com a extensão SimpleXML do PHP, pense em BadgerFish como algo que aponta para uma meta semelhante: criar uma forma simples para manipular documentos XML com uma estrutura previsível.</p>
<strong>As regras </strong></p>
	<ol>
	<li>Nomes de elementos tornam-se propriedades de objeto</li>
	<li>O texto dentro de uma TAG torna-se a propriedade &#8216;$&#8217; do objeto </li>
	<li>Elementos aninhados tornam-se propriedades aninhadas </li>
	<li>Múltiplos elementos iguais no mesmo nível tornam-se arrays </li>
	<li>Atributos das TAGs tornam-se propriedades cujos nomes começam com &#8216;@&#8217; </li>
	<li>Namespaces ativos vão para a propriedade &#8216;@xmlns&#8217; </li>
	<li>O namespace default entra em @xmlns.$ </li>
	<li>Outros namespaces viram outras propriedades de @xmlns </li>
	<li>Elementos com prefixo de namespace tornam-se também propriedades do objeto </li>
</ol>
	<p>(&#8230;)</p>
	<p><strong>O que falta fazer </strong></p>
	<ol>
	<li>Se o conteúdo de uma TAG for composto de espaços em branco, ele será ignorado.</li>
	<li>Não há um método para trabalhar com fragmentos de texto em TAGs cujo conteúdo é mesclado de texto solto e outrasTAGs (ex. &lt;p&gt;Some text &lt;strong&gt;is important&lt;/strong&gt;.&lt;/p&gt;). Talvez esses fragmentos de texto devessem estar disponíveis em $1, $2, etc. </li>
	<li>BadgerFish cria a propriedade @xmlns em todos os elementos onde um namespace é ativo, não só no elemento onde o namespace é declarado. Isso pode serexcessivo para quem não se preocupa tanto com namespaces. Talvez um formato alternativo que ignore @xmlns completamente?</li>
	<li>Adaptadores para criar strings JSON formatadas como BadgerFish em idiomas diferentes de PHP. </li>
</ol>
(&#8230;) [<a href="http://badgerfish.ning.com/" target=_blank>visite</a>] </em></blockquote>
</em></p>
	<p>Além do mostrado acima, a página oferece um <a href="http://badgerfish.ning.com/file.php?format=src&amp;path=lib/BadgerFish.php" target=_blank>script em PHP para tradizir, feito pelo próprio David Sklar</a> (que depende do <a href="http://pear.php.net/pepr/pepr-proposal-show.php?id=198" target=_blank>Services JSON</a>, da <a href="http://pear.php.net/">Pear</a>) e algumas outras referências. </p>
	<p>Para dar um exemplo inicial, considere o trecho de XML abaixo:</p>
	<div class=codigo>&lt;person&gt;&lt;name&gt;Fulado de Tal&lt;/name&gt;&lt;/person&gt; </div>
	<p>Cada elemento vira um objeto (regra 1, bem mal traduzida&#8230;) e é colocado como uma propriedade do objeto relativo ao seu elemento pai, a não ser no caso do elemento root, que é &#8216;o pai de todos&#8217;. A regra nº 2 (o texto de um elemento vira a propriedade &#8220;$&#8221; do objeto correspondente) também está em ação.</p>
	<p>Veja o resultado:</p>
	<div class=codigo>var json_str = &#8216;{ &#8220;person&#8221;: { &#8220;name&#8221;: { &#8220;$&#8221;: &#8220;Fulado de Tal&#8221; } } }&#8217;;</div>
	<p>O JSON em si é a string que está sendo atribuída a json_str. Criaremos a json_obj para receber a string &#8216;parseada&#8217;, assim: </p>
	<div class=codigo>var json_obj = eval(&#8221;(&#8221;+json_str+&#8221;)&#8221;);<br />// ou&#8230; (isso evita certos erros, retornando null) <br />var json_obj = new Function(&#8217;try { return &#8216;+json_str+&#8217;; } catch(e) { return null; }&#8217;)();</div>
	<p>Assim, bastaria atribuir o objeto (transformado de string para objeto) a uma variável (json_obj) e para pegar o texto do elemento &lt;name&gt; usaríamos:</p>
	<div class=codigo>var name_content = json_obj.person.name.$; // ou <br />var name_content = json_obj[&#8221;person&#8221;][&#8221;name&#8221;][&#8221;$&#8221;];</div>
	<p>Sim, mas e se fosse um arquivo XML completo? Veja: </p>
	<div class=codigo>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;iso-8859-1&#8243;?&gt;<br />&lt;noticias&gt;<br />&lt;item&gt;<br />&lt;title&gt;Caminhada na Natureza&lt;/title&gt;<br />&lt;description&gt;Caminhadas e lazer na região de São Pedro e Lumiar&lt;/description&gt;<br />&lt;url&gt;&lt;/url&gt;<br />&lt;text&gt;Percurso de 10 km, Padrão Internacional IVV, Inscrições no local&lt;/text&gt;<br />&lt;/item&gt;<br />&lt;/noticias&gt;</div>
	<p>Esse arquivo depois de &#8216;traduzido&#8217; pelas normas do BadgerFish, seria uma string JSON assim (as quebras de linha não são necessárias&#8230; apenas para ilustrar):</p>
	<div class=codigo>{ <br />&nbsp; &#8220;noticias&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;item&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;title&#8221;: { &#8220;$&#8221;: &#8220;Caminhada na Natureza&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;description&#8221;: { &#8220;$&#8221;: &#8220;Caminhadas e lazer na região de São Pedro e Lumiar&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;url&#8221;: { }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;text&#8221;: { &#8220;$&#8221;: &#8220;Percurso de 10 km, Padrão Internacional IVV, Inscrições no local&#8221; } <br />&nbsp;&nbsp;&nbsp;&nbsp;} <br />&nbsp;&nbsp;} <br />}</div>
	<p>Mas como ficaria se houvesse duas TAGs &lt;item&gt; na TAG root? </p>
	<div class=codigo>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;iso-8859-1&#8243;?&gt;<br />&lt;noticias&gt;<br />&lt;item&gt;<br />&lt;title&gt;Caminhada na Natureza&lt;/title&gt;<br />&lt;description&gt;Caminhadas e lazer na região de São Pedro e Lumiar&lt;/description&gt;<br />&lt;url&gt;&lt;/url&gt;<br />&lt;text&gt;Percurso de 10 km, Padrão Internacional IVV, Inscrições no local&lt;/text&gt;<br />&lt;/item&gt;<br />&lt;item&gt;<br />&lt;title&gt;Mostra de Orquídeas&lt;/title&gt;<br />&lt;description&gt;Mostra de Orquídeas - exposição e vendas&lt;/description&gt;<br />&lt;url&gt;&lt;/url&gt;<br />&lt;text&gt;Oficina de cultivo (gratuito), Dia 07: das 15h as 17h&lt;/text&gt;<br />&lt;/item&gt;<br />&lt;/noticias&gt;</div>
	<p>Como há duas TAGs iguais em seqüência e no mesmo nível, aplicamos a regra nº 4, transformando a seqüência em um array. Não poderíamos criar propriedades com o mesmo nome em um mesmo nível de um objeto JS - então fica assim:</p>
	<div class=codigo>{ <br />&nbsp; &#8220;noticias&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;item&#8221;: [ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;title&#8221;: { &#8220;$&#8221;: &#8220;Caminhada na Natureza&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;description&#8221;: { &#8220;$&#8221;: &#8220;Caminhadas e lazer na região de São Pedro e Lumiar&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;url&#8221;: { }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;text&#8221;: { &#8220;$&#8221;: &#8220;Percurso de 10 km, Padrão Internacional IVV, Inscrições no local&#8221; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;title&#8221;: { &#8220;$&#8221;: &#8220;Mostra de Orquídeas&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;description&#8221;: { &#8220;$&#8221;: &#8220;Mostra de Orquídeas - exposição e vendas&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;url&#8221;: { }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;text&#8221;: { &#8220;$&#8221;: &#8220;Oficina de cultivo (gratuito), Dia 07: das 15h as 17h&#8221; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />&nbsp;&nbsp;&nbsp;&nbsp;] <br />&nbsp;&nbsp;} <br />}</div>
	<p>E se os elementos tivessem propriedades e não apenas sub elementos? Aí se aplicam as regras n<sup><u>os</u></sup> 6, 7, 8 e 9 . Considere esse outro XML: </p>
	<div class=codigo>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;iso-8859-1&#8243;?&gt;<br />&lt;livro_de_receitas xmlns=&#8221;http://www.w3c.org/some-namespace&#8221;&gt;<br />&lt;receita nome=&#8221;pão&#8221; tempo_de_preparo=&#8221;5 minutos&#8221; tempo_de_cozimento=&#8221;3 horas&#8221;&gt;<br />&lt;titulo&gt;Pão simples&lt;/titulo&gt;<br />&lt;ingrediente quantidade=&#8221;3&#8243; unidade=&#8221;xícaras&#8221;&gt;Farinha&lt;/ingrediente&gt;<br />&lt;ingrediente quantidade=&#8221;7&#8243; unidade=&#8221;gramas&#8221;&gt;Fermento&lt;/ingrediente&gt;<br />&lt;ingrediente quantidade=&#8221;1.5&#8243; unidade=&#8221;xícaras&#8221; estado=&#8221;morna&#8221;&gt;Água&lt;/ingrediente&gt;<br />&lt;ingrediente quantidade=&#8221;1&#8243; unidade=&#8221;colheres de chá&#8221;&gt;Sal&lt;/ingrediente&gt;<br />&lt;instrucoes&gt;<br />&lt;passo&gt;Misture todos os ingredientes, e dissolva bem.&lt;/passo&gt;<br />&lt;passo&gt;Cubra com um pano e deixe por uma hora em um local morno.&lt;/passo&gt;<br />&lt;passo&gt;Misture novamente, coloque numa bandeja e asse num forno.&lt;/passo&gt;<br />&lt;/instrucoes&gt;<br />&lt;/receita&gt;<br />&lt;/livro_de_receitas&gt;</div>
	<p>A nona e última regra &#8220;<em>Elementos com prefixo de namespace tornam-se também propriedades do objeto</em>&#8220;, traduzindo a minha tradução, significa que todos os elementos contidos em um elemento com um ou mais namespaces definidos devem também ter esse(s) namespace(s) como propriedades. <br />Eu considero um certo exagero, posto que o princípio da hereditariedade usado no próprio XML é aplicável aqui também. Mais embaixo (O que falta fazer, 3), o próprio David sugere ignorar inteiramente os namespaces&#8230; esse tem aplicação possível - nem sempre estamos interessados nos namespaces&#8230; </p>
	<p>Resolvi usar a hereditariedade, declarando o namespace apenas no objeto reletivo ao elemento em que o tal namespace foi declarado. </p>
	<p>Veja o resultado: </p>
	<div class=codigo>{ <br />&nbsp; &#8220;livro_de_receitas&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: { &#8220;$&#8221;: &#8220;http://www.w3c.org/some-namespace&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;receita&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@nome&#8221;: &#8220;pão&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@tempo_de_preparo&#8221;: &#8220;5 minutos&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@tempo_de_cozimento&#8221;: &#8220;3 horas&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;titulo&#8221;: { &#8220;$&#8221;: &#8220;Pão simples&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;ingrediente&#8221;: [ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: 3, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;xícaras&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Farinha&#8221; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: 7, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;gramas&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Fermento&#8221; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: &#8220;1.5&#8243;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;xícaras&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@estado&#8221;: &#8220;morna&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Água&#8221; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: 1, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;colheres de chá&#8221;, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Sal&#8221; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;], <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;instrucoes&#8221;: { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;passo&#8221;: [ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &#8220;$&#8221;: &#8220;Misture todos os ingredientes, e dissolva bem.&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &#8220;$&#8221;: &#8220;Cubra com um pano e deixe por uma hora em um local morno.&#8221; }, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &#8220;$&#8221;: &#8220;Misture novamente, coloque numa bandeja e asse num forno.&#8221; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp; } <br />}</div>
	<p>Transcrevo abaixo o mesmo arquivo traduzido segundo a nona regra, literalmente (traduzido pelo script do David): </p>
	<div class=codigo>{<br />&nbsp;&nbsp;&#8221;livro_de_receitas&#8221;: {<br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;receita&#8221;: {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;titulo&#8221;: {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Pão simples&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;ingrediente&#8221;: [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Farinha&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: &#8220;3&#8243;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;xícaras&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Fermento&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: &#8220;7&#8243;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;gramas&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Água&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: &#8220;1.5&#8243;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;xícaras&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@estado&#8221;: &#8220;morna&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Sal&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@quantidade&#8221;: &#8220;1&#8243;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@unidade&#8221;: &#8220;colheres de chá&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;instrucoes&#8221;: {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;passo&#8221;: [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Misture todos os ingredientes, e dissolva bem.&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Cubra com um pano e deixe por uma hora em um local morno.&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;$&#8221;: &#8220;Misture novamente, coloque numa bandeja e asse num forno.&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@nome&#8221;: &#8220;pão&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@tempo_de_preparo&#8221;: &#8220;5 minutos&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@tempo_de_cozimento&#8221;: &#8220;3 horas&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;&nbsp;&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;@xmlns&#8221;: {&#8221;$&#8221;: &#8220;http:\/\/www.w3c.org\/some-namespace&#8221;}<br />&nbsp;&nbsp;}<br />} </div>
	<p>Não vou julgar, pois esse é um tópico que me parece óbvio demais&#8230; provavelmente há algo que eu não percebi, não sei. Por quê declarar em todos os sub elementos? Bem, finalizando&#8230;</p>
	<p>Fiz um script (qualquer hora mostro aqui) para fazer essa tradução, mas na hora da prática percebi alguns problemas&#8230; segue um trecho do texto que adicionei ao dito script:</p>
<em></p>
	<blockquote><p><em></p>
	<p><strong>O que ainda falta fazer</strong> </p>
	<ul>
	<li><strong>Tudo que estiver fora do escopo da TAG root será ignorado</strong><br />Como todo o conteúdo legível de um XML encontra-se encapsulado na sua TAG root e as regras para inclusão desses itens no objeto de retorno JSON ainda não estão estabelecidas, aqui trabalhamos apenas com o conteúdo da TAG root. Isso é um ponto importante, pois para podermos usar o termo &#8216;traduzir um documento XML&#8217;, essa questão deve ser resolvida. </li>
	<li><strong>Namespaces</strong><br />Resolvi declarar os namespaces apenas nos objetos relativos às TAGs onde eles foram declarados no XML e não em todos os childs, como recomendado no item 9 das regras. Posto que os childs já estão contidos no elemento onde o namespace está declarado, achei isso desnecessário. E com isso, chego a uma regra diferente da atual e diferente da sugestão de ignorar completamente os namespaces. </li>
	<li><strong>Fragmentos de texto em conteúdos mistos </strong><br />Os fragmentos, como descritos no item 2 de &#8216;O que falta fazer&#8217;, são tratados como sugerido no próprio texto: $1, $2, etc&#8230;, para cada TAG. </li>
	<li><strong>Os comentários (dentro do escopo da TAG root)</strong><br />Para os comentários, adotei o caracter &#8216;!&#8217;, usado na TAG correspondente (&lt;!&#8211;&#8230;). Da mesma forma que os fragmentos de texto, as TAGs de comentário contidas em determinada TAG entrarão nas propriedades: !1, !2, etc&#8230;, dessa TAG. </li>
	<li><strong>As seções CDATA</strong><br />Para as TAGs CDATA, adotamos o caracter &#8216;#&#8217;, arbitrariamente. Da mesma forma que os fragmentos de texto, as TAGs CDATA contidas em determinada TAG entrarão nas propriedades: #1, #2, etc&#8230;, dessa TAG. </li>
</ul>
	<p><strong>Colocado isso, aqui vão as regras que usei:</strong></p>
	<ol>
	<li>Nomes de elementos tornam-se propriedades de objeto</li>
	<li>O texto dentro de uma TAG torna-se a propriedade &#8216;$&#8217; do objeto </li>
	<li>Elementos aninhados tornam-se propriedades aninhadas </li>
	<li>Múltiplos elementos iguais no mesmo nível tornam-se arrays </li>
	<li>Atributos das TAGs tornam-se propriedades cujos nomes começam com &#8216;@&#8217; </li>
	<li>Namespaces ativos vão para a propriedade &#8216;@xmlns&#8217; do objeto relativo à TAG onde foram declarados</li>
	<li>O namespace default entra em @xmlns.$ </li>
	<li>Outros namespaces viram outras propriedades de @xmlns </li>
	<li><strike>Elementos com prefixo de namespace tornam-se também propriedades do objeto</strike> (usei a hereditariedade)</li>
	<li>No caso de conteúdos mistos de TAGs e texto, os fragmentos entram em $1, $2, etc., na sequência respectiva</li>
	<li>Comentários entram nas propriedades !1, !2, etc., na sequência respectiva </li>
	<li>As seções CDATA entram nas propriedades #1, #2, etc., na sequência respectiva</li>
</ol>
	<p><strong>O que ainda falta fazer </strong></p>
	<ul>
	<li>Um método para armazenar os dados em TAGs fora do escopo da TAG root </li>
	<li>Conteúdos de TAG compostos apenas de espaços em branco ainda são ignorados..</li>
</ul>
</em></blockquote>
</em></p>
	<p>Entrei em contato com o David Sklar a respeito das dúvidas colocadas acima, mas ele repondeu sem muito interesse, me deixando livre para criar minhas próprias regras complementares. Bem, foi o que fiz. Deixo isso claro, por que, se alguém achar que pode melhorar, por favor melhore! </p>
	<p>Abraço, Cau Guanabara </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/28/badgerfish-traduzindo-xml-para-json/feed/</wfw:commentRss>
	</item>
		<item>
		<title>editInPlace() - editando qualquer elemento HTML</title>
		<link>http://cauguanabara.blogsome.com/2006/11/26/editinplace-editando-qualquer-elemento-html/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/26/editinplace-editando-qualquer-elemento-html/#comments</comments>
		<pubDate>Mon, 27 Nov 2006 01:48:15 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>DHTML</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/26/editinplace-editando-qualquer-elemento-html/</guid>
		<description><![CDATA[	Hoje, mexendo em um trabalho que fiz há algum tempo, redescobri essa fun&ccedil;&atilde;o que considero muito útil. Com ela é possível abrir determinados elementos para edi&ccedil;&atilde;o. Deixar o usuário editar o conteúdo de um DIV ou TD por exemplo (ou qualquer um que tenha a propriedade innerHTML). Eu criei a fun&ccedil;&atilde;o para um sistema em [...]]]></description>
			<content:encoded><![CDATA[	<p>Hoje, mexendo em um trabalho que fiz há algum tempo, redescobri essa fun&ccedil;&atilde;o que considero muito útil. Com ela é possível abrir determinados elementos para edi&ccedil;&atilde;o. Deixar o usuário editar o conteúdo de um DIV ou TD por exemplo (ou qualquer um que tenha a propriedade innerHTML). Eu criei a fun&ccedil;&atilde;o para um sistema em que o usuário editava dados em um XML: montava a página a partir do XML e deixava o usuário editar os textos, ent&atilde;o remontava o XML a partir do innerHTML da página.</p>
	<p>A idéia surgiu&nbsp; com uma fun&ccedil;&atilde;o que encontrei nos meus garimpos, para determinar a posi&ccedil;&atilde;o exata de um elemento na página, a absPos(). Essa é uma fun&ccedil;&atilde;o que está toda dentro de um for que n&atilde;o tem bloco de comandos, numa sintaxe legal, pouco comum. N&atilde;o sei quem é o autor&nbsp;(displic&ecirc;ncia minha&#8230; desculpe-me por isso&nbsp;o autor dessa fun&ccedil;&atilde;o t&atilde;o legal), veja:</p>
<a id="more-14"></a><br />
<div class="codigo">function absPos(el) {<br />&nbsp; for(var lx = 0, ly = 0; el != null; lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);<br />return { &#8216;x&#8217;: lx, &#8216;y&#8217;: ly }<br />}</div>
	<p>Bem, sabendo a posi&ccedil;&atilde;o e as dimens&otilde;es do elemento, bastava pegar o innerHTML, jogar em um input e colocar em cima do elemento editado. A fun&ccedil;&atilde;o ficou curta e eficiente, restando o problema visual de, ao editar textos formatados, n&atilde;o exibir a mesma formata&ccedil;&atilde;o do texto original. Um elemento pode ser herdeiro de uma grande quantidade de regras CSS e n&atilde;o consegui um meio de&nbsp;fazer o meu input herdar&nbsp;isso também.</p>
	<p>A editInPlace depende de duas outras fun&ccedil;&otilde;es: absPos() e uma vers&atilde;o minha da fun&ccedil;&atilde;o $ do <a href="http://prototype.conio.net/" target="_blank">prototype</a>, que pega ou cria um elemento com determinado ID. </p>
	<p>Lá v&atilde;o as fun&ccedil;&otilde;es:</p>
	<div class="codigo">
<p>// editinplace.js</p>
	<p>function editInPlace(el) {<br />var oriHTML = el.innerHTML;<br />var xy = absPos(el);<br />editting_element = el;<br />var div = $(&#8217;edit_div&#8217;,'div&#8217;); <br />div.innerHTML = &#8216;&lt;form style=&quot;margin:0px;&quot; onsubmit=&quot;return false;&quot;&gt;\<br />&lt;input type=&quot;text&quot; value=&quot;&#8217;+(oriHTML == &#8216;[vazio]&#8217; ? &#8216;&#8217; : oriHTML)+<br />&#8216;&quot; id=&quot;edit_input&quot; onblur=&quot;editting_element\<br />.innerHTML = this.value != \&#8217;\&#8217; ? this.value : \&#8217;[vazio]\&#8217;; \<br />$(\&#8217;edit_div\&#8217;).style.display = \&#8217;none\&#8217;;&quot; style=&quot;width:&#8217;+<br />(el.offsetWidth+2)+&#8217;px; height:&#8217;+(el.offsetHeight+2)+<br />&#8216;px; border:none; background-color:transparent;&quot; /&gt;&lt;/form&gt;&#8217;;<br />editting_element.innerHTML = &#8216;&#8217;;<br />div.style.position = &#8216;absolute&#8217;;<br />div.style.width = &#8216;auto&#8217;;<br />div.style.height = &#8216;auto&#8217;;<br />div.style.top = (xy.y - 1)+&#8217;px&#8217;; <br />div.style.left = (xy.x - 1)+&#8217;px&#8217;;<br />div.style.display = &#8216;&#8217;;<br />$(&quot;edit_input&quot;).focus();<br />$(&quot;edit_input&quot;).select();<br />}</p>
	<p>function $(id,tag,targetId) {<br />var ret = document.getElementById(id) || false;<br />&nbsp;if(!ret) {<br />&nbsp;ret = document.createElement(tag);<br />&nbsp;ret.id = id;<br />&nbsp;((document.getElementById(targetId) || false) <br />&nbsp; || document.getElementsByTagName(&#8217;body&#8217;)[0]).appendChild(ret);<br />&nbsp;}<br />return ret;<br />}</p>
	<p>function absPos(el) {<br />&nbsp; for(var lx = 0, ly = 0; el != null; lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);<br />return { &#8216;x&#8217;: lx, &#8216;y&#8217;: ly }<br />} </p>
</div>
	<p>Segue um exemplo de uso, supondo que o conteúdo acima está no arquivo editinplace.js:</p>
	<div class="codigo">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;<br />&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot; /&gt;<br />&lt;title&gt;Untitled Document&lt;/title&gt;<br />&lt;script type=&quot;text/javascript&quot; src=&quot;editinplace.js&quot;&gt;&lt;/script&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;div onclick=&quot;editInPlace(this)&quot;&gt;clique para editar&lt;/div&gt;<br />&lt;span onclick=&quot;editInPlace(this)&quot;&gt;texto editável&lt;/span&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</div>
	<p>Resolvi inserir o texto &#8216;[vazio]&#8217; quando o usuário deleta o texto, pois n&atilde;o dava para criar algo clicável sem texto&#8230;<br />Bem, vou ficando por aqui. Sei que fui muito sintético, mas estamos aí&#8230; comente, pergunte que eu explico.</p>
	<p>Abra&ccedil;o, Cau Guanabara. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/26/editinplace-editando-qualquer-elemento-html/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Uma singela introdução à lógica de programação</title>
		<link>http://cauguanabara.blogsome.com/2006/11/21/uma-singela-introducao-a-logica-de-programacao/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/21/uma-singela-introducao-a-logica-de-programacao/#comments</comments>
		<pubDate>Tue, 21 Nov 2006 23:23:48 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>PHP</category>
	<category>Tutoriais</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/21/uma-singela-introducao-a-logica-de-programacao/</guid>
		<description><![CDATA[	Análise do problema e algoritmo de solu&ccedil;&atilde;o
	Todo aplicativo se destina a automatizar um processo que poderia ser executado manualmente, ou a resolver algum problema que se poderia resolver com raciocínio lógico - mesmo que isso fosse levar muito tempo. Acreditamos que isso é verdadeiro em qualquer &acirc;mbito. Entendemos por &#8216;processo&#8217; ou &#8216;problema&#8217; qualquer situa&ccedil;&atilde;o que [...]]]></description>
			<content:encoded><![CDATA[	<p class="negrito">Análise do problema e algoritmo de solu&ccedil;&atilde;o</p>
	<p>Todo aplicativo se destina a automatizar um processo que poderia ser executado manualmente, ou a resolver algum problema que se poderia resolver com raciocínio lógico - mesmo que isso fosse levar muito tempo. Acreditamos que isso é verdadeiro em qualquer &acirc;mbito. <br />Entendemos por &#8216;processo&#8217; ou &#8216;problema&#8217; qualquer situa&ccedil;&atilde;o que se apresente para o programador &#8216;automatizar&#8217;. Programar é resolver o problema proposto etapa por etapa e codificar cada passo, até a solu&ccedil;&atilde;o. Ou seja, um programa é uma refer&ecirc;ncia a um problema previamente resolvido. O que chamamos de algoritmo é simplesmente a sequ&ecirc;ncia lógica de a&ccedil;&otilde;es que levam ao resultado esperado (a solu&ccedil;&atilde;o do problema). Naturalmente, é necessária uma análise detalhada do problema, sem a qual n&atilde;o há a menor possibilidade de se desenvolver um algoritmo funcional.</p>
<a id="more-12"></a>
<p>Por exemplo, vamos supor que queremos que determinada página em nosso site seja acessada apenas por usuários com login e senha cadastrados no banco de dados. Para analisar este &#8216;problema&#8217; vamos transportar a situa&ccedil;&atilde;o para o &acirc;mbito humano e pensar no site como uma casa, um local de divers&atilde;o aberto ao público. Vamos imaginar que nessa casa há uma sala muito especial onde só entram certas pessoas selecionadas, cujos nomes est&atilde;o em uma lista de convidados. Na lista, para cada convidado ainda há uma senha secreta que o mesmo tem que saber, sen&atilde;o n&atilde;o entra.<br />Ficou mais fácil, n&atilde;o? Se alguém pedisse que voc&ecirc; ficasse na porta e controlasse a entrada dos convidados, aposto que n&atilde;o haveria problemas, voc&ecirc; saberia o que fazer&#8230; <br />Veja este diálogo: </p>
	<blockquote style="padding-left: 5px; border-left: #ccc 5px solid"><p><em>- Boa noite, sou convidado. <br />- Nome, por favor&#8230;<br />- Alberto.<br />- Deixe-me ver&#8230; ah sim! Alberto está na lista. Qual é a sua senha?<br />- Hum, &#8216;gato preto&#8217;. <br />- Senhor, infelizmente a senha cadastrada n&atilde;o é &#8216;gato preto&#8217;. Quer tentar novamente?<br />- Bem, foi minha mulher que fez esse cadastro&#8230; tente &#8216;bolinha&#8217;.<br />- Perfeitamente, senhor. Pode entrar, a senha está correta. <br />Ent&atilde;o o porteiro abre a porta. </em></p></blockquote>
	<p>&nbsp;</p>
	<p>O diálogo acima cont&ecirc;m tudo que precisamos para implementar o programa solicitado. Precisamos apenas transportar de volta a nossa abstra&ccedil;&atilde;o para o universo real do problema. </p>
	<table cellspacing="0" cellpadding="5" border="1">
<tr>
<td><strong>Abstra&ccedil;&atilde;o humana</strong></td>
	<td width="50%"><strong>Universo real </strong></td>
</tr>
	<tr>
<td>o porteiro</td>
	<td>o programa em si </td>
</tr>
	<tr>
<td>o convidado</td>
	<td>o usuário </td>
</tr>
	<tr>
<td>a lista </td>
	<td>o banco de dados </td>
</tr>
	<tr>
<td>verificar o nome na lista </td>
	<td>ver se há o login fornecido no banco </td>
</tr>
	<tr>
<td>verificar a senha de alberto </td>
	<td>ver se a senha correspende ao login </td>
</tr>
	<tr>
<td>abrir a porta </td>
	<td>mostrar a página </td>
</tr>
</table>

<p>Para organizar as etapas da solu&ccedil;&atilde;o em uma sequ&ecirc;ncia lógica, vamos escrev&ecirc;-la na forma de um pseudo-código. </p>
	<p class="negrito">Pseudo-código </p>
	<p>Um pseudo-código é uma lista de a&ccedil;&otilde;es, organizadas numa sequ&ecirc;ncia lógica, para resolver determinado problema. É a formaliza&ccedil;&atilde;o do algoritmo, o próprio programa escrito em linguagem humana. É extremamente útil, pois nos ajuda a identificar as possíveis falhas na lógica utilizada. <br />Existem algumas regras simples para tornar o seu pseudo-código mais inteligível: </p>
	<ul>
<li>seja direto e objetivo</li>
	<li>use apenas um verbo por frase</li>
	<li>n&atilde;o use palavras de sentido ambíguo</li>
	<li>use frases curtas</li>
</ul>
	<p>&nbsp;</p>
	<p>O nosso algoritmo é simples e curto: come&ccedil;a quando o usuário clica no link que leva &agrave; nossa página protegida e termina quando o acesso é liberado ou negado. Existem algumas condi&ccedil;&otilde;es que ficaram implícitas no diálogo, mas temos que explicitá-las para o computador entender. S&atilde;o essas condi&ccedil;&otilde;es que determinar&atilde;o se o acesso será permitido ou negado. Vamos ver o exemplo acima escrito dessa forma: </p>
	<ul>
<li>Pedir login e senha</li>
	<li>Verificar se o par login/senha recebido corresponde a algum registro no banco
<ul>
<li>Caso negativo: voltar ao início (pedir login e senha)</li>
	<li>Caso positivo: mostrar a página </li>
</ul>
</li>
</ul>
	<p>O pseudo-código acima descreve um sistema que testa o par login-senha como uma coisa única. Funcionaria perfeitamente, mas em caso de erro, o script n&atilde;o saberia se o erro foi do login, da senha ou de ambos, o que n&atilde;o seria muito elegante - e n&atilde;o corresponde ao diálogo de nosso educado porteiro com o convidado. Podemos ent&atilde;o fazer dois testes separados e enviar ao usuário uma mensagem de erro personalizada para cada caso: </p>
	<ul>
<li>Pedir login e senha</li>
	<li>Verificar se o login recebido corresponde a algum registro no banco
<ul>
<li>Caso negativo: imprimir &#8216;login inexistente&#8217; e voltar ao início</li>
	<li>Caso positivo: comparar a senha digitada com a senha do banco
<ul>
<li>Caso negativo: imprimir &#8217;senha incorreta&#8217; e voltar ao início</li>
	<li>Caso positivo: mostrar a página </li>
</ul>
</li>
</ul>
</li>
</ul>
	<p>É exatamente isso que queremos que o script fa&ccedil;a: enquanto o usuário n&atilde;o acertar o login e a senha, o sistema continua solicitando esses dados. Qualquer pessoa ao ler esse pseudo-código é capaz de entender o que ele faz e de que forma, pois a linguagem adotada é humana. Existe uma outra forma de representar o algorítmo com uma linguagem gráfica, os diagramas de blocos. </p>
	<p class="negrito">Diagramas de blocos</p>
	<table cellspacing="0" cellpadding="5" width="450" border="1">
<tr>
<td width="50%"><strong>Símbolo</strong></td>
	<td width="50%"><strong>Significado</strong></td>
</tr>
	<tr>
<td align="center"><img height="99" src="http://cauguanabara.blogsome.com/images/inicio_fim.gif" width="133" border="0" /></td>
	<td>início ou fim do programa </td>
</tr>
	<tr>
<td align="center"><img height="99" src="http://cauguanabara.blogsome.com/images/entrada.gif" width="133" border="0" /></td>
	<td>entrada de dados </td>
</tr>
	<tr>
<td align="center"><img height="99" src="http://cauguanabara.blogsome.com/images/condicao.gif" width="133" border="0" /></td>
	<td>condi&ccedil;&atilde;o</td>
</tr>
	<tr>
<td align="center"><img height="99" src="http://cauguanabara.blogsome.com/images/processamento.gif" width="133" border="0" /></td>
	<td>processamento</td>
</tr>
	<tr>
<td align="center"><img height="99" src="http://cauguanabara.blogsome.com/images/saida.gif" width="133" border="0" /></td>
	<td>saída de dados </td>
</tr>
</table>
	<p>Partindo da pressuposto de que um programa deve receber dados e processá-los de acordo com certas condi&ccedil;&otilde;es para ent&atilde;o retornar o resultado, com os símbolos acima podemos representar qualquer algoritmo. Vamos ent&atilde;o criar o diagrama para o exemplo acima (o primeiro):</p>
	<p><img style="border-bottom: #333 1px solid" height="526" src="http://cauguanabara.blogsome.com/images/diagrama.gif" width="450" border="0" /></p>
	<p>Poderíamos também ter usado termos mais técnicos como os nomes das fun&ccedil;&otilde;es que pretendemos usar em cada etapa, mas essa n&atilde;o era a minha inten&ccedil;&atilde;o, portanto ficaremos por aqui. O importante é perceber como funciona a lógica de construir uma funcionalidade em forma de algoritmo, pois mais adiante n&atilde;o precisaremos mais escrever o algoritmo antes de come&ccedil;ar a programar, mas nunca deixaremos de faz&ecirc;-lo em pensamento. </p>
	<p>Esperamos ter ajudado&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/21/uma-singela-introducao-a-logica-de-programacao/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Mapa do site</title>
		<link>http://cauguanabara.blogsome.com/2006/11/20/9/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/20/9/#comments</comments>
		<pubDate>Mon, 20 Nov 2006 23:52:05 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>PHP</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/20/9/</guid>
		<description><![CDATA[	Um dos recursos mais importantes para que o visitante possa encontrar as informa&ccedil;&otilde;es que deseja é o famoso link &quot;mapa do site&quot;. O mapa do seu site pode ser organizado de várias formas e, naturalmente, é mais legal quando podemos fazer isso com calma, facilitando ao máximo o trabalho de achar o conteúdo procurado. Aliás, [...]]]></description>
			<content:encoded><![CDATA[	<p>Um dos recursos mais importantes para que o visitante possa encontrar as informa&ccedil;&otilde;es que deseja é o famoso link &quot;mapa do site&quot;. O mapa do seu site pode ser organizado de várias formas e, naturalmente, é mais legal quando podemos fazer isso com calma, facilitando ao máximo o trabalho de achar o conteúdo procurado. Aliás, o dito &quot;mapa do site&quot; é uma importante ferramenta de acessibilidade e deveria estar sempre presente. É ele que garante o&quot; aprendizado do layout do site&quot; pelo usuário menos experiente ou em layouts incomuns, com sistemas de navega&ccedil;&atilde;o fora do padr&atilde;o, etc. Mas em situa&ccedil;&otilde;es em que há muitas páginas para catalogar ou onde páginas s&atilde;o criadas/excluídas dinamicamente, podemos usar um script para ler a estrutura do site e mostrar as páginas automaticamente.</p>
	<p>Vou mostrar aqui um script em PHP que faz esse trabalho de cataloga&ccedil;&atilde;o e exibi&ccedil;&atilde;o automaticamente.</p>
<a id="more-9"></a>
<p><strong>A idéia</strong> </p>
	<p>Primeiro, o script tinha que ler um diretório (raiz do site) e guardar dados sobre todos os arquivos de tipos determinados, pela extens&atilde;o - .HTM, .HTML, .PHP, etc. Legal, mas e quanto a arquivos PHP que n&atilde;o contém HTML, por exemplo? há muitos arquivos, inclusive .html que n&atilde;o deveriam ser listados&#8230; ent&atilde;o precisamos também de algo que limite isso. Pensei em usar um array para isso, onde colocaria os nomes dos arquivos a serem excluídos. Ok, mas em grandes quantidades de arquivos isso ainda era insuficiente. Comecei ent&atilde;o a ler os arquivos e pegar apenas os que tem alguma string entre as tags &lt;title&gt; e &lt;/title&gt; e ler as META TAGs DESCRIPTION para descrever o arquivo na listagem. Os arquivos que n&atilde;o tem META DESCRIPTION podem também ser ignorados, bastando descomentar a linha a seguir na fun&ccedil;&atilde;o printTree. </p>
	<p>//if(empty($arr[&#8217;description&#8217;])) continue; </p>
	<p>Bem, afinal, acho que ficou bem legal, mas é importante salientar que este script só vai ser realmente útil para sites que usam de forma eficiente as TAGs citadas, n&atilde;o repetindo um mesmo title para todas as páginas do site e com descri&ccedil;&otilde;es específicas para cada página. </p>
	<p>Para usar é preciso editar certas variáveis, como descrito no comentário dentro do script. Segue o script na íntegra:</p>
	<p class="codigo">&lt;?php<br />/**<br />* Mapa do site<br />* &#8212;&#8212;&#8212;&#8212;<br />* @author Cau Guanabara<br />* @date 2006-10-01<br />* <br />* Este script cria um &#8216;mapa do site&#8217; a partir dos arquivos dentro de determinado diretório.<br />* Os par&acirc;metros buscados s&atilde;o os elementos HTML &lt;TITLE&gt; (para retirar o título) e<br />* &lt;META NAME=description CONTENT=&#8230;&gt; (para retirar a descri&ccedil;&atilde;o). Se o documento n&atilde;o tiver o<br />* elemento TITLE, n&atilde;o será incluído na listagem. Se n&atilde;o tiver META Description, aparecerá <br />* na listagem, mas sem descri&ccedil;&atilde;o.<br />* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />* Para usar defina essas variáveis com os valores apropriados:<br />* $sitedir -&gt; define o caminho para o diretório base da listagem (todos os sub-dir ser&atilde;o incluídos).<br />* $hostname -&gt; define a URL para o diretório base da listagem, para comp&ocirc;r os links.<br />* $extensions -&gt; define que tipos de arquivos ser&atilde;o incluídos na busca, pela extens&atilde;o.<br />* $ignore -&gt; define que arquivos e diretórios ser&atilde;o ignorados pelo sistema. Aqui deve-se usar<br />* apenas os nomes dos itens, n&atilde;o o caminho ou URL. Se houver vários itens com o mesmo<br />* nome em níveis diferentes, todos ser&atilde;o ignorados.<br />*<br />* Pode n&atilde;o ser conveniente usar este arquivo, se o conteúdo a ser listado é muito grande.<br />* Nesse caso, use este script para gerar o HTML e salve com extens&atilde;o .html - será mais rápido.<br />*<br />* O HTML pode ser editado &agrave; vontade, bastando preservar as se&ccedil;&otilde;es PHP. As tabelas est&atilde;o vinculadas <br />* ao CSS e para modificar, edite as classes CSS abaixo.<br />*/<br />// &#8212;&#8212;&#8212;&#8212;-<br />// configura&ccedil;&otilde;es<br />// &#8212;&#8212;&#8212;&#8212;-<br />// pasta raiz do site (path abs. ou rel. - n&atilde;o URL)<br />$sitedir = &quot;./&quot;; <br />// URL do site para usar endere&ccedil;os absolutos (se ficar em branco, as URLs ser&atilde;o relativas)<br />$hostname = &#8216;http://localhost/&#8217;;<br />// extens&otilde;es dos arquivos para listar<br />$extensions = array(&#8217;htm&#8217;,'html&#8217;,'php&#8217;,'asp&#8217;);<br />// nomes de pastas e arquivos que devem ser ignorados (em qualquer nível)<br />$ignore = array(&quot;sitemap.php&quot;); <br />// &#8212;&#8212;&#8212;&#8212;-<br />// isso foi necessário para pastas com conteúdo muito grande. O limite de 30 seg. <br />// n&atilde;o era suficiente, aumentei para 100 seg. (descomente se for necessário)<br />//set_time_limit(100);<br />$tree = dirItems($sitedir, $extensions, $ignore);<br />//print &#8216;&lt;hr /&gt;&lt;pre&gt;&#8217;.print_r($tree,1).&quot;&lt;/pre&gt;\n&quot;;<br />printTree($tree, $hostname);<br />function dirItems($directory, $extensions, $ignore = array()) {<br />$items = array();<br />if($_dir = @opendir($directory)) { <br />while(($_file = readdir($_dir)) !== false) {<br />if(in_array($_file, $ignore)) continue;<br />if(is_file($directory.$_file) and preg_match(&quot;/\.(&quot;.join(&#8217;|',$extensions).&quot;)$/&quot;,$_file)) {<br />if($retit = readItem($directory.$_file)) $items[] = $retit;<br />}<br />if(is_dir($directory.$_file) and !preg_match(&quot;/^\./&quot;,$_file)) {<br />$items[$_file] = dirItems($directory.$_file.&#8217;/', $extensions, $ignore);<br />}<br />}<br />closedir($_dir);<br />}<br />return $items;<br />}<br />function readItem($item) { //print $item.&#8217;&lt;br&gt;&#8217;;<br />$ret = array(&#8217;name&#8217; =&gt; preg_replace(&quot;/(^.+\/)([^\/]+)$/&quot;,&quot;$2&quot;,$item), <br />&#8216;folder&#8217; =&gt; preg_replace(&quot;/^.+\/([^\/]+)\/[^\/]+$/&quot;,&quot;$1&quot;,$item), <br />&#8216;url&#8217; =&gt; $item);<br />$conts = file_get_contents($item);<br />if(preg_match(&quot;/&lt;title[^&gt;]*&gt;([^&lt;]+)&lt;\/title&gt;/i&quot;, $conts, $matches)) $ret[&#8217;title&#8217;] = $matches[1];<br />else return false;<br />if(preg_match(&quot;/&lt;meta[^&gt;]*name=[\&#8217;\&quot;]description[\&#8217;\&quot;][^&gt;]*content=[\&#8217;\&quot;]([^\&#8217;\&quot;]+)[\&#8217;\&quot;]\s*\/?&gt;/i&quot;, $conts, $matches)) <br />$ret[&#8217;description&#8217;] = $matches[1];<br />return $ret;<br />}<br />?&gt;<br />&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;<br />&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot; /&gt;<br />&lt;meta name=&quot;description&quot; content=&quot;Encontre facilmente as páginas que procura dentro deste site.&quot; /&gt;<br />&lt;title&gt;Mapa do site&lt;/title&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />&lt;!&#8211;<br />body,td,th {<br />font-family: trebuchet MS, verdana, arial;<br />font-size: 14px;<br />}<br />body {<br />margin-left: 10px;<br />margin-top: 10px;<br />margin-right: 10px;<br />margin-bottom: 10px;<br />}<br />a.tit { <br />font-size: 16px; <br />font-weight:bold; <br />color:#000099; <br />}<br />a.tit:visited { <br />color:#005; <br />font-style:italic; <br />}<br />a.tit:hover { <br />color:#0000EE; <br />}<br />a.url {<br />color: #006633;<br />font-weight: bold;<br />}<br />a.url:visited { color:#666; font-style:italic; }<br />.tabela {<br />background-color:#FAFAFA;<br />margin-bottom:10px;<br />border:1px dotted #ccc;<br />width:500px;<br />}<br />.tabela td {<br />padding:5px;<br />}<br />fieldset.mapset {<br />padding:10px;<br />width:450px;<br />border:none;<br />margin-left:20px;<br />border-left:3px solid #E8E8E8;<br />}<br />fieldset.mapset legend {<br />font-size:120%;<br />color:#663333;<br />padding:3px;<br />}<br />&#8211;&gt;<br />&lt;/style&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;?php <br />// criei essa fun&ccedil;&atilde;o dentro do BODY para poder editar o html (&#8230;)<br />function printTree($tree, $host = &#8216;&#8217;, $retrue = false) {<br />$subs = array();<br />if($retrue) ob_start();<br />foreach($tree as $ind =&gt; $arr) {<br />if(is_string($ind) and count($arr) &gt; 0) { // guarda as pastas para inserir no fim da lista<br />$sbs = printTree($arr, $host, true);<br />if(!empty($sbs)) <br />$subs[] = &quot;&lt;fieldset class=\&quot;mapset\&quot;&gt;&lt;legend&gt;Diret&amp;oacute;rio: &quot;.<br />&quot;&lt;strong&gt;$ind&lt;/strong&gt;&lt;/legend&gt;&quot;.$sbs.&quot;&lt;/fieldset&gt;&quot;;<br />continue;<br />}/**/<br />if(empty($arr[&#8217;url&#8217;]) or empty($arr[&#8217;title&#8217;])) continue;<br />// descomente para excluir da lista as páginas sem descri&ccedil;&atilde;o<br />//if(empty($arr[&#8217;description&#8217;])) continue;<br />if($host) $arr[&#8217;url&#8217;] = preg_replace(&quot;/^\./&quot;, preg_replace(&quot;/\/?$/&quot;, &quot;&quot;, $host), $arr[&#8217;url&#8217;]);<br />?&gt;<br />&lt;table class=&quot;tabela&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;<br />&lt;tr&gt;<br />&lt;td&gt;&lt;a class=&quot;tit&quot; href=&quot;&lt;?=$arr[&#8217;url&#8217;]?&gt;&quot;&gt;&lt;?=$arr[&#8217;title&#8217;]?&gt;&lt;/a&gt;&lt;/td&gt;<br />&lt;/tr&gt;<br />&lt;?php if(!empty($arr[&#8217;description&#8217;])) { ?&gt;<br />&lt;tr&gt;<br />&lt;td&gt;&lt;?=$arr[&#8217;description&#8217;]?&gt;&lt;/td&gt;<br />&lt;/tr&gt;<br />&lt;?php } ?&gt;<br />&lt;tr&gt;<br />&lt;td&gt;&lt;a class=&quot;url&quot; href=&quot;&lt;?=$arr[&#8217;url&#8217;]?&gt;&quot;&gt;&lt;?=$arr[&#8217;url&#8217;]?&gt;&lt;/a&gt;&lt;/td&gt;<br />&lt;/tr&gt;<br />&lt;/table&gt;<br />&lt;?php<br />}<br />if(count($subs) &gt; 0) print join(&quot;\n&quot;,$subs);<br />if($retrue) return ob_get_clean();<br />}<br />?&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</p>
	<p>Como vimos, o arquivo é uma página - depois de configurado, basta exibir no navegador. Pode-se editar o HTML e o CSS na página, naturalmente. Espero que seja útil ao menos como base para algo mais detalhado. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/20/9/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Data em Javascript como na função date() do PHP</title>
		<link>http://cauguanabara.blogsome.com/2006/11/15/6/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/15/6/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 20:47:52 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>PHP</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/15/6/</guid>
		<description><![CDATA[	Sempre tive a idéia de que trabalhar com datas no Javascript era algo chato, que exigia muitas linhas de código para se conseguir algo simples. Bem, isso hoje certamente n&atilde;o é mais verdade, com a quantidade de scripts e frameworks e todo tipo de interfaces para facilitar a vida do programador, mas resolvi fazer um [...]]]></description>
			<content:encoded><![CDATA[	<p>Sempre tive a idéia de que trabalhar com datas no Javascript era algo chato, que exigia muitas linhas de código para se conseguir algo simples. Bem, isso hoje certamente n&atilde;o é mais verdade, com a quantidade de scripts e frameworks e todo tipo de interfaces para facilitar a vida do programador, mas resolvi fazer um script que me permitisse manipular strings de data t&atilde;o facilmente como no PHP. Naturalmente, nem todas as op&ccedil;&otilde;es de date() est&atilde;o disponíveis aqui, mas acredito que facilitou muito o trabalho de colher e formatar informa&ccedil;&otilde;es separadas para formar um frase simples como &#8216;Segunda, 3 de maio de 2006&#8242;.</p>
	<p>Criei ent&atilde;o alguns novos métodos adicionados ao objeto Date.prototype. O principal deles é o Date.toFormattedString(), que devolve a string enviada, com alguns caracteres especiais convertidos para valores de data e hora (<a href="#stab">veja a tabela de substitui&ccedil;&atilde;o</a>), como na <a href="http://www.php.net/date">fun&ccedil;&atilde;o date() do PHP</a>. <br />O resultado pode ser em ingl&ecirc;s ou portugu&ecirc;s, mas pode-se também definir outros idiomas dinamicamente. Além do Date.toFormattedString(), há algumas outras funcionalidades. Segue o script e algumas explica&ccedil;&otilde;es. </p>
<a id="more-6"></a>
<p>Há métodos para: </p>
	<ul>
<li>Formatar data de acordo com uma string de formata&ccedil;&atilde;o </li>
	<li>Trabalhar com nomes de dias e meses em qualquer idioma </li>
	<li>Converter datas para o formato aceito em arquivos RSS (RFC 2822) </li>
	<li>Converter datas para o formato aceito em arquivos ATOM (RFC 3339) </li>
	<li>Determinar o fuso horário em horas, minutos ou segundos </li>
	<li>Manter os valores do objeto sempre atualizados </li>
	<li>Acionar uma fun&ccedil;&atilde;o de relógio a intervalos regulares </li>
	<li>Métodos extras
<ul>
<li>Array.walk -&gt; aplica determinada fun&ccedil;&atilde;o a todos os elementos do array </li>
	<li>String.UCFirst -&gt; transforma a primeira letra da string para caixa alta </li>
</ul>
</li>
</ul>
	<p>Pegue o arquivo aqui <a href="http://sistemas.algobrasil.com.br/js/date.prototype.js" target="_self">date.prototype.js</a></p>
	<p>Exemplo de uso: </p>
	<div class="codigo">var dat = new Date(); <br />var uc_output = dat.toFormattedString(&#8217;l, j \de F&#8217;); <br />var lc_output = dat.toFormattedString(&#8217;l, j \de F&#8217;, &#8216;m&#8217;); <br />alert(uc_output+&#8217; - &#8216;+lc_output); <br />// mostra algo como: Ter&ccedil;a, 5 de Setembro - Ter&ccedil;a, 5 de setembro </div>
	<p>Podemos definir o idioma de saída da fun&ccedil;&atilde;o toFormattedString(). <br />Para isso há os métodos addLang() e setLang(), que devem ser chamados <strong>antes</strong> de toFormattedString().<br />Apenas os idiomas ingl&ecirc;s (&#8217;en&#8217;) e portugu&ecirc;s (&#8217;pt-br&#8217;) est&atilde;o disponíveis no sistema e o padr&atilde;o é ingl&ecirc;s. <br />Para usar portugu&ecirc;s, basta chamar setLang(), passando o par&acirc;metro &#8216;pt-br&#8217;.</p>
	<p><strong>Segue uma pequena refer&ecirc;ncia das fun&ccedil;&otilde;es:</strong></p>
	<div class="codigo">
<h3>boolean Date.addLang(lang_id, days, months)</h3>
<br />string lang_id -&gt; string identificador do idioma (&#8217;en&#8217;, &#8216;it&#8217;, &#8216;pt-br&#8217;, etc&#8230;) <br />array days -&gt; nomes dos dias num array (domingo a sábado) <br />array_months -&gt; nomes dos meses num array (janeiro a dezembro) </div>
	<p>Adiciona nomes de dias e meses em um idioma ao sistema. Equivale a definir as propriedades Date.days[&#8217;id_do_idioma&#8217;] (array com os nomes dos dias) e Date.months[&#8217;id_do_idioma&#8217;] (array com os nomes dos meses) com os nomes enviados. Veja o exemplo 1. </p>
	<div class="codigo">
<h3>boolean Date.setLang(lang_id)</h3>
string lang_id -&gt; string identificador do idioma (&#8217;en&#8217;, &#8216;it&#8217;, &#8216;pt-br&#8217;, etc&#8230;) </div>
	<p>Define o idioma de trabalho para id enviado. O id precisa fazer refer&ecirc;ncia a um idioma existente (&#8217;en&#8217; ou &#8216;pt-br&#8217;) ou que tenha sido adicionado previamente com Date.addLang(). Equivale a definir a propriedade Date.lang para o id enviado. Veja o exemplo 1.</p>
	<p>Para adicionar e selecionar um idioma, use addLang() e depois setLang(), assim:</p>
	<div class="codigo">// Exemplo 1 - adicionando o idioma italiano, por ex. <br />var dat = new Date(); <br />var days = [&quot;domenica&quot;, &quot;luned&igrave;&quot;, &quot;marted&igrave;&quot;, &quot;mercoled&igrave;&quot;, &quot;gioved&igrave;&quot;, &quot;venerd&igrave;&quot;, &quot;sabato&quot;]; <br />var months = [&quot;gennaio&quot;, &quot;febbraio&quot;, &quot;marzo&quot;, &quot;aprile&quot;, &quot;pu&ograve;&quot;, &quot;giugno&quot;, &quot;luglio&quot;, &quot;agosto&quot;, &quot;settembre&quot;, &quot;ottobre&quot;, &quot;novembre&quot;, &quot;dicembre&quot;]; <br />dat.addLang(&#8217;it&#8217;, days, months); // adiciona o idioma <br />dat.setLang(&#8217;it&#8217;); // seleciona o idioma </div>
	<p><strong>Para retornar valores formatados segundo especifica&ccedil;&otilde;es oficiais, há os métodos toRFC2822 e toRFC3339. </strong></p>
	<div class="codigo">
<h3>string Date.toRFC2822() sem par&acirc;metros</h3>
<br />var dat = new Date();<br />alert(dat.toRFC2822()); <br />// mostra algo como: Tue, 5 Sep 2006 14:17:32 +03:00 </div>
	<p>Essa fun&ccedil;&atilde;o formata a data definida ao instanciar o objeto Date() de acordo com as especifica&ccedil;&otilde;es no RFC 2822.<br />&gt;&gt; Tipo de data suportado em formatos RSS.</p>
	<div class="codigo">
<h3>string Date.toRFC3339(no_timezone)</h3>
<br />boolean no_timezone -&gt; se true, retorna uma string sem a parte time zone (AAAA:MM:DDTHH:MM:SSZ) </div>
	<p>Essa fun&ccedil;&atilde;o formata a data definida ao instanciar o objeto Date() de acordo com as especifica&ccedil;&otilde;es no RFC 3339.<br />&gt;&gt; Tipo de data suportado em formatos ATOM. </p>
	<div class="codigo">var dat = new Date(); <br />alert(dat.toRFC3339()); // mostra algo como: 2006-09-05T14:17:32+03:00 <br />alert(dat.toRFC3339(true)); // mostra algo como: 2006-09-05T14:17:32Z</div>
	<p><strong>Quando instanciamos um objeto Date, a hora de trabalho é relativa ao momento em que este foi instanciado</strong>. <br />Para construir um relógio, por exemplo, com precis&atilde;o de segundos, normalmente se executa uma fun&ccedil;&atilde;o que instancia o objeto novamente a cada segundo, para obter a hora atualizada. A fun&ccedil;&atilde;o descrita a seguir executa esse processo, sem precisar instanciar o objeto novamente. </p>
	<div class="codigo">
<h3>Date.setClock([interval [, code]])</h3>
<br />number interval -&gt; intervalo de tempo em milissegundos para a atualiza&ccedil;&atilde;o <br />string code -&gt; código (como string) a ser executado a cada atualiza&ccedil;&atilde;o </div>
	<p>Mantém o momento para o qual o objeto Date aponta sempre atualizado, de acordo com o par&acirc;metro interval ou a cada 1 segundo, se ele for omitido.. Se seu relógio n&atilde;o precisa de segundos (ou se n&atilde;o se trata de um relógio), seria aconselhável definir interval com um intervalo maior (1 minuto, por exemplo). Opcionalmente, executa a string de código code a cada atualiza&ccedil;&atilde;o. Isso torna possível usar o método como uma espécie de setInterval, onde code é executado a cada interval milisegundos. Voc&ecirc; pode querer apenas ter o objeto atualizado, para quando o usuário executar determinada a&ccedil;&atilde;o, a hora estar certa. Para isso basta executar o método enviando o par&acirc;metro interval ou nenhum.</p>
	<p><strong>Métodos extra </strong></p>
	<div class="codigo">
<h3>string String.UCFirst()</h3>
<br />Converte a primeira letra da string para caixa alta </p>
	<h3>array Array.walk(func)</h3>
<br />function func -&gt; fun&ccedil;&atilde;o a ser aplicada aos elementos do array <br />Transforma todos os elementos do array através da fun&ccedil;&atilde;o enviada.
<p>&nbsp;</p>
</div>
<a name="stab"></a>
<p><strong>Tabela de substitui&ccedil;&atilde;o </strong></p>
	<table cellspacing="0" cellpadding="5" border="0">
<tr>
<td align="center"><strong>Caracter</strong></td>
	<td align="center"><strong>Descri&ccedil;&atilde;o</strong></td>
	<td align="center"><strong>Exemplos de retorno</strong></td>
</tr>
	<tr>
<td align="center"><strong>a</strong></td>
	<td>Ante / pós meio dia (minúsculas) </td>
	<td align="right">am / pm</td>
</tr>
	<tr>
<td align="center"><strong>A</strong></td>
	<td>Ante / pós meio dia (maiúsculas) </td>
	<td align="right">AM / PM</td>
</tr>
	<tr>
<td align="center"><strong>d</strong></td>
	<td>Dia do m&ecirc;s (2 digitos)</td>
	<td align="right">01 - 31</td>
</tr>
	<tr>
<td align="center"><strong>D</strong></td>
	<td>Dia da semana, 3 letras</td>
	<td align="right">dom - sáb </td>
</tr>
	<tr>
<td align="center"><strong>F</strong></td>
	<td>Nome de um m&ecirc;s</td>
	<td align="right">janeiro - dezembro</td>
</tr>
	<tr>
<td align="center"><strong>g</strong></td>
	<td>Horas, formato 12h (1-2 dígitos) </td>
	<td align="right">1 - 12 </td>
</tr>
	<tr>
<td align="center"><strong>G</strong></td>
	<td>Horas, formato 24h (1-2 dígitos) </td>
	<td align="right">0 - 23 </td>
</tr>
	<tr>
<td align="center"><strong>h</strong></td>
	<td>Horas, formato 12h (2 dígitos) </td>
	<td align="right">01 - 12</td>
</tr>
	<tr>
<td align="center"><strong>H</strong></td>
	<td>Horas, formato 24h (2 dígitos) </td>
	<td align="right">00 - 23</td>
</tr>
	<tr>
<td align="center"><strong>i</strong></td>
	<td>Minutos </td>
	<td align="right">00 - 59</td>
</tr>
	<tr>
<td align="center"><strong>j</strong></td>
	<td>Dia do m&ecirc;s (1-2 dígitos) </td>
	<td align="right">1 - 31 </td>
</tr>
	<tr>
<td align="center"><strong>l</strong></td>
	<td>Dia da semana</td>
	<td align="right">domingo - sábado</td>
</tr>
	<tr>
<td align="center"><strong>m</strong></td>
	<td>M&ecirc;s (2 dígitos) </td>
	<td align="right">01 - 12</td>
</tr>
	<tr>
<td align="center"><strong>M</strong></td>
	<td>Nome de um m&ecirc;s, 3 letras</td>
	<td align="right">jan - dez </td>
</tr>
	<tr>
<td align="center"><strong>n</strong></td>
	<td>M&ecirc;s (1-2 dígitos) </td>
	<td align="right">1 - 12 </td>
</tr>
	<tr>
<td align="center"><strong>s</strong></td>
	<td>Segundos</td>
	<td align="right">00 - 59</td>
</tr>
	<tr>
<td align="center"><strong>U</strong></td>
	<td>Segundos desde 1970-01-01 00:00:00 </td>
	<td align="right">Ex.: 1157322265473</td>
</tr>
	<tr>
<td align="center"><strong>w</strong></td>
	<td>Representa&ccedil;&atilde;o numérica do dia da semana</td>
	<td align="right">0 (domingo) - 6 (sábado)</td>
</tr>
	<tr>
<td align="center"><strong>Y</strong></td>
	<td>Ano, 4 dígitos</td>
	<td align="right">Ex.: 1999 ou 2003</td>
</tr>
	<tr>
<td align="center"><strong>y</strong></td>
	<td>Ano, 2 dígitos</td>
	<td align="right">Ex: 99 ou 03</td>
</tr>
	<tr>
<td align="center"><strong>Z</strong></td>
	<td>Fuso horário em minutos </td>
	<td align="right">Ex.: 180 (+03:00) </td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/15/6/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Ajax e bookmark - adicionando conteúdos dinâmicos aos favoritos</title>
		<link>http://cauguanabara.blogsome.com/2006/11/15/ajax-e-bookmark-adicionando-conteudos-dinamicos-aos-favoritos/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/15/ajax-e-bookmark-adicionando-conteudos-dinamicos-aos-favoritos/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 19:18:12 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>Web 2.0</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/15/ajax-e-bookmark-adicionando-conteudos-dinamicos-aos-favoritos/</guid>
		<description><![CDATA[	Quando uma página tem seu conteúdo carregado de forma assíncrona (via ajax), ocorre um conhecido problema ao tentar salvá-la nos favoritos. A n&atilde;o ser que o usuário adicione a página logo que ela carregar - quando nenhuma a&ccedil;&atilde;o foi executada, nenhum clique foi dado - quando ele clicar no link salvo em favoritos, o conteúdo [...]]]></description>
			<content:encoded><![CDATA[	<p>Quando uma página tem seu conteúdo carregado de forma assíncrona (via ajax), ocorre um conhecido problema ao tentar salvá-la nos favoritos. A n&atilde;o ser que o usuário adicione a página logo que ela carregar - quando nenhuma a&ccedil;&atilde;o foi executada, nenhum clique foi dado - quando ele clicar no link salvo em favoritos, o conteúdo apresentado será sempre o inicial e n&atilde;o aquele que ele estava vendo no momento em que salvou a página. </p>
	<p>A raiz desse problema é a mesma que impede o usuário de usar os bot&otilde;es do histórico em conteúdos carregados com ajax: a única página que existe para o navegador é a inicial, os conteúdos carregados com ajax n&atilde;o s&atilde;o vistos como novas páginas. Como resolver isso? Me ocorreu a idéia de enviar um comando em forma de string (como no script <a href="http://cauguanabara.blogspot.com/2006/11/histrico-do-browser-para-navegao-via.html" target="_blank">ajaxHistory</a>) usando o hash. Na verdade, o hash foi usado (no lugar da query string) por que eu queria poder também usar o refresh&#8230; isso funcionou, mas só no IE. Quando a solu&ccedil;&atilde;o para o refresh for cross-browser (estamos trabalhando para isso&#8230;), vou divulgá-la aqui. Mas para usar os favoritos funcionou beleza. </p>
<a id="more-5"></a>
<p>A idéia é a seguinte: criei uma fun&ccedil;&atilde;o que adiciona a página aos favoritos dinamicamente, acrescentando um comando javascript &agrave; URL, no hash (se o usuário for ao menu Favoritos e clicar em Adicionar a favoritos o sistema n&atilde;o vai funcionar). Ao carregar, uma outra fun&ccedil;&atilde;o l&ecirc; a URL e busca pelo comando, se ele existir, será executado no onload e o hash será esvaziado.</p>
	<p>O princípio é bastante simples. Salvamos a página com um comando no hash que, se executado reproduz o estado da página no momento em que o usuário a salvou e executamos esse comando no onload da página. É preciso ser detalhista na hora de escrever essa string de comando, pois muitas vezes n&atilde;o basta executar a fun&ccedil;&atilde;o que carrega os conteúdos, é preciso recriar todo um ambiente, setando variáveis e criando elementos. </p>
	<p>Há uma variável-chave para o sistema funcionar, a jscommand. Ela deve ser atualizada a cada a&ccedil;&atilde;o, com a string de comando. Se voc&ecirc; resolveu usar o script <a href="http://cauguanabara.blogspot.com/2006/11/histrico-do-browser-para-navegao-via.html" target="_blank">ajaxHistory</a>, fique atento por que nem sempre a string de comando será igual - quando executamos os comando do array de itens do histórico, trabalhamos num mesmo ambiente. Por outro lado, quando o sujeito voltar &agrave; nossa página a partir de um clique no seu menu Favoritos, esse ambiente deve ser inteiramente recriado, portanto, &agrave; vezes o comando para o ajaxBookmark, na variável jscommand precisa ser mais complexo. </p>
	<p>Vamos ao código, pequeno e simples:</p>
	<div class="codigo">/* ajax_bookmarks.js */</p>
	<p>var isIE = (/msie/i.test(navigator.userAgent) &amp;&amp; document.all), // é Internet Explorer?<br />jscommand = &#8216;&#8217;; // aqui criamos a var. que irá guardar o comando atual</p>
	<p>// adiciona aos favoritos - chamada a partir de um bot&atilde;o ou link tipo &#8216;Bookmark this page&#8217;<br />function ajaxBookmark() {<br />var loc = jscommand == &#8216;&#8217; ? location.href : // se jscommand está vazia, usa a URL como está<br />// sen&atilde;o, redefine o hash adicionando a string de comando<br />location.href.split(&#8217;#')[0]+&#8217;#jscommand:&#8217;+encodeURIComponent(jscommand);<br />if(isIE) window.external.AddFavorite(loc, document.title); // IE<br />else if(window.sidebar) window.sidebar.addPanel(document.title, loc, &quot;&quot;); // Mozilla<br />else alert(&#8217;N&atilde;o foi possível adicionar esta página aos favoritos automaticamente.\n&#8217;+<br />&#8216;Por favor, pressione CTRL + D para adicionar manualmente.&#8217;); // ???<br />}</p>
	<p>// usada para checar o hash - deve ser chamada no onload da página<br />function checkHashCommand() {<br />if(/#?jscommand\:(.+)$/.test(location.hash)) { // testa se o comando existe e em caso positivo<br />jscommand = decodeURIComponent(RegExp.$1); // define o comando em jscommand<br />// e tenta executar a string e limpar o hash<br />try { new Function(jscommand)(); location.hash = &#8216;&#8217;; }<br />catch(e) { }<br />}<br />}</div>
	<p>Um exemplo de uso (com <a href="http://cauguanabara.blogspot.com/2006/11/histrico-do-browser-para-navegao-via.html" target="_blank">ajaxHistory</a>) </p>
	<div class="codigo">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;<br />&lt;title&gt;teste ajax&lt;/title&gt;<br />&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />&lt;head&gt;<br />&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;../js/ajax_history.js&quot;&gt;&lt;/script&gt;<br />&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;../js/ajax_bookmarks.js&quot;&gt;&lt;/script&gt;<br />&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt;<br />// inicializa o sistema e o histórico<br />function ajaxFeatures() {<br />checkHashCommand();<br />ajaxHistory.activateBrowserHistory();<br />}<br />// executa um comando recebido como string<br />function execute(comm, capt) {<br />try { new Function(comm)(); if(capt) document.title = capt; }<br />catch(e) { return; }<br />ajaxHistory.add(comm, capt);<br />jscommand = comm; // setando o comando atual<br />}<br />&lt;/script&gt;<br />&lt;/head&gt;<br />&lt;!&#8211; chamar checkHashCommand() no onload é fundamental!!! &#8211;&gt;<br />&lt;body onload=&quot;ajaxFeatures();&quot;&gt;<br />Clique num dos links e depois em &#8216;Bookmark&#8217; para salvar nos Favoritos,&lt;br /&gt;<br />Vá para outra página e depois volte a partir dos seus Favoritos e&lt;br /&gt;<br />repare no texto exibido abaixo do link &#8216;Bookmark this page&#8217;&lt;br /&gt;&lt;br /&gt;<br />&lt;!&#8211; para usar a fun&ccedil;&atilde;o execute(), foi preciso o &#8216;return false&#8217; nos links&#8230; &#8211;&gt;<br />&lt;p&gt;&lt;a href=&quot;javascript://&quot; onclick=&quot;<br />execute(&#8217;document.getElementById(\&#8217;see\&#8217;).innerHTML = \&#8217;link 1\&#8217;;',&#8217;link 1&#8242;);<br />return false;&quot;&gt;link 1&lt;/a&gt;&lt;br /&gt;<br />&lt;a href=&quot;javascript://&quot; onclick=&quot;<br />execute(&#8217;document.getElementById(\&#8217;see\&#8217;).innerHTML = \&#8217;link 2\&#8217;;',&#8217;link 2&#8242;);<br />return false;&quot;&gt;link 2&lt;/a&gt;&lt;br /&gt;<br />&lt;a href=&quot;javascript://&quot; onclick=&quot;<br />execute(&#8217;document.getElementById(\&#8217;see\&#8217;).innerHTML = \&#8217;link 3\&#8217;;',&#8217;link 3&#8242;);<br />return false;&quot;&gt;link 3&lt;/a&gt; &lt;/p&gt;<br />&lt;p&gt;&lt;a href=&quot;javascript://Adicionar aos Favoritos&quot; onclick=&quot;<br />ajaxBookmark()&quot;&gt;Bookmark this page&lt;/a&gt;&lt;/p&gt;<br />&lt;p id=&quot;see&quot;&gt;&lt;/p&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</div>
	<p>Bem, a princípio isso me pareceu uma boa solu&ccedil;&atilde;o, mas n&atilde;o funcionou satisfatoriamente em FF 1.5 e NS 7.2. Coisas estranhas acontecem, como a página ser carregada na barra lateral e o resultado da fun&ccedil;&atilde;o n&atilde;o ser igual para NS e FF. A fun&ccedil;&atilde;o addPanel na verdade n&atilde;o adiciona um item aos Favoritos, apenas cria um panel no Sidebar&#8230; N&atilde;o sou usuário de Mozilla, uso apenas para testar (digo isso sabendo que vai parecer um sacrilégio para alguns, mas tenho que confessar: eu uso o IE!). </p>
	<p>Espero que aproveitem a idéia mas, principalmente, espero que alguém que conhe&ccedil;a os meandros do Netscape e do Firefox tenha uma boa idéia e possa fazer um ajuste. </p>
	<p>Sugest&otilde;es e comentários s&atilde;o muito bemvindos. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/15/ajax-e-bookmark-adicionando-conteudos-dinamicos-aos-favoritos/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Padrão Web 2.0 - será ficção?</title>
		<link>http://cauguanabara.blogsome.com/2006/11/15/padrao-web-20-sera-ficcao/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/15/padrao-web-20-sera-ficcao/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 15:34:42 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
	<category>Web 2.0</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/15/padrao-web-20-sera-ficcao/</guid>
		<description><![CDATA[	O novo conceito criado há pouco tempo tem dividido opini&otilde;es e gerado muita pol&ecirc;mica. Nunca houve uma &lsquo;Web 1.0&rsquo;, ent&atilde;o que estória é essa? Bem, vamos tentar explicar&#8230;
	O assunto é delicado, pois uma parcela considerável dos profissionais da área considera que o termo n&atilde;o passa de uma &lsquo;buzzword&rsquo; (um termo belo, mas vazio de significado [...]]]></description>
			<content:encoded><![CDATA[	<p>O novo conceito criado há pouco tempo tem dividido opini&otilde;es e gerado muita pol&ecirc;mica. Nunca houve uma &lsquo;Web 1.0&rsquo;, ent&atilde;o que estória é essa? Bem, vamos tentar explicar&#8230;</p>
	<p>O assunto é delicado, pois uma parcela considerável dos profissionais da área considera que o termo n&atilde;o passa de uma &lsquo;buzzword&rsquo; (um termo belo, mas vazio de significado real), que é apenas uma onda criada para explorar a necessidade de constante atualiza&ccedil;&atilde;o exigida aos profissionais da área, etc., e que os criadores dessa &lsquo;palavra mágica&rsquo; (que sacudiu toda a área de TI) ganham muito dinheiro divulgando e ensinando algo que eles próprios inventaram - uma espécie de golpe de marketing. Bem, este é um ponto de vista embasado e tem suas raz&otilde;es de ser, mas somente após conhecer as tecnologias, idéias e conceitos por trás da legenda &lsquo;Web 2.0&rsquo; é que poderemos julgar. Portanto, m&atilde;os &agrave; obra.</p>
<a id="more-3"></a>
<p>Come&ccedil;aremos dizendo que &lsquo;Web 2.0&rsquo; n&atilde;o é uma linguagem, nem um programa, nem um protocolo nem nada do g&ecirc;nero. É apenas uma idéia, um conjunto de &lsquo;regras&rsquo; que sugerem uma nova maneira de fazer e usar a internet. Algumas tecnologias novas (e outras nem tanto) associadas a conceitos como padroniza&ccedil;&atilde;o, usabilidade e interatividade e ao &lsquo;novo nível&rsquo; de capacita&ccedil;&atilde;o da média dos internautas mudou o panorama da web e um &lsquo;novo paradigma&rsquo; precisou ser formulado &ndash; e esse novo paradigma foi chamado &lsquo;Web 2.0&rsquo;.</p>
<strong>Principais conceitos envolvidos</strong>
<ul>
<li><strong>Conteúdo participativo</strong> A possibilidade de interatividade e participa&ccedil;&atilde;o do usuário na cria&ccedil;&atilde;o e classifica&ccedil;&atilde;o dos conteúdos passou a ser uma característica comum a grande parte dos sites de sucesso atualmente e estudos comprovam que cada vez mais o internauta valoriza sites que permitem sua participa&ccedil;&atilde;o. Tanto que empresas como Yahoo! e Google est&atilde;o envolvidos de corpo e alma na afirma&ccedil;&atilde;o desses novos conceitos. </li>
	<li><strong>Classifica&ccedil;&atilde;o pessoal dos conteúdos</strong> Foram criados alguns sites que viraram sucesso imediato, como o del.icio.us, que permitem ao usuário classificar endere&ccedil;os da web com TAGs (rótulos) personalizados, organizando a &lsquo;sua internet&rsquo; a sua própria maneira, além de poder compartilhar sua rela&ccedil;&atilde;o de &lsquo;favoritos online&rsquo; com outros internautas. É o que se chama hoje &lsquo;social-bookmarking&rsquo; ou &lsquo;tagsonomia&rsquo;. </li>
	<li><strong>Design e usabilidade</strong> O design também sofre modifica&ccedil;&otilde;es com a Web 2.0, tendendo a um estilo mais clean, que valoriza também os espa&ccedil;os em branco. Primeiro que a preocupa&ccedil;&atilde;o com o grau de usabilidade do site passa a ser primordial, depois, a variedade de tipos de mídia e tamanhos de monitor torna a apresenta&ccedil;&atilde;o do site uma quest&atilde;o bem mais complexa, exigindo o uso de CSS. A informa&ccedil;&atilde;o deve estar &agrave; m&atilde;o, a poucos cliques de dist&acirc;ncia e dentro de uma hierarquia de organiza&ccedil;&atilde;o que seja de fácil entendimento ao usuário. </li>
	<li><strong>Novas tecnologias e novas abordagens para velhos temas</strong> O Javascript, linguagem de script natural do HTML, surgiu para dar um mínimo de autonomia &agrave;s páginas HTML. Mas hoje, na vers&atilde;o 1.5, o Javascript é uma linguagem de programa&ccedil;&atilde;o poderosa, capaz de interagir com outras linguagens e possibilitando ao desenvolvedor criar sistemas mais rápidos e confortáveis, efetivamente mais interativos. Enfim, mais próximos das aplica&ccedil;&otilde;es de desktop. </li>
	<li><strong>A web como plataforma de desenvolvimento</strong> Acabou a era do conteúdo estático. Ao invés de &lsquo;páginas&rsquo;, agora teremos cada vez mais &lsquo;programas&rsquo; online. A rede passou a oferecer tudo: linguagens de servidor / cliente mais poderosas, com alta portabilidade, além de conteúdo farto - muitos sites passaram a oferecer seus conteúdos na forma de servi&ccedil;os ou &lsquo;web-services&rsquo;, que podem ser acessados e utilizados por outros sites ou aplicativos. </li>
	<li><strong>Sintetizando conteúdos</strong> Com o advento dos &lsquo;web-services&rsquo;, tornou-se possível organizar conteúdos de várias fontes numa única página e vários sites come&ccedil;aram a oferecer esse tipo de servi&ccedil;o, denominado &lsquo;mash-up&rsquo;. Esses sites tem uma rela&ccedil;&atilde;o de conteúdos disponíveis e o usuário &lsquo;monta&rsquo; sua própria página. </li>
	<li><strong>Padroniza&ccedil;&atilde;o </strong>Com a diversidade de recursos e tipos de dispositivos de mídia capazes de exibir um site da internet, a necessidade de seguir certos padr&otilde;es de desenvolvimento se tornou maior que nunca. A internet, essa verdadeira &lsquo;Torre de Babel&rsquo;, precisava mesmo de um pouco de ordem&#8230; Surgiu ent&atilde;o a W3C e outras organiza&ccedil;&otilde;es com a finalidade de promover essa &lsquo;lineariza&ccedil;&atilde;o&rsquo;, para que em breve tempo n&atilde;o precisemos nos preocupar com as diferen&ccedil;as entre os navegadores. O que chamamos de &lsquo;programa&ccedil;&atilde;o crossbrowser&rsquo; é na verdade um conjunto de &lsquo;gatilhos&rsquo; para evitar um problema que é, em ess&ecirc;ncia, desnecessário.</li>
</ul>
	<p><strong>A justificativa da nega&ccedil;&atilde;o</strong></p>
	<p>A verdade é que as tecnologias que servem &agrave; internet v&ecirc;m se aprimorando (e se modificando) desde que tudo come&ccedil;ou. O ambiente da internet foi concebido originalmente para suportar a linguagem HTML, com textos, imagens, links, sons, enfim, poucas op&ccedil;&otilde;es de componentes para exibir um conteúdo estático e n&atilde;o-interativo, mas isso come&ccedil;ou a se modificar imediatamente e num processo gradual e constante, até chegar ao que é a internet hoje. Isso significa que o que alardeiam como &lsquo;Web 2.0&rsquo; n&atilde;o passa da evolu&ccedil;&atilde;o natural da coisa e que se ninguém falasse nada a respeito, n&atilde;o faria a menor diferen&ccedil;a. Todos os tópicos citados acima como diretrizes de um novo movimento, já existem há tempos, excetuando-se as funcionalidades adicionadas pelas novas vers&otilde;es de programas e linguagens envolvidos no processo. Ent&atilde;o qual a vantagem de vender esse peixe agora, como se fosse um &lsquo;novo produto&rsquo;, quando tudo n&atilde;o passa da mesma coisa de sempre?</p>
	<p><strong>Qual a vantagem?</strong></p>
	<p>A vantagem está justamente em alardear a Web 2.0 como &lsquo;a nova realidade da internet&rsquo;, como um &lsquo;novo padr&atilde;o a seguir&rsquo;, criando com isso a possibilidade de &lsquo;moldar o futuro&rsquo; e criar padr&otilde;es para orientar os desenvolvedores e evitar que a confus&atilde;o que reina há tanto tempo permane&ccedil;a. &lsquo;Web 2.0&rsquo; é um marco, um divisor de águas, uma mudan&ccedil;a de paradigma muito bem vinda, mas n&atilde;o é algo fácil de apreender nem nada palpável&#8230; é apenas uma idéia. E só quem navega com alguma facilidade pelo oceano das idéias percebe que o mundo das coisas palpáveis é o apenas o reflexo delas. S&atilde;o as idéias que d&atilde;o origem &agrave;s coisas e qualquer movimento sem a sustenta&ccedil;&atilde;o de uma idéia é vazio de significado. Um pouco de filosofia talvez ajude a explicar o que quero dizer: web 2.0 n&atilde;o passa de uma idéia, mas a partir dessa idéia vamos conseguir, no futuro, uma atitude mais coerente e embasada por parte dos <em>zilh&otilde;es</em> de webdesigners e webdevelopers pelo mundo afora. Se todos que tem uma tesoura se dissessem barbeiros e cabeleireiros, já imaginou como seriam os cabelos por aí? &#8230; certamente iguais a certos sites que ainda vemos em grande número na internet&#8230;</p>
	<p><strong>Web 2.0, ok. Mas quando isso acontecerá?</strong></p>
	<p>Surpresa: já acontece há algum tempo. É isso mesmo, a Web 2.0 já é uma realidade, nós é que n&atilde;o tínhamos percebido. O termo foi usado pela primeira vez simplesmente para definir o abismo que há entre os sites da década de 90 e os atuais, e entre a atitude dos internautas daquela época e a dos de hoje &ndash; melhor informados, mais familiarizados com os processos e interfaces da internet e principalmente mais exigentes e participativos. Como foi dito no tópico acima, o termo &lsquo;Web 2.0&rsquo; veio apenas &lsquo;batizar&rsquo; a nova maneira de fazer, separando o joio do trigo e determinando certas diretrizes de procedimento para o futuro.</p>
	<p><strong>Um movimento maior e anterior&#8230;</strong></p>
	<p>Antes de se inventar o termo web 2.0, já havia um movimento no sentido de padronizar a internet, com a cria&ccedil;&atilde;o de organiza&ccedil;&otilde;es como a w3c e outras, que tem por finalidade desenvolver padr&otilde;es (comumente chamados &lsquo;web-standarts&rsquo;) para imprimir um certa ordem &agrave; bagun&ccedil;a que é a internet. Para os desenvolvedores, principalmente no tocante &agrave;s tecnologias &lsquo;client-side&rsquo;, que dependem do navegador, a padroniza&ccedil;&atilde;o é um sonho, significando uma redu&ccedil;&atilde;o substancial do código. E o termo &lsquo;web 2.0&rsquo; define sites que, além de levar em conta a participa&ccedil;&atilde;o do usuário, abra&ccedil;aram o movimento &lsquo;web-standarts&rsquo; &ndash; que, poderíamos dizer, é a especifica&ccedil;&atilde;o da parte tecnológica do padr&atilde;o definido pelo termo &lsquo;web 2.0&rsquo;. Por este aspecto, o que se chama hoje de &lsquo;web 2.0&rsquo; pode ser visto como uma nova abordagem, mais completa, daquele mesmo movimento que come&ccedil;ou com os web-standarts.</p>
	<p><strong>Conclus&atilde;o</strong></p>
	<p>Bem, visto tudo isso, acho que fica claro que sou um entusiasta da web 2.0. Considero que esse papo de que isso nunca existiu, n&atilde;o significa nada, etc., é coisa de quem n&atilde;o conseguiu perceber as implica&ccedil;&otilde;es implícitas no movimento. A febre &lsquo;web 2.0&rsquo; é apenas um &lsquo;ritual de passagem&rsquo;, algo que veio para lembrar a todos os envolvidos que a web agora mudou. É a evolu&ccedil;&atilde;o natural sim, mas era preciso falar disso, acordar todos e faz&ecirc;-los ouvir. N&atilde;o que os sites padr&atilde;o &lsquo;web 2.0&rsquo; sejam melhores que os mais antigos, mas é que ao seguir as tend&ecirc;ncias globais, voc&ecirc; se torna mais compatível com o futuro, além de dar uma perspectiva de sobreviv&ecirc;ncia maior aos seus sites e poder contar com mais recursos na hora de desenvolv&ecirc;-los.</p>
	<p>O momento é de invers&atilde;o: os usuários, que sempre tiveram que suar a camisa para compreender e usar as interfaces que lhes eram oferecidas, agora t&ecirc;m o comando e est&atilde;o for&ccedil;ando os desenvolvedores a seguir as suas decis&otilde;es. O público agora é rei - é a t&atilde;o falada &lsquo;democracia na rede&rsquo; se tornando realidade. </p>
	<p>Por fim vou afirmar que, mesmo n&atilde;o sendo um conceito t&atilde;o objetivo quanto muitos gostariam, a tal da &lsquo;Web 2.0&rsquo; existe sim - e será um marco na história do desenvolvimento web. </p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/15/padrao-web-20-sera-ficcao/feed/</wfw:commentRss>
	</item>
		<item>
		<title>Histórico do browser para navegação via Ajax</title>
		<link>http://cauguanabara.blogsome.com/2006/11/15/historico-do-browser-para-navegacao-via-ajax/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/15/historico-do-browser-para-navegacao-via-ajax/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 12:48:18 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Javascript</category>
	<category>Web 2.0</category>
	<category>Funções</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/15/historico-do-browser-para-navegacao-via-ajax/</guid>
		<description><![CDATA[	Pesquisei e quebrei a cabe&ccedil;a para achar essa solu&ccedil;&atilde;o&#8230; tanto que questionei entre dar apenas o &#8216;mapa&#8217; ou o script pronto. Mas sou um cara open-source por natureza, por isso vou fazer as duas coisas. 
	Bem, todos já sabemos que comandos em javascript n&atilde;o ativam os bot&otilde;es de histórico do navegador, mesmo que mudem 100% [...]]]></description>
			<content:encoded><![CDATA[	<p>Pesquisei e quebrei a cabe&ccedil;a para achar essa solu&ccedil;&atilde;o&#8230; tanto que questionei entre dar apenas o &#8216;mapa&#8217; ou o script pronto. Mas sou um cara open-source por natureza, por isso vou fazer as duas coisas. </p>
	<p>Bem, todos já sabemos que comandos em javascript n&atilde;o ativam os bot&otilde;es de histórico do navegador, mesmo que mudem 100% do conteúdo exibido. Isso n&atilde;o é legal, pois sabemos que o usuário busca usar os recursos que conhece e o bot&atilde;o &#8216;Voltar&#8217; é uma institui&ccedil;&atilde;o, existe desde que o mundo é mundo. Eu me sentia meio que &#8216;na obriga&ccedil;&atilde;o&#8217; de possibilitar isso ao usuário. </p>
<a id="more-4"></a>
<p>Pensei ent&atilde;o, há alguns meses em uma solu&ccedil;&atilde;o - que me serviu no momento, mas que n&atilde;o ativava os bot&otilde;es, apenas criava um &#8216;histórico de comandos&#8217; num array, com fun&ccedil;&otilde;es para adicionar, exibir e testar itens do histórico. Com isso eu fazia os meus próprios bot&otilde;es de histórico. Achei que fosse suficiente, mas hoje vejo que n&atilde;o, pois na maior parte dos casos o usuário nem entende que há um histórico &#8216;paralelo&#8217; e que ele precisa clicar em outros bot&otilde;es para navegar&#8230; <br />Veja o script original: </p>
	<div class="codigo">var _ajax = {}; // o obj. _ajax era usado para outros fins&#8230; <br />// histórico de comandos - 2006-06-07 <br />_ajax.history = { <br />&#8216;items&#8217;: [], <br />&#8216;currentIndex&#8217;: 0, <br />&#8216;go&#8217;: function(ref) { <br />if(_ajax.history.items[_ajax.history.currentIndex + ref] false) <br />_ajax.history.currentIndex += ref; <br />else return; <br />new Function(_ajax.history.items[_ajax.history.currentIndex])(); <br />}, <br />&#8216;add&#8217;: function (str) { <br />if(str == _ajax.history.items[_ajax.history.currentIndex]) return; <br />_ajax.history.currentIndex = _ajax.history.items.length; <br />_ajax.history.items.push(str); <br />}, <br />&#8216;hasBack&#8217;: function() { <br />return (_ajax.history.items[_ajax.history.currentIndex - 1] || false) ? true : false; <br />}, <br />&#8216;hasForward&#8217;: function() { <br />return (_ajax.history.items[_ajax.history.currentIndex + 1] || false) ? true : false; <br />} <br />}; </div>
	<p>Caí de cabe&ccedil;a atrás da solu&ccedil;&atilde;o, que eu já sabia, tinha algo a ver com a propriedade hash do objeto location. Descobri algumas possibilidades, a come&ccedil;ar pelos famosos frameworks (que eu abomino&#8230;), algumas fun&ccedil;&otilde;es interessantes que só funcionavam em Mozilla, outras gigantescas demais para o meu gosto. Tentei ent&atilde;o entender como as coisas eram feitas e fazer eu mesmo. Este é sempre o método mais enriquecedor (mas nem sempre é o mais eficiente&#8230; é bom lembrar -rsrsrs).</p>
	<p><strong>Entendendo</strong> </p>
	<p>O objeto window.location tem uma propriedade chamada &#8216;hash&#8217;, que mostra ou define aquela parte da URL que vem no final, depois do caracter &#8216;#&#8217; - que usamos para navegar para diferentes pontos na mesma página, com, por ex.: </p>
&lt;a name=&quot;meu_hash&quot;&gt;&lt;/a&gt; e chamamos com: &lt;a href=&quot;#meu_hash&quot;&gt;meu_hash&lt;/a&gt;
<p>Pois é, ele é a chave para o histórico do navegador, pois ao mudar o hash, mudamos a URL. Ent&atilde;o se ao executar um comando, eu mudar o hash o navegador armazena como uma nova página? A resposta é n&atilde;o. Se n&atilde;o há um clique explícito do usuário em um link como o descrito acima (com um A NAME=&quot;&#8230;&quot;), ao clicar no bot&atilde;o Voltar, nada acontece! O IE nem habilita o bot&atilde;o!!! Bem, mas a URL está diferente e é isso que vamos usar. Usaremos uma variável para armazenar o hash e um setInterval para testá-lo a intervalos regulares. D&ecirc; uma olhada nesse link: <a href="http://juliogreff.wordpress.com/2006/10/20/ativando-o-botao-voltar/">http://juliogreff.wordpress.com/2006/10/20/ativando-o-botao-voltar/</a>. </p>
	<p>Com o script que o Júlio mostra, resolve-se a quest&atilde;o. Mas resta um problema: o IE n&atilde;o habilitou o bot&atilde;o voltar apenas com a mudan&ccedil;a do hash&#8230; Mais pesquisas e mais pesquisas para achar a solu&ccedil;&atilde;o, que quando foi encontrada me pareceu t&atilde;o óbvia que n&atilde;o sei por que n&atilde;o pensei nisso antes (sempre pensamos isso, né?). Quando carregamos um frame ou iframe o IE cria um novo item no histórico! Veja a página de onde tirei a idéia: <a href="http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps">http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps</a>. <br />Esse exemplo é crossbrowser, mas muito complicado. Serviu para esclarecer, mas n&atilde;o tive vontade de usá-lo. </p>
	<p>Bem, baseado nesses scripts resolvi criar um terceiro, fundindo com o que já tinha pronto (mostrado acima) criei o objeto ajaxHistory. Vou falar sobre a lógica que usei antes de mostrar o script. Basicamente preservei os métodos e propiedades do antigo objeto e acrescentei novos métodos para permitir o uso do objeto history do navegador. </p>
	<p>Em nosso objeto haverá um array para armazenar os comandos (como strings) chamado ajaxHistory.items e um inteiro que indica o índice do item exibido no momento, ajaxHistory.currentIndex. O sistema original funciona da forma mais simples possível. A cada comando que modifique o conteúdo da página, executamos ajaxHistory.add enviando uma string que se executada como comando reproduz a opera&ccedil;&atilde;o que modificou a página. Depois podemos usar os métodos ajaxHistory.go ou ajaxHistory.goTo para navegar pelos itens do nosso &#8216;histórico de comandos&#8217;. Além do método goTo, o array ajaxHistory.captions foi adicionado, possibilitando ajustar o título da página de acordo com o item exibido. Aí podemos usar ajaxHistory.hasBack e ajaxHistory.hasForward para testar se há itens atrás ou adiante do atual e assim habilitar ou desabilitar nossos bot&otilde;es personalizados de histórico. </p>
	<p>Ok, mas e para usar os benditos bot&otilde;es de histórico do browser? Para isso vários métodos foram criados, mas para executar, basta chamar o método ajaxHistory.activateBrowserHistory no onload da página, uma única vez. Isso dispara uma série de eventos que em conjunto habilitam o histórico do navegador. Vamos a eles. </p>
	<p>A lógica e a execu&ccedil;&atilde;o da coisa s&atilde;o diferentes para Mozilla e IE (novidade&#8230;). </p>
	<p>Em ambos os casos o hash é modificado ao criar um novo item ou ao carregar um item do histórico (ajaxHistory.setHash). </p>
	<p>No Mozilla criamos um setInterval chamando o método ajaxHistory.checkHash a cada 1/10 de seg. testando se o hash é igual a ajaxHistory.currentIndex, se for diferente, o usuário clicou no bot&atilde;o voltar (ou avan&ccedil;ar). O hash é setado com o valor do índice do item no array ajaxHistory.items, ent&atilde;o ajaxHistory.goTo é chamado com o hash como par&acirc;metro. </p>
	<p>No IE um iframe é inserido na página, com display:none. Este iframe carrega o arquivo &#8216;historyframe.html&#8217; que deve ser criado como descrito abaixo: </p>
	<div class="codigo">&lt;html&gt;&lt;head&gt;&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt; <br />function checkHistory() { <br />var pi = parent.location.hash.replace(/#/,'&#8217;), si = location.href.replace(/^.+\?/,'&#8217;); <br />if(si &amp;&amp; pi &amp;&amp; (parent.ajaxHistory || false)) <br />if(pi != si) parent.ajaxHistory.goTo(si); <br />} <br />&lt;/script&gt;&lt;/head&gt;&lt;body onLoad=&quot;checkHistory();&quot;&gt;&lt;/body&gt;&lt;/html&gt; </div>
	<p>No caso do IE, ajaxHistory.setHash recarrega o iframe enviando na query string o valor do índice, assim: &#8216;historyframe.html?2&#8242;, por exemplo. O arquivo &#8216;historyframe.html&#8217; ao ser carregado testa o índice enviado na URL com o hash na URL da janela principal, se forem diferentes, ajaxHistory.goTo é chamado com o índice enviado na URL como par&acirc;metro. </p>
	<p>O Mozilla, ao contrário do IE, habilita os bot&otilde;es mas n&atilde;o há a&ccedil;&atilde;o mesmo quando o iframe é recarregado, portando os dois métodos foram necessários. Bem, lá vai o script: </p>
	<div class="codigo">/** <br />* ajaxHistory - histórico de comandos para navega&ccedil;&atilde;o por Ajax <br />* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; <br />* autor: Cau Guanabara <br />* data: 2006-06-07 :: 2006-11-07 <br />* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; <br />*/ </p>
	<p>var ajaxHistory = { <br />&#8216;items&#8217;: [], <br />&#8216;captions&#8217;: [], <br />&#8216;currentIndex&#8217;: 0, <br />&#8216;go&#8217;: function(ref) { <br />if(this.items[this.currentIndex + ref] || false) this.currentIndex += ref; <br />else return; <br />if(this.activeHistory) this.setHash(); <br />if(this.captions[this.currentIndex]) document.title = this.captions[this.currentIndex]; <br />new Function(this.items[this.currentIndex])(); <br />}, <br />&#8216;goTo&#8217;: function(ind) { <br />if(this.items[ind] || false) this.currentIndex = ind; <br />else return; <br />if(this.activeHistory) this.setHash(); <br />if(this.captions[this.currentIndex]) document.title = this.captions[this.currentIndex]; <br />new Function(this.items[this.currentIndex])(); <br />}, <br />&#8216;add&#8217;: function(str, cap) { <br />if(str == this.items[this.currentIndex]) return false; <br />this.currentIndex = this.items.length; <br />this.items.push(str); <br />this.captions.push(cap || false); <br />if(this.activeHistory) this.setHash(); <br />return true; <br />}, <br />&#8216;hasBack&#8217;: function() { return (this.items[this.currentIndex - 1] || false) ? true : false; }, <br />&#8216;hasForward&#8217;: function() { return (this.items[this.currentIndex + 1] || false) ? true : false; }, <br />&#8216;activeHistory&#8217;: false, <br />&#8216;activateBrowserHistory&#8217;: function() { <br />if(document.all) this.makeIframe(); <br />else setInterval(&quot;ajaxHistory.checkHash()&quot;, 100); <br />this.activeHistory = true; <br />}, <br />&#8216;makeIframe&#8217;: function() { <br />this.iframe = document.createElement(&#8217;iframe&#8217;); <br />this.iframe.style.display = &#8216;none&#8217;; <br />this.iframe.src = &#8216;historyframe.html&#8217;; <br />document.getElementsByTagName(&#8217;body&#8217;)[0].appendChild(this.iframe); <br />}, <br />&#8216;checkHash&#8217;: function() { <br />var curHash = location.hash.replace(/#/,'&#8217;); <br />if(this.currentIndex != curHash) this.goTo(curHash); <br />}, <br />&#8217;setHash&#8217;: function() { <br />top.location.hash = this.currentIndex; <br />if(document.all) <br />this.iframe.contentWindow.location.href = &#8216;historyframe.html?&#8217;+this.currentIndex; <br />} <br />};</div>
Note que este objeto n&atilde;o deve ser inicializado com o operador <strong>new</strong>, basta chamar os métodos diretamente. Veja abaixo um exemplo de uso do sistema (os comandos no exemplo n&atilde;o mudam o conteúdo da pagina, mas isso n&atilde;o faz a menor diferen&ccedil;a - qualquer comando javascript é válido)<br />
<div class="codigo">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; <br />&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt; <br />&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; <br />&lt;head&gt; <br />&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;ajax_history.js&quot;&gt;&lt;/script&gt; <br />&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt; <br />function request(command, caption) { <br />ajaxHistory.add(command, caption); <br />document.title = caption; <br />new Function(command)(); <br />} <br />&lt;/script&gt; <br />&lt;/head&gt; </p>
	<p>&lt;body onload=&quot;ajaxHistory.activateBrowserHistory();&quot;&gt; <br />Clique nos links e depois navegue pelo histórico&lt;br /&gt;&lt;br /&gt; <br />&lt;p&gt;&lt;a href=&quot;javascript://&quot; onclick=&quot;request(&#8217;alert(\&#8217;link 1\&#8217;);&#8217;,'link 1&#8242;)&quot;&gt;link 1&lt;/a&gt;&lt;br /&gt; <br />&lt;a href=&quot;javascript://&quot; onclick=&quot;request(&#8217;alert(\&#8217;link 2\&#8217;);&#8217;,'link 2&#8242;)&quot;&gt;link 2&lt;/a&gt;&lt;br /&gt; <br />&lt;a href=&quot;javascript://&quot; onclick=&quot;request(&#8217;alert(\&#8217;link 3\&#8217;);&#8217;,'link 3&#8242;)&quot;&gt;link 3&lt;/a&gt; &lt;/p&gt; <br />&lt;/body&gt; <br />&lt;/html&gt; </div>
Espero que fa&ccedil;am proveito das informa&ccedil;&otilde;es contidas aqui. É isso aí.
</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/15/historico-do-browser-para-navegacao-via-ajax/feed/</wfw:commentRss>
	</item>
		<item>
		<title>The web way of life - uma divagação sobre networking e privacidade</title>
		<link>http://cauguanabara.blogsome.com/2006/11/10/the-web-way-of-life-uma-divagacao-sobre-networking-e-privacidade/</link>
		<comments>http://cauguanabara.blogsome.com/2006/11/10/the-web-way-of-life-uma-divagacao-sobre-networking-e-privacidade/#comments</comments>
		<pubDate>Fri, 10 Nov 2006 23:37:08 +0000</pubDate>
		<dc:creator>Cau Guanabara</dc:creator>
		
	<category>Pensamentos</category>
		<guid>http://cauguanabara.blogsome.com/2006/11/10/the-web-way-of-life-uma-divagacao-sobre-networking-e-privacidade/</guid>
		<description><![CDATA[	A evolu&ccedil;&atilde;o das tecnologias e linguagens usadas na rede em combina&ccedil;&atilde;o com a conex&atilde;o de banda larga e custo estreito, já utilizada em grande escala, e a viol&ecirc;ncia das grandes cidades, que torna proibitivo sair &agrave;s ruas, tem direcionado muita gente a praticamente &lsquo;viver&rsquo; na web. Pela rede pode-se fazer quase tudo&#8230; Conhecer pessoas e [...]]]></description>
			<content:encoded><![CDATA[	<p>A evolu&ccedil;&atilde;o das tecnologias e linguagens usadas na rede em combina&ccedil;&atilde;o com a conex&atilde;o de banda larga e custo estreito, já utilizada em grande escala, e a viol&ecirc;ncia das grandes cidades, que torna proibitivo sair &agrave;s ruas, tem direcionado muita gente a praticamente &lsquo;viver&rsquo; na web. Pela rede pode-se fazer quase tudo&#8230; Conhecer pessoas e lugares, obras de arte, fazer compras, ir ao banco, divulgar suas idéias. Até namorar via web&#8230; é um pouco demais, n&atilde;o?</p>
	<p>As comunidades da rede s&atilde;o uma febre, juntamente com os blogs. Pode-se encontrar todo tipo de informa&ccedil;&atilde;o, de qualquer assunto, inclusive dados pessoais dos internautas.<br /><a id="more-2"></a>O Orkut, que tem tido tantos problemas com a justi&ccedil;a por conta dos conteúdos dos usuários, é um exemplo excelente. Entre na página de um usuário que n&atilde;o tem voca&ccedil;&atilde;o para hacker (falo da média dos usuários) e perceba a inoc&ecirc;ncia com ele se exp&otilde;e, informando onde mora, nomes de parentes, fotos, etc. Até telefone já vi divulgado.</p>
	<p>Em qualquer comunidade que ingressamos, a primeira coisa que voc&ecirc; tem que fazer é informar seu e-mail. Aliás, n&atilde;o se pede mais para o usuário criar um login, esse conceito está ficando ultrapassado. Agora o login é o seu e-mail na maior parte dos sites, voc&ecirc; só escolhe a sua senha. Bem, ao entrar a primeira sugest&atilde;o é (e isso é quase invariável): fale um pouco de voc&ecirc;, preencha o seu &lsquo;profile&rsquo;, ou seja, informe para nós os seus dados pessoais. Essas informa&ccedil;&otilde;es s&atilde;o usadas, como vemos nos jornais todos os dias, por bandidos, hackers e outros, talvez piores&#8230;</p>
	<p>Isso tudo me faz lembrar a já quase esquecida (e mais possível que nunca) &lsquo;teoria da conspira&ccedil;&atilde;o&rsquo;. É verdade, os dados est&atilde;o totalmente descentralizados em milh&otilde;es de servidores pelo mundo afora, como achá-los e usá-los? Respondo que tudo é uma quest&atilde;o de proporcionalidade. Se estivéssemos falando de uma rede local, com 10 máquinas, com um computador de última gera&ccedil;&atilde;o seria possível, n&atilde;o? Nem seria caro montar uma máquina capaz de fazer o trabalho bem rapidamente, talvez uns 2 mil dólares?. Agora imagine que voc&ecirc; tem uma verba de 2 bilh&otilde;es de dólares para varrer a internet&#8230; come&ccedil;a a parecer menos impossível, n&atilde;o?</p>
	<p>Aí surge o Google, tomando conta de todos os setores mais visitados da internet em pouquíssimo tempo e oferecendo um e-mail com 2 giga de espa&ccedil;o em disco (que disco? Onde está esse disco? Quem é o dono desse disco?) e com o conselho explícito: &lsquo;n&atilde;o jogue mais nada fora!&rsquo; (deixe que nós tomamos conta dessas informa&ccedil;&otilde;es para voc&ecirc;).</p>
	<p>Ora, informa&ccedil;&atilde;o sempre foi sin&ocirc;nimo de poder, quanto mais no mundo de hoje. Agora eu pergunto: será que sou neurótico ou empresas como o Google podem tirar proveito dos dados que guardam? Ou até terem liga&ccedil;&otilde;es com ag&ecirc;ncias internacionais de intelig&ecirc;ncia? Sabemos que o tio Sam anda em crises de neurose com os terroristas e acabou de desembolsar alguns trilh&otilde;es de dólares numa guerra estúpida&#8230; que tal ent&atilde;o aumentar nosso or&ccedil;amento de 2 mi para 1 tri? Mais viável?</p>
	<p>N&atilde;o, n&atilde;o fique assustado, pois realmente sou um pouco neurótico.<br />Claro que tudo que estou falando s&atilde;o absurdos jurídicos &ndash; toda empresa tem deveres legais e n&atilde;o pode (legalmente) se prestar a esse tipo de papel, como negociar os dados sob sua guarda. Se voc&ecirc; acredita numa atua&ccedil;&atilde;o legal e ética por parte daqueles a quem interessa controlar esses dados, fique tranq&uuml;ilo.</p>
	<p>Sou programador e acredito no &lsquo;open-source&rsquo;, acho que o compartilhar é o grande lance da rede. O que questiono é até onde devemos nos expor pessoalmente ao invés de apenas divulgar nossas idéias. Alguém mais inteligente que eu já disse que as pessoas interessantes falam sobre idéias enquanto as medíocres falam sobre pessoas &ndash; incluindo, naturalmente, ter a si mesmo como tema principal. N&atilde;o que seja apenas o egocentrismo que leve as pessoas a divulgar seus dados pessoais na rede, a inoc&ecirc;ncia é enorme também.</p>
	<p>Compartilhe seus arquivos e idéias, mas n&atilde;o se exponha demais&#8230; a privacidade está se tornando um bem quase impossível de se conseguir e eu o desejo. Por isso tento dificultar em lugar de facilitar as coisas&#8230; falo isso rindo &agrave;s gargalhadas! Devo ser mesmo um maluco neurótico.</p>
]]></content:encoded>
			<wfw:commentRss>http://cauguanabara.blogsome.com/2006/11/10/the-web-way-of-life-uma-divagacao-sobre-networking-e-privacidade/feed/</wfw:commentRss>
	</item>
	</channel>
</rss>
