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

<channel>
	<title>Marlon Pacheco</title>
	<atom:link href="http://blog.marlonpacheco.com.br/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.marlonpacheco.com.br</link>
	<description>Desenvolvimento web descomplicado</description>
	<lastBuildDate>Fri, 27 Nov 2015 03:17:55 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.4</generator>
	<item>
		<title>Onde tem sinal?&#8211;Projeto da semana</title>
		<link>http://blog.marlonpacheco.com.br/onde-tem-sinalprojeto-da-semana/</link>
		<comments>http://blog.marlonpacheco.com.br/onde-tem-sinalprojeto-da-semana/#respond</comments>
		<pubDate>Fri, 23 Aug 2013 23:11:14 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[JS]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=353</guid>
		<description><![CDATA[Essa semana, conversando com alguns colegas, fiquei sabendo que utilizavam o site coberturacelular.com.br para algumas consultas referente ao posicionamento de antenas de celular pelo país. Eles reclamaram que o site não está sendo atualizado desde janeiro de 2011 e que algumas consultas poderiam ser prejudicadas por isso. Resolvi encarar o desafio de fazer algo similar [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Essa semana, conversando com alguns colegas, fiquei sabendo que utilizavam o site coberturacelular.com.br para algumas consultas referente ao posicionamento de antenas de celular pelo país.</p>
<p>Eles reclamaram que o site não está sendo atualizado desde janeiro de 2011 e que algumas consultas poderiam ser prejudicadas por isso.</p>
<p>Resolvi encarar o desafio de fazer algo similar e que atendesse as necessidades de todos. Nasceu o <a href="http://ondetemsinal.com.br/" target="_blank">Onde tem sinal ?</a>.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image23.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb22.png" width="418" height="197" /></a></p>
<p><span id="more-353"></span>
<p>Usando a API do Google Maps e os dados provenientes do site da Anatel (depois vou fazer um post contando essa aventura.), consegui deixar a aplicação funcional.</p>
<p>Ainda é necessário alguns ajustes, melhorias de performance, mas acredito que já atenda bem o propósito da ferramenta. Em breve vou lançar o código no Github e aviso aqui.</p>
<p>Comentem, digam o que acharam, sugiram melhorias, critiquem os problemas.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/onde-tem-sinalprojeto-da-semana/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tarefas&#8211;Meu primeiro Chrome App</title>
		<link>http://blog.marlonpacheco.com.br/tarefasmeu-primeiro-chrome-app/</link>
		<comments>http://blog.marlonpacheco.com.br/tarefasmeu-primeiro-chrome-app/#respond</comments>
		<pubDate>Fri, 12 Jul 2013 22:05:48 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=346</guid>
		<description><![CDATA[Depois de publicar o artigo Criando seu próprio Chrome App me dei conta que eu mesmo nunca tive uma app publicada na Web Store. Ontem resolvi essa pendência. Publiquei meu primeiro aplicativo na Chrome Web Store, o Tarefas (baseado no tutorial que publiquei sobre IndexedDb). É um app simples, para gerenciar suas tarefas e que [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Depois de publicar o artigo <a title="Criando seu próprio Chrome App" href="http://blog.marlonpacheco.com.br/2013/04/criando-seu-prprio-chromeapp/" target="_blank">Criando seu próprio Chrome App</a> me dei conta que eu mesmo nunca tive uma app publicada na <a href="https://chrome.google.com/webstore/category/apps" target="_blank">Web Store</a>.</p>
<p>Ontem resolvi essa pendência. Publiquei meu primeiro aplicativo na Chrome Web Store, o <a href="https://chrome.google.com/webstore/detail/tarefas/fcfppgoahnfcpfpkdbfhkjkjfkdoijma" target="_blank">Tarefas</a> (baseado no tutorial que publiquei sobre <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDb</a>).</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/Chrome-Web-Store-Tarefas.png"><img title="Chrome Web Store - Tarefas" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="Chrome Web Store - Tarefas" src="http://blog.marlonpacheco.com.br/wp-content/uploads/Chrome-Web-Store-Tarefas_thumb.png" width="436" height="211" /></a></p>
<p><span id="more-346"></span>
<p>É um app simples, para gerenciar suas tarefas e que funciona totalmente offline. Como será utilizado apenas no Chrome, não precisei me preocupar com compatibilidades cross-browser.</p>
<p>Instale e dê seu feedback. Gostaria de receber sugestões, críticas, reclamações, etc… Usem os comentários abaixo ou os reviews da Web Store para deixar sua opinião.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/tarefasmeu-primeiro-chrome-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MyReader&#8211;Seu novo leitor de feeds</title>
		<link>http://blog.marlonpacheco.com.br/myreaderseu-novo-leitor-de-feeds/</link>
		<comments>http://blog.marlonpacheco.com.br/myreaderseu-novo-leitor-de-feeds/#respond</comments>
		<pubDate>Thu, 04 Jul 2013 15:13:21 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=342</guid>
		<description><![CDATA[Sei que não foi apenas eu, mas muitas pessoas foram pegas de surpresa com o anúncio, pelo Google, do desligamento do Google Reader. Há anos utilizava a ferramenta diariamente para me atualizar acerca dos assuntos do mundo internético. Infelizmente o anúncio concretizou-se (apesar dos protestos de usuários) e ficamos sem o nosso querido Google Reader. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Sei que não foi apenas eu, mas muitas pessoas foram pegas de surpresa com o anúncio, pelo Google, do desligamento do Google Reader. Há anos utilizava a ferramenta diariamente para me atualizar acerca dos assuntos do mundo <em>internético.</em></p>
<p>Infelizmente o anúncio concretizou-se (apesar dos protestos de usuários) e ficamos sem o nosso querido Google Reader.</p>
<p>Como sou antiquado e resistente à mudanças (algo inconcebível para quem trabalha com computação), resolvi criar meu próprio leitor de feeds. Agora apresento à vocês o <a href="http://myreader.com.br" target="_blank">MyReader</a>.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/My-Reader.png"><img title="My Reader" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="My Reader" src="http://blog.marlonpacheco.com.br/wp-content/uploads/My-Reader_thumb.png" width="337" height="315" /></a></p>
<p><span id="more-342"></span>
<p>Ainda estou no começo. Fiz às pressas no última final de semana, pois o dia 01/07 (data de desligamento do Google Reader) estava chegando.</p>
<p>Nesse momento o serviço não permite multiusuários e nem registra o que você já leu. Mas estou trabalhando arduamente nisso e espero contar com a colaboração de quem, assim como eu, gostava do Google Reader.</p>
<p>O código está disponível no meu <a href="https://github.com/marlonlp/MyReader" target="_blank">GitHub</a>. Sinta-se à vontade para contribuir, sugerir, criticar. Se você não tiver os conhecimentos necessários para ajudar no desenvolvimento, ajude com idéias, utilize os comentários aqui no blog para deixar sugestões/críticas.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/myreaderseu-novo-leitor-de-feeds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Criando seu pr&#243;prio ChromeApp</title>
		<link>http://blog.marlonpacheco.com.br/criando-seu-prprio-chromeapp/</link>
		<comments>http://blog.marlonpacheco.com.br/criando-seu-prprio-chromeapp/#respond</comments>
		<pubDate>Tue, 30 Apr 2013 15:19:20 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=326</guid>
		<description><![CDATA[Há alguns dias o GDG São paulo postou no G+ questionando quem já havia desenvolvido Apps para o Google Chrome e fiquei surpreso com a quantidade de respostas. Foram apenas 9. 5 querendo aprender e 4 (contando comigo) que já meteram a mão na massa. Então, pensando nisso, resolvi criar um manualzinho bem básico sobre [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Há alguns dias o <a title="GDG São Paulo" href="https://plus.google.com/u/0/102774871279745079139/about" target="_blank">GDG São paulo</a> postou no G+ questionando quem já havia desenvolvido Apps para o Google Chrome e fiquei surpreso com a quantidade de respostas.</p>
<p>Foram apenas 9. 5 querendo aprender e 4 (contando comigo) que já meteram a mão na massa. Então, pensando nisso, resolvi criar um manualzinho bem básico sobre como criar um ChromeApp.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image21.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb20.png" width="410" height="195" /></a></p>
<p>&#160;</p>
<p><span id="more-326"></span>
<p>Muitos desenvolvedores acreditam que aqueles ícones que aparecem em uma nova guia do Chrome são apenas atalhos para sites e/ou aplicações na web. Mas neste manual, você irá aprender como fazer uma aplicação que rode localmente, sem a necessidade de conexão com a internet.</p>
<p>Para que não percamos muito tempo pensando no que desenvolver (acredito que seja a parte mais difícil, a idéia) vamos usar a aplicação que criei no post <a href="http://blog.marlonpacheco.com.br/2013/01/gerenciando-suas-tarefas-com-html5-indexeddb-css3-e-jquery/" target="_blank">Gerenciando suas tarefas com HTML5, IndexedDB, CSS3 e jQuery</a> (você pode baixar os arquivos originais pelo meu <a href="https://github.com/marlonlp/web_sql" target="_blank">Github</a>).</p>
<p>Com os arquivos na sua máquina vamos começar pelo principal responsável pelo funcionamento do nosso App, o arquivo de manifesto. Vamos utilizar uma versão bem básica desse arquivo, mas você pode conhecer mais a fundo o que é possível fazer direto no <a href="http://developer.chrome.com/apps/manifest.html" target="_blank">Google Developers</a>. Toda extensão, app ou tema deve utilizar o arquivo manifest.json (para saber mais sobre json, leia o ótimo artigo do <a href="https://plus.google.com/114896277363762090056?rel=author" target="_blank">Tárcio Zemel</a>, <a href="http://desenvolvimentoparaweb.com/javascript/json-javascript-object-notation/" target="_blank">JSON – JavaScript Object Notation</a>). Abaixo o código da nossa aplicação.</p>
<pre class="prettyprint">{
    &quot;name&quot;: &quot;Tarefas&quot;,
    &quot;description&quot;: &quot;Gerenciamento de Tarefas&quot;,
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;manifest_version&quot;: 2,
    &quot;offline_enabled&quot;: true,
    &quot;icons&quot;: {
        &quot;128&quot;: &quot;img/128.png&quot;
    },
    &quot;app&quot;: {
        &quot;launch&quot; : {
            &quot;local_path&quot;: &quot;index.html&quot;
        }
    }
}</pre>
<p>Acredito que este arquivo seja totalmente auto-explicativo. Lembrando que ele deve ficar no diretório raiz da aplicação.</p>
<p>Feito isso, vamos ao passo a passo para habilitar o nosso app no Chrome.</p>
<ol>
<li>Abra uma nova guia no Chrome e digite na <em>Omnibar: </em><a href="chrome://extensions/">chrome://extensions/</a>;</li>
<li>Caso não esteja marcado, marque a opção “Modo do desenvolvedor”;</li>
<li>Clique no botão “Carregar extensão expandida…”;</li>
<li>Selecione o diretório onde você salvou os arquivos do app;</li>
<li>Abra uma nova guia com os Apps instalados e verifique o último da lista;</li>
<p>  <a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image22.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb21.png" width="362" height="101" /></a>Fácil não ?</ol>
<ol>Caso você queira apenas criar um atalho para o seu site, basta trocar a linha <em>“local_path”: “index.html”</em> para <em>&quot;web_url&quot;: &quot;<strong>http://blog.marlonpacheco.com.br/</strong>&quot;.</em></ol>
<ol>Se você quiser criar uma aplicação para disponibilizar na Chrome Web Store, basta fazer um <a href="https://chrome.google.com/webstore/developer/dashboard" target="_blank">cadastro de desenvolvedor</a> e incluir os seus Apps (lembrando que há uma taxa única de US$ 5,00 para publicar seus apps).</ol>
<ol>O que achou do post ? Ajudou você ? Tirou suas dúvidas ? Se tiver dúvidas, críticas, sugestões fique a vontade nos comentários.</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/criando-seu-prprio-chromeapp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery &#8211; Trocando seu arquivo CSS</title>
		<link>http://blog.marlonpacheco.com.br/jquery-trocando-seu-arquivo-css/</link>
		<comments>http://blog.marlonpacheco.com.br/jquery-trocando-seu-arquivo-css/#respond</comments>
		<pubDate>Thu, 25 Apr 2013 16:24:31 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=323</guid>
		<description><![CDATA[Agora a pouco um usuário do G+ postou uma dúvida sobre como seria feita a mudança de tema de uma página dinamicamente. Pensando no assunto um pouco mais, montei esse exemplo simples de como isso funcionaria. Aqui você pode ver o exemplo em funcionamento e fazer o download do código fonte. Sinta-se à vontade para [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Agora a pouco um usuário do G+ postou uma dúvida sobre como seria feita a mudança de tema de uma página dinamicamente. Pensando no assunto um pouco mais, montei esse exemplo simples de como isso funcionaria.</p>
<p><a title="Troca Tema" href="http://blog.marlonpacheco.com.br/labs/Troca_Tema/" target="_blank">Aqui</a> você pode ver o exemplo em funcionamento e fazer o download do código fonte.</p>
<p>Sinta-se à vontade para criticar, melhorar, sugerir alterações. Use os comentários e diga o que achou.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/jquery-trocando-seu-arquivo-css/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS3&#8211;M&#250;ltiplos Backgrounds</title>
		<link>http://blog.marlonpacheco.com.br/css3mltiplos-backgrounds/</link>
		<comments>http://blog.marlonpacheco.com.br/css3mltiplos-backgrounds/#respond</comments>
		<pubDate>Wed, 27 Mar 2013 02:17:13 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=317</guid>
		<description><![CDATA[Com a chegada do CSS3, um dos grandes desejos dos designers foi satisfeito: a possibilidade de inclusão de várias imagens de background em elementos sem a necessidade de mudanças na forma como você escreve o seu CSS. Com alguns caracteres a mais, você tem o efeito da imagem abaixo, onde o ambiente é uma imagem [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Com a chegada do CSS3, um dos grandes desejos dos designers foi satisfeito: a possibilidade de inclusão de várias imagens de background em elementos sem a necessidade de mudanças na forma como você escreve o seu CSS.</p>
<p>Com alguns caracteres a mais, você tem o efeito da imagem abaixo, onde o ambiente é uma imagem e o <em>meme face</em> é outra imagem.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image20.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb19.png" width="319" height="218" /></a></p>
<p><span id="more-317"></span>
<p>O suporte à essa funcionalidade contempla, praticamente, todos os principais navegadores modernos. O Google Chrome oferece suporte à múltiplos backgrounds desde a versão 10, o Firefox desde a versão 3.6, o Safari desde a versão 1.3, o Opera desde a versão 10.50 (ainda na <em>engine</em> Presto) e o IE desde a versão 9.0 (que novidade).</p>
<p>Você consegue repetir a renderização da imagem acima com o seguinte código:</p>
<pre class="prettyprint">#trabalho {
    background: url(../img/ok.png) right bottom no-repeat, url(../img/trabalho.jpg) left top no-repeat;
}</pre>
<p>Viu como é simples ? Basta você separar os atributos por vírgula. Mas você precisa prestar atenção no seguinte detalhe: as imagens são exibidas do primeiro plano para o plano de fundo. No exemplo acima, o arquivo ok.png é o <em>meme face</em> e está visível pois está declarado primeiro.</p>
<p>Caso você ache o código acima confuso e de manutenção complicada você pode ‘distribuir’ os atributos pelas propriedades de background.</p>
<pre class="prettyprint">#trabalho {
    background-image: url(../img/ok.png), url(../img/trabalho.jpg);
    background-position: right bottom, left top;
    background-repeat: no-repeat;
}</pre>
<p>Você pode perceber que na propriedade <em>background-repeat</em> eu informei apenas 1 vez o atributo <em>no-repeat</em>. Caso não seja declarado, o navegador repetirá o último atributo para o restante das imagens. Para o caso de você exceder o número de atributos, os excedentes serão ignorados pelo seu navegador.</p>
<p>Você pode visualizar o nosso <a href="http://blog.marlonpacheco.com.br/labs/Multiplos_Backgrounds/" target="_blank">exemplo</a> e <a href="http://blog.marlonpacheco.com.br/labs/Multiplos_Backgrounds/Multiplos_Backgrounds.zip" target="_blank">baixar</a> o código. Comente, modifique, critique, crie.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/css3mltiplos-backgrounds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS3&#8211;Fun&#231;&#227;o Calc()</title>
		<link>http://blog.marlonpacheco.com.br/css3funo-calc/</link>
		<comments>http://blog.marlonpacheco.com.br/css3funo-calc/#respond</comments>
		<pubDate>Wed, 13 Mar 2013 02:14:56 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=305</guid>
		<description><![CDATA[Com a chegada do CSS3, diversas gambiarras que tínhamos que fazer para resolver problemas simples não são mais necessárias. Uma das novidades que ganhamos é a função calc(). Segundo a especificação da W3C: The calc() function allows mathematical expressions with addition (‘+’), subtraction (‘-’), multiplication (‘*’), and division (‘/’) to be used as component values. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Com a chegada do CSS3, diversas gambiarras que tínhamos que fazer para resolver problemas simples não são mais necessárias. Uma das novidades que ganhamos é a função calc(). Segundo a especificação da W3C:</p>
<blockquote><p><em>The calc() function allows mathematical expressions with addition (‘+’), subtraction (‘-’), multiplication (‘*’), and division (‘/’) to be used as component values. The ‘</em><a href="http://www.w3.org/TR/css3-values/#calc"><em>calc()</em></a><em>’ expression represents the result of the mathematical calculation it contains, using standard operator precedence rules. It can be used wherever </em><a href="http://www.w3.org/TR/css3-values/#length-value"><em>&lt;length&gt;</em></a><em>, </em><a href="http://www.w3.org/TR/css3-values/#frequency-value"><em>&lt;frequency&gt;</em></a><em>, </em><a href="http://www.w3.org/TR/css3-values/#angle-value"><em>&lt;angle&gt;</em></a><em>, </em><a href="http://www.w3.org/TR/css3-values/#time-value"><em>&lt;time&gt;</em></a><em>, </em><a href="http://www.w3.org/TR/css3-values/#number-value"><em>&lt;number&gt;</em></a><em>, or </em><a href="http://www.w3.org/TR/css3-values/#integer-value"><em>&lt;integer&gt;</em></a><em> values are allowed. Components of a ‘</em><a href="http://www.w3.org/TR/css3-values/#calc"><em>calc()</em></a><em>’ expression can be literal values, ‘</em><a href="http://www.w3.org/TR/css3-values/#attr"><em>attr()</em></a><em>’ or ‘</em><a href="http://www.w3.org/TR/css3-values/#calc"><em>calc()</em></a><em>’ expressions, or </em><a href="http://www.w3.org/TR/css3-values/#percentage-value"><em>&lt;percentage&gt;</em></a><em> values that resolve to one of the preceding types.</em></p></blockquote>
<blockquote><p><em>O função calc () permite expressões matemáticas, como adição (&#8216;+&#8217;), subtração (&#8216;-&#8216;), multiplicação (&#8216;*&#8217;), e divisão (&#8216;/&#8217;) que são utilizados como valores de componentes. A expressão &#8216;calc ()&#8217; representa o resultado do cálculo matemático que contém, utilizando as regras de operação padrão de precedência. Ele pode ser usado sempre que &lt;length&gt;, &lt;frequency&gt;, &lt;angle&gt;, &lt;time&gt;, &lt;number&gt; ou &lt;integer&gt; são permitidos. Componentes de uma expressão &#8220;calc () &#8216;podem ser valores literais,&#8221; attr () &#8220;ou&#8221; calc ()&#8217; expressões ou valores &lt;porcentagem&gt; que resolver para um dos tipos anteriores.</em></p></blockquote>
<p><span id="more-305"></span></p>
<p>Essa função permite, ainda, que sejam utilizadas diferentes unidades de medidas para o definir os valores dos elementos, como px, em, %, etc…</p>
<p>Vamos começar definindo o estilo dos nossos elementos <em>article:</em></p>
<pre class="lang:css decode:true prettyprint">article {
    border: 1px solid #333;
    height: 80px;
    margin: auto;
    width: 800px;
}</pre>
<p>&nbsp;</p>
<p>No nosso primeiro exemplo temos um elemento <em>article</em> com 3 <em>section</em> que dividirão o espaço igualmente entre si.</p>
<p>O HTML:</p>
<pre class="lang:xhtml decode:true prettyprint">&lt;article id="um"&gt;
    &lt;section class="um-um"&gt;Um Um&lt;/section&gt;
    &lt;section class="um-dois"&gt;Um Dois&lt;/section&gt;
    &lt;section class="um-tres"&gt;Um Três&lt;/section&gt;
&lt;/article&gt;</pre>
<p>O CSS:</p>
<p>&nbsp;</p>
<pre class="lang:css decode:true prettyprint">#um section {
    float:left;
    height: 80px;
    width: calc(100% / 3);
    width: -webkit-calc(100% / 3);
    width: -moz-calc(100% / 3);
}

.um-um { background: #555; }

.um-dois { background: #999; }

.um-tres { background: #ccc; }</pre>
<p>Você pode me dizer: “Mas é só colocar as <em>section </em>com 33% de <em>width</em> que resolve.”. Aí eu te pergunto: “Onde fica o 1% que sobra?”.</p>
<p>Bom, reconheço que não fui muito feliz na escolha do primeiro exemplo, mas agora você vai ver o que realmente importa. Vou mudar o seu mundo (tá exagerei).</p>
<p>O HTML:</p>
<pre class="lang:xhtml decode:true prettyprint">&lt;article id="dois"&gt;
    &lt;section class="dois-um"&gt;Dois Um&lt;/section&gt;
    &lt;section class="dois-dois"&gt;Dois Dois&lt;/section&gt;
&lt;/article&gt;</pre>
<p>O CSS:</p>
<p>&nbsp;</p>
<pre class="lang:css decode:true prettyprint">#dois section {
    float:left;
    height: calc(100% - 40px);
    height: -webkit-calc(100% - 40px);
    height: -moz-calc(100% - 40px);
    width: calc(100% / 2 - 40px);
    width: -webkit-calc(100% / 2 - 40px);
    width: -moz-calc(100% / 2 - 40px);
}

.dois-um {
    background: #ccc;
    padding: 20px;
}

.dois-dois {
    background: #999;
    margin: 20px;
}</pre>
<p>Quando você adiciona o atributo <em>padding</em>/<em>margin</em> em um elemento, os valores desse atributo são somados ao tamanho do elemento. Neste caso, cada um dos elementos <em>section</em> ficaria com 50% (100$ / 2) do tamanho total do elemento <em>article</em> (400px) mais os 40px de <em>padding</em>/<em>margin</em> em cada lado do elemento. Assim os 2 elementos section ficarão um abaixo do outro, pois os 2 elementos terão 440px de largura total, enquanto o article tem apenas 800px de largura.</p>
<p>Com o CSS 2.1 não teríamos como corrigir isso. Com a função calc() basta diminuirmos o tamanho do padding/margin do tamanho do elemento.</p>
<p>No <a href="http://blog.marlonpacheco.com.br/labs/CSS_Calc/" target="_blank">exemplo</a> publicado você pode ver o funcionamento da função calc() e se quiser <a href="http://blog.marlonpacheco.com.br/labs/CSS_Calc/CSS_Calc.zip" target="_blank">baixar</a> o código fique a vontade.</p>
<p>Teste, modifique, questione, critique. Use o campo de comentários para sanar dúvidas. Mas atenção, essa função ainda é uma candidata a recomendação da W3C. Para utilizá-la são necessários os prefixos proprietários (somente Chrome e Firefox suportam atualmente).</p>
<p><strong>Fonte:</strong></p>
<p><a href="http://www.maujor.com/tutorial/css3-funcao-css-calc.php" target="_blank"><em>Maujor – Função calc()</em></a><em>;</em></p>
<p><a href="http://www.hongkiat.com/blog/css3-calc-function/" target="_blank"><em>Hongkiat – CSS3 calc() function</em></a><em>;</em></p>
<p><a href="http://www.w3.org/TR/css3-values/#calc-notation" target="_blank"><em>W3C – CSS Values and Unit Module Level 3</em></a><em>;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/css3funo-calc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Table Stripes&#8211;Dando um pouco de estilo &#224;s suas tabelas com CSS3</title>
		<link>http://blog.marlonpacheco.com.br/table-stripesdando-um-pouco-de-estilo-s-suas-tabelas-com-css3/</link>
		<comments>http://blog.marlonpacheco.com.br/table-stripesdando-um-pouco-de-estilo-s-suas-tabelas-com-css3/#respond</comments>
		<pubDate>Sat, 09 Mar 2013 03:38:58 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=290</guid>
		<description><![CDATA[Não é porque hoje é tudo tableless que você não pode usar tabelas em seu site. Tabelas devem ser utilizadas para apresentar dados tabulados, mas nem por isso elas devem destoar do restante do layout do seu site. Neste artigo vou demonstrar como aplicar estilos às suas tabelas sem precisar recorrer à classes e ids [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Não é porque hoje é tudo tableless que você não pode usar tabelas em seu site. Tabelas devem ser utilizadas para apresentar dados tabulados, mas nem por isso elas devem destoar do restante do layout do seu site. Neste artigo vou demonstrar como aplicar estilos às suas tabelas sem precisar recorrer à <em>classes</em> e <em>ids</em> nos elementos (nada impede você de fazer isso, mas aqui quero demonstrar como criar um padrão).</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image15.png"><img style="background-image: none; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; margin-right: auto; border-width: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb14.png" width="386" height="141" border="0" /></a></p>
<p><span id="more-290"></span></p>
<p>Comece criando um documento HTML com a seguinte estrutura:</p>
<pre class="prettyprint">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Table Stripe&lt;/title&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;link rel="stylesheet" href="css/style.css"&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;table&gt;
          &lt;thead&gt;
            &lt;tr&gt;
              &lt;th&gt;Posição - Fev 2013&lt;/th&gt;
              &lt;th&gt;Posição - Fev 2012&lt;/th&gt;
              &lt;th&gt;Comparativo de posição&lt;/th&gt;
              &lt;th&gt;Linguagem&lt;/th&gt;
              &lt;th&gt;% Fev 2013&lt;/th&gt;
              &lt;th&gt;% Comparativo Fev 2012&lt;/th&gt;
              &lt;th&gt;Status&lt;/th&gt;
            &lt;/tr&gt;
          &lt;/thead&gt;
          &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;1&lt;/td&gt;
                &lt;td&gt;1&lt;/td&gt;
                &lt;td&gt;=&lt;/td&gt;
                &lt;td&gt;Java&lt;/td&gt;
                &lt;td&gt;18.387%&lt;/td&gt;
                &lt;td&gt;+1.34%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;2&lt;/td&gt;
                &lt;td&gt;2&lt;/td&gt;
                &lt;td&gt;=&lt;/td&gt;
                &lt;td&gt;C&lt;/td&gt;
                &lt;td&gt;17.080%&lt;/td&gt;
                &lt;td&gt;+0.56%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;3&lt;/td&gt;
                &lt;td&gt;5&lt;/td&gt;
                &lt;td&gt;&amp;uarr;&amp;uarr;&lt;/td&gt;
                &lt;td&gt;Objective-C&lt;/td&gt;
                &lt;td&gt;9.803%&lt;/td&gt;
                &lt;td&gt;+2.74%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;4&lt;/td&gt;
                &lt;td&gt;4&lt;/td&gt;
                &lt;td&gt;=&lt;/td&gt;
                &lt;td&gt;C++&lt;/td&gt;
                &lt;td&gt;8.758%&lt;/td&gt;
                &lt;td&gt;+0.91%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;5&lt;/td&gt;
                &lt;td&gt;3&lt;/td&gt;
                &lt;td&gt;&amp;darr;&amp;darr;&lt;/td&gt;
                &lt;td&gt;C#&lt;/td&gt;
                &lt;td&gt;6.680%&lt;/td&gt;
                &lt;td&gt;-1.97%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;6&lt;/td&gt;
                &lt;td&gt;6&lt;/td&gt;
                &lt;td&gt;=&lt;/td&gt;
                &lt;td&gt;PHP&lt;/td&gt;
                &lt;td&gt;5.074%&lt;/td&gt;
                &lt;td&gt;-0.57%&lt;/td&gt;
                &lt;td&gt;A&lt;/td&gt;
            &lt;/tr&gt;
          &lt;/tbody&gt;
      &lt;/table&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Esse código deixará sua tabela com a seguinte aparência:</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image16.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb15.png" width="565" height="133" border="0" /></a></p>
<p>Agora vamos para a parte bonita do código, o nosso CSS. Começaremos aplicando um estilo básico para identificar a tabela e uma estilização do cabeçalho da tabela, lembrando que não colocamos <em>classes</em> ou <em>ids</em> para identificar nada nessa tabela.</p>
<pre class="prettyprint">table {
    border: 1px solid #000;
    font-family: Verdana,sans-serif;
    font-size: 12px;
    margin: 10px auto;
    width: 70%;
}

th, td {
    padding: 5px;
    text-align: center;
}</pre>
<p>Esta parte do CSS vai deixar a tabela com a seguinte aparência:</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image17.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb16.png" width="569" height="124" border="0" /></a></p>
<p>Agora o cabeçalho.</p>
<pre class="prettyprint">thead tr:nth-child(1) {
    background: #02273b;
    color: #fff;
}</pre>
<p>O pseudo-seletor <strong>nth-child</strong> é o responsável pela mágica. O parâmetro 1, indica que o estilo será aplicado no primeiro elemento filho do elemento <em>&lt;tr&gt;. </em>Assim temos a seguinte aparência na nossa tabela.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image18.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb17.png" width="569" height="124" border="0" /></a></p>
<p>Agora vamos criar a nossa <em>“zebrinha”</em>.</p>
<pre class="prettyprint">tbody tr:nth-child(odd) {
    background: #eee;
}</pre>
<p>O mesmo pseudo-seletor que usamos no cabeçalho, mas agora estamos aplicando o estilo nos elementos <em>tr</em>  ímpares que são filhos do <em>tbody.</em> Dessa maneira nossa tabela está pronta.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image19.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb18.png" width="569" height="124" border="0" /></a></p>
<p>No <a href="http://blog.marlonpacheco.com.br/labs/table_stripe/" target="_blank">exemplo</a> publicado há mais algumas opções nos estilos aplicados. <a title="Download" href="http://blog.marlonpacheco.com.br/labs/table_stripe/table_stripe.zip" target="_blank">Baixe</a> o código fonte, estude, melhore. Caso tenha dúvidas, pode usar a nossa caixa de comentário aqui embaixo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/table-stripesdando-um-pouco-de-estilo-s-suas-tabelas-com-css3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gerenciando suas tarefas com HTML5, IndexedDB, CSS3 e jQuery</title>
		<link>http://blog.marlonpacheco.com.br/gerenciando-suas-tarefas-com-html5-indexeddb-css3-e-jquery/</link>
		<comments>http://blog.marlonpacheco.com.br/gerenciando-suas-tarefas-com-html5-indexeddb-css3-e-jquery/#respond</comments>
		<pubDate>Wed, 16 Jan 2013 17:57:33 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JS]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=195</guid>
		<description><![CDATA[Recentemente conheci o Wunderlist, uma aplicação para gerenciamento de tarefas que possui aplicações para desktop, Android, iOS, Web e, se duvidar, até para o seu George Foreman Grill. Gostei bastante da ferramenta e já estou usando em praticamente todos os meus devices, com uma sincronia perfeita. Gostei tanto que resolvi utilizar de exemplo nesse post [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Recentemente conheci o <a href="http://wunderlist.com" target="_blank">Wunderlist</a>, uma aplicação para gerenciamento de tarefas que possui aplicações para desktop, Android, iOS, Web e, se duvidar, até para o seu George Foreman Grill. Gostei bastante da ferramenta e já estou usando em praticamente todos os meus <em>devices</em>, com uma sincronia perfeita. Gostei tanto que resolvi utilizar de exemplo nesse post para criar um gerenciador de tarefas simples com armazenamento local, utilizando <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDB</a>.</p>
<p><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="Gerenciador de Tarefas" alt="Gerenciador de Tarefas" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image14.png" width="470" height="183" border="0" /></p>
<p><span id="more-195"></span></p>
<p>Com essa pequena aplicação será composta de apenas 5 arquivos você poderá fazer a criação e a exclusão de tarefas, que podem ser organizadas por categorias. Neste primeiro post, a intenção é mostrar as funcionalidades da API <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDB</a> que temos agora no HTML5.</p>
<p>Bom, chega de enrolar e vamos ao que interessa.</p>
<p>Começamos com um arquivo HTML bem simples.</p>
<pre class="lang:xhtml decode:true ">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Gerenciando Tarefas - HTML5 - IndexedDB&lt;/title&gt;
    &lt;link rel='stylesheet' href='css/style.css' /&gt;
    &lt;script src="js/jquery-1.8.3.min.js"&gt;&lt;/script&gt;
    &lt;script src="js/scripts.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;section id="geral"&gt;
        &lt;aside id='barra_menus'&gt;
            &lt;header id="topo"&gt;
                &lt;h1 id="titulo"&gt;Tarefas&lt;/h1&gt;
            &lt;/header&gt;
            &lt;nav&gt;
                &lt;ul class="listaCategorias"&gt;

                &lt;/ul&gt;
            &lt;/nav&gt;
        &lt;/aside&gt;
        &lt;article id="conteudo"&gt;
            &lt;span class="formulario"&gt;
                &lt;input type="hidden" name="categoria" id="categoria" value=""&gt;
                &lt;input type="text" name="tarefa" id="tarefa" placeholder="Adicionar nova tarefa"&gt;
            &lt;/span&gt;
            &lt;br/&gt;
            &lt;ul class="listaTarefas"&gt;

            &lt;/ul&gt;            
        &lt;/article&gt;
    &lt;/section&gt;  
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Viu como é simples mesmo ? Agora o CSS para deixar a nossa aplicação com uma ‘carinha bonita’.</p>
<pre class="lang:css decode:true ">@charset "UTF-8";

* {margin: 0; padding: 0;}
a {text-decoration : none;}

/*
    Estilo geral
*/
body {
    background: #fff url('../img/wood.jpg') no-repeat top center;
    color : #000;
    font-family : Helvetica,sans-serif;
    font-size : 10pt;
    overflow: hidden;
    text-align : left;
}

html, body {
    height: 100%;
}

#geral {
    color : #000;
    min-height : 100%;
    margin : auto;
    position : relative;
}

#topo {
    background: #555; 
    box-shadow: 0px 0px 5px 1px rgba(0,0,0,.5);
    height : 40px;
    padding : 0 0 0 0;   
    text-align: center;
    z-index: 999;
}

#titulo {
    color : #eaeaea;
    font-size: 15pt;
    font-weight : bolder;
    padding : 3px;
    line-height: 40px;
    text-shadow: 0px 0px 6px rgba(255,255,255,.7);
    top : 5px;
}

#barra_menus {
    background: #eaeaea;
    box-shadow: 5px 0px 5px rgba(0,0,0,.5);
    height: 100%;
    width:270px;
    position: fixed;
}

nav li {
    border-bottom: 1px dotted #ccc;
    color: #555;
    cursor: pointer;
    display: block;
    font-weight: bold;
    padding: 10px;
}

nav li.ativo {
    background: #4876FF;
    border: 1px inset;
    color: #fff;
}

nav li a {
    color: #555;
    float: right;
}

#conteudo {
    color : #000;
    padding : 20px 0px 0px 270px;
}

/* 
    Formulário de tarefa;
*/
.formulario {
    padding: 20px;
}
#tarefa {
    background: rgba(0,0,0,.3);
    border: 1px inset #ccc;
    border-radius: 5px;
    box-shadow: 2px 2px 5px rgba(0,0,0,.5) inset;
    color: #fff;
    margin:3px;
    padding: 10px 20px;
    text-shadow: 2px 2px 2px rgb(0,0,0);
    width: 90%;
}

/* 
    Listagem de tarefas;
*/
.listaTarefas {
    list-style: none;
    overflow: auto;
    max-height: 500px;
    padding: 20px;
}

.listaTarefas li {
    background: #eaeaea;
    border: 1px outset rgba(255,255,255,.9);
    border-radius: 5px;
    color: #555;
    margin: 2px;
    padding: 10px;
}

.listaTarefas li a {
    float: right;
}</pre>
<p>Se você está usando um navegador decente, a aplicação ficará igual à imagem no início do post. Caso contrário, você terá que fazer alguns ajustes no CSS. Testei o layout no Chrome, Firefox (última versão estável) e IE9 e não tive problemas de renderização.</p>
<p>Agora vamos mágica.</p>
<pre class="lang:js decode:true ">$(document).ready(function(){

    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
    var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
    var db;

    if (!window.indexedDB) {
        alert("Seu navegavor não suporta a API IndexedDB.");
    } else {
        bdTarefas();        
    }   

    function bdTarefas(){
        var request = indexedDB.open("Tarefas", 1);  
        request.onsuccess = function (evt) {
            db = request.result;
            $('#categoria').val('Entrada');
            var categoria = $('#categoria').val();
            $('#tarefa').attr('placeholder', "Adicionar um item em \"" + categoria + "\"");        
            listaTarefas();
            listaCategorias();
        };

        request.onerror = function (evt) {
            console.log("IndexedDB error: " + evt.target.errorCode);
        };

        request.onupgradeneeded = function (evt) {
            var storeTarefas = evt.currentTarget.result.createObjectStore("tarefas", { keyPath: "id", autoIncrement: true });
            storeTarefas.createIndex("tarefa", "tarefa", { unique: false });
            storeTarefas.createIndex("categoria", "categoria", { unique: false });
            var storeCategorias = evt.currentTarget.result.createObjectStore("categorias", { keyPath: "id", autoIncrement: true });
            storeCategorias.createIndex("categoria", "categoria", { unique: true });
        };
    }

    function listaTarefas() {
        var tarefas = $('.listaTarefas');
        tarefas.empty();        
        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                if(cursor.value.categoria == $('#categoria').val()) {
                    var linha  = "&lt;li&gt;" + cursor.value.tarefa + "&lt;a href='#' id='" + cursor.key + "'&gt;[ Delete ]&lt;/a&gt;&lt;/li&gt;";
                    $('.listaTarefas').append(linha);
                }
                cursor.continue();  
            }  
        };          
    }

    function listaCategorias() {
        var tarefas = $('.listaCategorias');
        tarefas.empty();        
        $('.listaCategorias').append("&lt;li id='Entrada' class='categorias ativo'&gt;Entrada&lt;/li&gt;");
        var transaction = db.transaction("categorias", "readwrite");
        var objectStore = transaction.objectStore("categorias");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                var linha  = "&lt;li id='"+ cursor.value.categoria +"' class='categorias'&gt;" + cursor.value.categoria + "&lt;a href='" + cursor.value.categoria + "' id='"+cursor.key+"'&gt;[ X ]&lt;/a&gt;&lt;/li&gt;";
                $('.listaCategorias').append(linha);
                cursor.continue();  
            } else {
                $('.listaCategorias').append('&lt;li id="nova"&gt;+ Adicionar Nova Categoria&lt;/li&gt;');                                
            }
        };   
    }    

    function insereTarefa() {
        var categoria = $('#categoria').val();
        var tarefa = $("#tarefa").val();

        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");                    
        var request = objectStore.add({tarefa: tarefa, categoria: categoria});
        request.onsuccess = function (evt) {
            $('#tarefa').val('');
            listaTarefas(); 
        };                   
    }    

    function insereCategoria() {
        var categoria = $('#nova_categoria').val();

        var transaction = db.transaction("categorias", "readwrite");
        var objectStore = transaction.objectStore("categorias");                    
        var request = objectStore.add({categoria: categoria});
        request.onsuccess = function (evt) {
            $('#nova_categoria').val('');
            listaCategorias(); 
        };                   
    }        

    function deletaTarefa(id) {
        var transaction = db.transaction("tarefas", "readwrite");
        var store = transaction.objectStore("tarefas");
        var req = store.delete(+id);
        req.onsuccess = function(evt) {  
            listaTarefas();
        };
    }

    function deletaCategoria(id, categoria) {
        var transaction = db.transaction("categorias", "readwrite");
        var store = transaction.objectStore("categorias");
        var req = store.delete(+id);
        req.onsuccess = function(evt) {
            limpaTarefasSemCategoria(categoria);
            bdTarefas();
        };
    }

    function limpaTarefasSemCategoria(categoria) {
        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                if(cursor.value.categoria == categoria) {
                    var del = objectStore.delete(cursor.key);
                }
                cursor.continue();  
            }
        };           
    }

    $('#tarefa').keypress(function (e) {
        if(e.keyCode == 13) {
            insereTarefa();
        }
    });

    $('.listaTarefas').on('click', 'a', function(){
        var confirma = confirm('Deseja excluir esta tarefa ?')
        if(confirma) {
            deletaTarefa(this.id);
            return false;
        }
    });

    $('.listaCategorias').on('click', 'a', function(){
        var confirma = confirm('Deseja excluir esta categoria ?\nATENÇÃO: Esta ação excluirá todas as tarefas vinculadas a esta categoria!')
        if(confirma){
            var id = this.id;
            var categoria = $(this).parent().get(0).id;
            deletaCategoria(id, categoria);       
        }
        return false;        
    });    

    $('.listaCategorias').on('keypress', '#nova_categoria', function(e) {
        if(e.keyCode == 13) {
            insereCategoria();
        }
    });

    $('.listaCategorias').on('click', '.categorias', function(){
        $('nav li').removeClass('ativo');
        $(this).addClass('ativo');        
        $('#categoria').val('');
        var id = this.id;
        $('#categoria').val(id);
        $('#tarefa').attr('placeholder', "Adicionar um item em \"" + id + "\"");        
        listaTarefas();
    });

    $('.listaCategorias').on('click','#nova', function(){
        $(this).replaceWith('&lt;li id="nova"&gt;&lt;input type="text" name="nova_categoria" id="nova_categoria" placeholder="Adicionar nova categoria"&gt;&lt;/li&gt;')
        $('#nova_categoria').focus();
    });

    $('.listaCategorias').on('blur', '#nova_categoria', function(){
        $(this).replaceWith('+ Adicionar Nova Categoria')
    });
});</pre>
<p>No código abaixo criamos as variáveis que armazenam as informações da API <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDB</a> de acordo com o navegador utilizado e fazemos uma pequena verificação de compatibilidade;</p>
<pre class="lang:js decode:true ">    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
    var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
    var db;

    if (!window.indexedDB) {
        alert("Seu navegavor não suporta a API IndexedDB.");
    } else {
        bdTarefas();        
    }</pre>
<p>Caso o navegador seja compatível com a tecnologia é chamada a função <strong>bdTarefas()</strong> que é responsável por abrir a conexão com o nosso banco.</p>
<pre class="lang:js decode:true ">    function bdTarefas(){
        var request = indexedDB.open("Tarefas", 1);  
        request.onsuccess = function (evt) {
            db = request.result;
            $('#categoria').val('Entrada');
            var categoria = $('#categoria').val();
            $('#tarefa').attr('placeholder', "Adicionar um item em \"" + categoria + "\"");        
            listaTarefas();
            listaCategorias();
        };

        request.onerror = function (evt) {
            console.log("IndexedDB error: " + evt.target.errorCode);
        };

        request.onupgradeneeded = function (evt) {
            var storeTarefas = evt.currentTarget.result.createObjectStore("tarefas", { keyPath: "id", autoIncrement: true });
            storeTarefas.createIndex("tarefa", "tarefa", { unique: false });
            storeTarefas.createIndex("categoria", "categoria", { unique: false });
            var storeCategorias = evt.currentTarget.result.createObjectStore("categorias", { keyPath: "id", autoIncrement: true });
            storeCategorias.createIndex("categoria", "categoria", { unique: true });
        };
    }</pre>
<p>Nas linhas 4 à 9, temos algumas funções executadas caso a requisição de abertura <em>banco</em> seja concluída com sucesso. Na linha 13, enviamos para o console um aviso caso a requisição execute com erro e no final (linhas 17 à 21) fazemos a criação das nossas <em>tabelas</em> e <em>colunas</em>.</p>
<p>As funções abaixo (<strong>listaTarefas()</strong> e <strong>listaCategorias()</strong>) são responsáveis por listar as informações de cada uma das <em>tabelas </em>da nossa aplicação. A função listaTarefas() começa limpando o elemento que possui a classe .listaTarefas . Em seguida fazemos a conexão com o o objeto tarefas e incluímos os resultados dentro da classe .listaTarefas, apenas das tarefas relacionadas à categoria selecionada.</p>
<p>A função listaCategorias() inclui no nosso menu lateral uma categoria padrão, lista as categorias criadas pelo usuário, e insere um link no final para o usuário poder criar novas categorias.</p>
<pre class="lang:js decode:true ">    function listaTarefas() {
        var tarefas = $('.listaTarefas');
        tarefas.empty();        
        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                if(cursor.value.categoria == $('#categoria').val()) {
                    var linha  = "&lt;li&gt;" + cursor.value.tarefa + "&lt;a href='#' id='" + cursor.key + "'&gt;[ Delete ]&lt;/a&gt;&lt;/li&gt;";
                    $('.listaTarefas').append(linha);
                }
                cursor.continue();  
            }  
        };          
    }

    function listaCategorias() {
        var tarefas = $('.listaCategorias');
        tarefas.empty();        
        $('.listaCategorias').append("&lt;li id='Entrada' class='categorias ativo'&gt;Entrada&lt;/li&gt;");
        var transaction = db.transaction("categorias", "readwrite");
        var objectStore = transaction.objectStore("categorias");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                var linha  = "&lt;li id='"+ cursor.value.categoria +"' class='categorias'&gt;" + cursor.value.categoria + "&lt;a href='" + cursor.value.categoria + "' id='"+cursor.key+"'&gt;[ X ]&lt;/a&gt;&lt;/li&gt;";
                $('.listaCategorias').append(linha);
                cursor.continue();  
            } else {
                $('.listaCategorias').append('&lt;li id="nova"&gt;+ Adicionar Nova Categoria&lt;/li&gt;');                                
            }
        };   
    }</pre>
<p>As funções abaixo executam a tarefa de incluir os dados nas <em>tabelas</em>.</p>
<pre class="lang:js decode:true ">    function insereTarefa() {
        var categoria = $('#categoria').val();
        var tarefa = $("#tarefa").val();

        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");                    
        var request = objectStore.add({tarefa: tarefa, categoria: categoria});
        request.onsuccess = function (evt) {
            $('#tarefa').val('');
            listaTarefas(); 
        };                   
    }    

    function insereCategoria() {
        var categoria = $('#nova_categoria').val();

        var transaction = db.transaction("categorias", "readwrite");
        var objectStore = transaction.objectStore("categorias");                    
        var request = objectStore.add({categoria: categoria});
        request.onsuccess = function (evt) {
            $('#nova_categoria').val('');
            listaCategorias(); 
        };                   
    }</pre>
<p>Na sequência temos as funções de deleção de registros. A função deletaCategoria(id,categoria) possui uma função complementar, para excluir todas as tarefas relacionadas àquela categoria para que não fiquem registros <em>perdidos.</em></p>
<pre class="lang:js decode:true ">    function deletaTarefa(id) {
        var transaction = db.transaction("tarefas", "readwrite");
        var store = transaction.objectStore("tarefas");
        var req = store.delete(+id);
        req.onsuccess = function(evt) {  
            listaTarefas();
        };
    }

    function deletaCategoria(id, categoria) {
        var transaction = db.transaction("categorias", "readwrite");
        var store = transaction.objectStore("categorias");
        var req = store.delete(+id);
        req.onsuccess = function(evt) {
            limpaTarefasSemCategoria(categoria);
            bdTarefas();
        };
    }

    function limpaTarefasSemCategoria(categoria) {
        var transaction = db.transaction("tarefas", "readwrite");
        var objectStore = transaction.objectStore("tarefas");

        var req = objectStore.openCursor();
        req.onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {
                if(cursor.value.categoria == categoria) {
                    var del = objectStore.delete(cursor.key);
                }
                cursor.continue();  
            }
        };           
    }</pre>
<p>O restante do javascript contém algumas funções de <em>perfumaria</em> da aplicação. Alteração de classe da categoria selecionada, inclusão de funcionalidade de deleção nos links, etc.</p>
<p>Fiz este post com o intuito de demonstrar as funcionalidades da API IndexedDB. Para maiores informações, você pode consultar os links fonte no final do post.</p>
<p>Veja a <a href="http://blog.marlonpacheco.com.br/labs/web_sql/" target="_blank">demonstração</a> da aplicação e baixe os fontes do meu <a href="https://github.com/marlonlp/web_sql" target="_blank">Github</a>. Faça seus próprios testes, melhore o código, inclua novas funcionalidades, questione, critique. Em um próximo post, vou mostrar como sincronizar essas informações com um banco de dados relacional em um servidor web.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/gerenciando-suas-tarefas-com-html5-indexeddb-css3-e-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatizando atualiza&#231;&#227;o de arquivo de cache&#8211;HTML5 offline application cache</title>
		<link>http://blog.marlonpacheco.com.br/automatizando-atualizao-de-arquivo-de-cachehtml5-offline-application-cache/</link>
		<comments>http://blog.marlonpacheco.com.br/automatizando-atualizao-de-arquivo-de-cachehtml5-offline-application-cache/#respond</comments>
		<pubDate>Sat, 05 Jan 2013 21:25:01 +0000</pubDate>
		<dc:creator><![CDATA[]]></dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[JS]]></category>

		<guid isPermaLink="false">http://blog.marlonpacheco.com.br/?p=177</guid>
		<description><![CDATA[Depois do último post, fiquei pensando em como é chato ficar abrindo o arquivo cache manifest a cada atualização de um arquivo para que os arquivos sejam armazenados novamente para utilização offline. Sou muito preguiçoso e não tenho muita paciência com esse negócio de ficar ‘monitorando’ todos os arquivos. Com certeza eu esqueceria de fazer [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Depois do último <a href="http://blog.marlonpacheco.com.br/2013/01/sua-aplicao-web-offlinehtml5-offline-application-cache/" target="_blank">post</a>, fiquei pensando em como é chato ficar abrindo o arquivo <strong>cache manifest </strong>a cada atualização de um arquivo para que os arquivos sejam armazenados novamente para utilização offline. Sou muito preguiçoso e não tenho muita paciência com esse negócio de ficar ‘monitorando’ todos os arquivos. Com certeza eu esqueceria de fazer isso.</p>
<p><a href="http://blog.marlonpacheco.com.br/wp-content/uploads/image13.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="image" alt="image" src="http://blog.marlonpacheco.com.br/wp-content/uploads/image_thumb13.png" width="381" height="144" border="0" /></a></p>
<p><span id="more-177"></span></p>
<p>Decidi então criar um pequeno script em PHP para a atualização automática do cache manifest. É um script sem muito ‘refinamento’, mas que atende plenamente ao nosso propósito.</p>
<p>Vamos relembrar um pouco do nosso código:</p>
<p><strong>index.html<br />
</strong></p>
<pre class="lang:xhtml decode:true ">&lt;!DOCTYPE html&gt;
&lt;html manifest="cron.appcache"&gt;
  &lt;head&gt;
    &lt;title&gt;Exemplo de uso de Cache + PHP + cron&lt;/title&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;link rel="stylesheet" href="style.css"&gt;
    &lt;script&gt;
        window.applicationCache.addEventListener('updateready', function(e) {
            if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
                window.applicationCache.swapCache();
                if (confirm('Uma nova versão dessa aplicação está disponível. Deseja carregar ?')) {
                    window.location.reload();
                }
            }
        }, false);
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;header&gt;
        &lt;img src="logo.png" alt="HTML5"&gt;
        &lt;h1&gt;Aplicação Web Offline&lt;/h1&gt;
        &lt;h1&gt;Usando AppCache&lt;/h1&gt;
        &lt;br&gt;
        &lt;h2&gt;Utilizando o atualização automática via CRON&lt;/h2&gt;
      &lt;/header&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p><strong>cron.appcache </strong></p>
<pre class="lang:default decode:true ">CACHE MANIFEST
# modificao em 05/01/2013 - 19:00

CACHE:
index.html
logo.png
style.css

NETWORK:
login.php

FALLBACK:
/ offline.html</pre>
<p><strong>styles.css </strong></p>
<pre class="lang:css decode:true ">* { 
    padding: 0; 
    margin: 0; 
}

header {
    background: #ccc;
    height: 200px;
    margin: 50px auto;
    padding: 30px 0 0 0;
    text-align: center;
    width: 50%;
}</pre>
<p>Com um pouco de PHP resolvemos o ‘problema’ que é ficar atualizando o arquivo <strong>cache manifest</strong> a cada modificação da aplicação. Aqui temos o código utilizado para identificar as mudanças nos arquivos e a criação/modificação do cache manifest.</p>
<p><strong>cron.php<br />
</strong></p>
<pre class="lang:php decode:true ">&lt;?php
date_default_timezone_set('America/Sao_Paulo');
//Definição do diretório que será monitorado para modificações;
$dir = "./";
//Variáveis que armazenarão as informações dos arquivos;
$cache = null;
$modf = null;
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
            if ($file != "." &amp;&amp; $file != ".." &amp;&amp; $file != "Thumbs.db") {
                if ($file == "cron.appcache") {
                    //Se existir o arquivo appcache, é armazenada a informação da última modificação na variável;
                    $cache .= filemtime($dir.$file);
                }
                if ($file == "index.html" || $file == "style.css" || $file == "logo.png") {
                    //Armazena em um array a informação da última modificação dos arquivos da aplicação;
                    $modf .= filemtime($dir.$file).",";
                }
            }
        }
        closedir($dh);
        $arquivos = array($modf);
        foreach ($arquivos as $arquivo) {
            //Varre as informações dos arquivos que deverão ser armazenados no cache e compara com o arquivo cache manifest;
            if ($cache &lt; $arquivo) {
                //Se a última modificação do arquivo cache manifest for anterior à algum dos arquivos é feita a atualização;
                $result = "Houve Atualização";
                $arqCache = "cron.appcache";
                $dt_modificacao = date("d/m/Y - H:i");
                $fh = fopen($arqCache, 'w') or die("Não é possível abrir o arquivo.");
                $contCache = "CACHE MANIFEST\n";
                $contCache .= "# modificado em ". $dt_modificacao ."\n";
                $contCache .= "\n";
                $contCache .= "CACHE:\n";
                $contCache .= "index.html\n";
                $contCache .= "logo.png\n";
                $contCache .= "style.css\n";
                $contCache .= "\n";
                $contCache .= "NETWORK:\n";
                $contCache .= "login.php\n";
                $contCache .= "\n";
                $contCache .= "FALLBACK:\n";
                $contCache .= "/ offline.html";
                fwrite($fh, $contCache);
                fclose($fh);                
            } else {
                $result = "Nada modificado";
            }
        }
        echo $result;
    }
} else {
    echo "Erro";
}                
?&gt;</pre>
<p>Pronto. Agora é só colocar no cron do seu servidor, onde você pode definir a periodicidade da execução, para que a atualização seja automática.</p>
<p>Como sempre, comentem, critiquem, participem. Os arquivos estão disponíveis no meu <a href="https://github.com/marlonlp/app_cache_cron" target="_blank">Github</a> e <a href="http://blog.marlonpacheco.com.br/labs/app_cache_cron/" target="_blank">aqui</a> você pode ver a aplicação em ação.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marlonpacheco.com.br/automatizando-atualizao-de-arquivo-de-cachehtml5-offline-application-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
