<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"> 
  <id>http://openblog.github.com/</id>
  <title>Open Blog</title>
  <icon>http://openblog.github.com/img/favicon.png</icon>
  <updated>2013-03-22T07:15:29-07:00</updated>
  <link rel="self" href="http://openblog.github.com/feed/index.xml" />
  <link href="http://openblog.github.com/" />
  
  <entry>
    <id>http://loopinfinito.com.br/2013/03/22/grunt</id>
    <title>Grunt: você deveria estar usando!</title>
    <updated>2013-03-22T00:00:00-07:00</updated>
    <link href="http://openblog.github.com/2013/03/22/grunt/" />
    <author>
      <name>Vagner Santana</name>
      <uri>http://twitter.com/vagnervjs</uri>
    </author>
    <content type="html">
      
      
      &lt;p&gt;&lt;img itemprop=&quot;thumbnailUrl&quot; src=&quot;http://openblog.github.com/img/posts/2013-03-22-grunt.png&quot; alt=&quot;Grunt: você deveria estar usando!&quot; title=&quot;Grunt: você deveria estar usando!&quot; width=&quot;700&quot; height=&quot;432&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Todo programador é preguiçoso, e isso é fato, pois sempre estamos procurando ferramentas que automatizem o trabalho para nós. Mas isso necessariamente não é algo ruim, pelo contrário, automatizar tarefas implica em ganho de produção e isso é ótimo. O que não podemos deixar acontecer é a não realização de tarefas primordiais para que uma aplicação tenha qualidade.&lt;/p&gt;

&lt;p&gt;Minificação e concatenação de arquivos por exemplo são tarefas básicas e você não deve deixar isso de lado, mas fazer isso usando um plugin no editor (que seja o Sublime Text) ou um site, copiar o código minificado, colar em um novo arquivo renomeado com .min no final e por fim salvar, e toda vez que alterar o código ter que repetir essa operação é um saco.&lt;/p&gt;

&lt;p&gt;E o deploy ? Se você utiliza FTP sabe o quão lento é fazer upload de arquivos, principalmente se forem muitos, e o pior de tudo, ele abre e fecha uma conexão para cada arquivo, é um sofrimento. E se você esquece de enviar um arquivo que alterou ? Melhor nem pensar&amp;#8230;&lt;/p&gt;

&lt;h2 id='o_que__o_grunt'&gt;O que é o Grunt?&lt;/h2&gt;

&lt;p&gt;Foi pensando nessas e várias outras atividades que o Ben Alman, conhecido como &lt;a href='https://twitter.com//cowboy' target='_blank'&gt;Cowboy&lt;/a&gt; criou essa ferramenta incrível. O Grunt é uma aplicação de linha de comando que tem como objetivo automatizar tarefas, principalmente tarefas em aplicações JavaScript. Essas tarefas são como as descritas acima. E como isso é feito? Escrevendo as tarefas em JavaScript e rodando no Node.JS. &lt;br /&gt; Link oficial: &lt;a href='http://gruntjs.com' target='_blank'&gt;http://gruntjs.com&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='ok_quero_usar'&gt;Ok, quero usar!&lt;/h2&gt;

&lt;p&gt;Bom, agora que você já entendeu para o que ele serve, vou mostrar como é simples utilizá-lo. &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Como eu disse, ele roda no Node.JS, então antes de tudo você precisa ter o node e o npm instalados em sua máquina. Se isso estiver ok, você pode continuar.&lt;/p&gt;

&lt;p&gt;Se você já instalou o Grunt alguma vez, certifique-se de remove-lo não ocorrer problemas futuros.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;  sudo npm uninstall -g grunt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora para instalar:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;  sudo npm install -g grunt-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Isso irá deixar disponível o comando &lt;code&gt;grunt&lt;/code&gt; em seu terminal. Perceba que instalamos o &lt;code&gt;grunt-cli&lt;/code&gt; e não o &lt;code&gt;grunt&lt;/code&gt; em si, a tarefa do grunt-cli é rodar qualquer versão do grunt, isso permite que você tenha diversas versões do grunt disponíveis em diferentes projetos, e você poderá rodar (inclusive simultâneamente) em sua máquina sem ter problemas.&lt;/p&gt;

&lt;h2 id='mas_como_ele_funciona_'&gt;Mas como ele funciona ?&lt;/h2&gt;

&lt;p&gt;Para utilizar o Grunt em um projeto, é necessário que exista dois arquivos: o &lt;code&gt;Gruntfile.js&lt;/code&gt; e o &lt;code&gt;package.json&lt;/code&gt;. Eles devem estar na raiz (diretório principal, root) do projeto. Vou falar sobre esses arquivos logo mais. &lt;br /&gt; Se você estiver trabalhando em um projeto que já utiliza o Grunt (isto é, exista os arquivos Gruntfile.js e package.json), para rodar é simples.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;  // Acesse a pasta &lt;span class='k'&gt;do &lt;/span&gt;projeto
  &lt;span class='nb'&gt;cd &lt;/span&gt;project-folder

  // Instale as dependências 
  sudo npm install

  // Rode o Grunt
  grunt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simples não? &lt;br /&gt; Mas ok, vamos fazer isso do zero agora.&lt;/p&gt;

&lt;h2 id='criando_um_projeto_com_grunt'&gt;Criando um projeto com Grunt&lt;/h2&gt;

&lt;p&gt;Para iniciar um projeto com o Grunt existem algumas opções: você pode optar pelo &lt;code&gt;grunt-init&lt;/code&gt; que gera o scaffolding para alguns modelos de aplicações, como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;→ jquery: cria um projeto para um plugin jQuery&lt;/li&gt;

&lt;li&gt;→ commonjs: cria um projeto para um módulo commonjs&lt;/li&gt;

&lt;li&gt;→ Gruntfile: cria um arquivo Gruntfile.js básico&lt;/li&gt;

&lt;li&gt;→ gruntplugin: cria um plugin grunt&lt;/li&gt;

&lt;li&gt;→ node: cria um módulo Node.JS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Você também pode baixar outros templates, além dos oficiais. Para criar um projeto a partir de um dos template como os descritos acima basta usar o comando:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;grunt-init &amp;lt;nome-do-template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou então iniciar o Grunt sem um template, criando os arquivos &amp;#8220;na unha&amp;#8221;. &lt;br /&gt; Antes, é nescessário que você saiba para que serve aqueles dois arquivos. &lt;br /&gt; &lt;code&gt;Gruntfile.&lt;/code&gt;: Esse é um arquivo JavaScript que são definidas e configuradas as tarefas a serem executadas pelo Grunt. &lt;br /&gt; &lt;code&gt;package.json&lt;/code&gt;: Esse arquivo é usado pelo npm para armazenar as informações da aplicação, dados como nome, autor, repositório e dependências, e é por isso que o grunt precisa dele, para instalar as dependências e os plugins do grunt que seu projeto irá utilizar. Ao rodar o comando npm install, ele procura as dependências descritas nessa arquivo, e instala na pasta do projeto as mesmas com suas respectivas versões. Para criar um arquivo &lt;code&gt;package.json&lt;/code&gt; você pode utilizar o comando &lt;code&gt;npm init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;meu-projeto&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.0.1&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Meu íncrivel projeto&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;homepage&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;http://vagnersantana.com/meuprojeto&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;repository&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;http://github.com/vagnervjs/meu-projeto&amp;quot;&lt;/span&gt;
  &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;engines&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.8.x&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;npm&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;1.1.x&amp;quot;&lt;/span&gt;
  &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;devDependencies&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;grunt-cli&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.1.6&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;grunt&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;~0.4.1&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;grunt-contrib-jshint&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;~0.1.1&amp;quot;&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para instalar o &lt;code&gt;grunt&lt;/code&gt; e plugins dele, você pode usar o comando &lt;code&gt;npm install &amp;lt;nome do modulo ou plugin&amp;gt; --save-dev&lt;/code&gt; que além de instalar localmente, adiciona a dependência e sua versão na sessão &lt;code&gt;devDependences&lt;/code&gt; do arquivo &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;O arquivo &lt;code&gt;Gruntfile.js&lt;/code&gt; é compostos da função principal que engloba tudo, das configurações e tarefas da aplicação, do carregamento de grunt plugins, e de tarefas personalizadas.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;module&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;exports&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;grunt&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='s1'&gt;&amp;#39;use strict&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

  &lt;span class='c1'&gt;// configuração do projeto&lt;/span&gt;
  &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;gruntConfig&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;pkg&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;grunt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;file&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;readJSON&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;package.json&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
    &lt;span class='nx'&gt;min&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;dist&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;src&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;src/assets/js/main.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
        &lt;span class='nx'&gt;dest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;src/assets/js/all.min.js&amp;#39;&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;},&lt;/span&gt;
    &lt;span class='nx'&gt;cssmin&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;dist&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;src&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;src/assets/css/main.css&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
        &lt;span class='nx'&gt;dest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;src/assets/css/all.min.css&amp;#39;&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;},&lt;/span&gt;
    &lt;span class='nx'&gt;jshint&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;all&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;src/assets/**/*.js&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;};&lt;/span&gt;
  &lt;span class='nx'&gt;grunt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;initConfig&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;gruntConfig&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

  &lt;span class='c1'&gt;// carregando plugins&lt;/span&gt;
  &lt;span class='nx'&gt;grunt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;loadNpmTasks&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;grunt-contrib-jshint&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

  &lt;span class='c1'&gt;// tarefas&lt;/span&gt;
  &lt;span class='nx'&gt;grunt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;registerTask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;jshint&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bom, pra quem não entendeu direito o que acontece acima vou explicar: dentro da função foram declaradas várias tarefas, e suas configurações, por exemplo: &lt;code&gt;min&lt;/code&gt; é responsável por minificar os arquvios da pasta descrita na propriedade &lt;code&gt;src&lt;/code&gt; e enviar para o arquivo de destino em &lt;code&gt;desc&lt;/code&gt;. Depois de definir as tarefas e configurações em &lt;code&gt;initConfig()&lt;/code&gt;, é nescessário carregar os plugins grunt de terceitos, caso esteja utilizando algum. Feito isso, basta registrar as tarefas a serem executadas, usando &lt;code&gt;registerTask()&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='plugins_do_grunt'&gt;Plugins do Grunt&lt;/h2&gt;

&lt;p&gt;Talvez a melhor parte do Grunt seja essa: seus plugins que estão disponíveis. O Grunt vem com algumas tarefas padrões como &lt;code&gt;min&lt;/code&gt; e &lt;code&gt;concat&lt;/code&gt;, e você chamas elas definindo suas configurações e adicionando o parâmetro &lt;code&gt;&amp;#39;default&amp;#39;&lt;/code&gt; em &lt;code&gt;registerTask()&lt;/code&gt;. Porém, a comunidade já criou e vem criando novas tarefas para o Grunt, e a lista não para de crescer. Provavelmente tudo o que você precisa já deve ter pronto. Você pode ver essas tarefas em: &lt;a href='http://gruntjs.com/plugins' target='_blank'&gt;http://gruntjs.com/plugins&lt;/a&gt;, lá tem o link para o npm, onde você vê como instalar, e qual configuração utilizar.&lt;/p&gt;

&lt;h3 id='e_o_deploy'&gt;E o deploy?&lt;/h3&gt;

&lt;p&gt;É, eu disse lá no início que é possível até fazer deploy com o Grunt, e sim, isso é perfeitamente possível. Agora que você já viu como ele funciona vou falar sobre esse plugin em específico.&lt;/p&gt;

&lt;p&gt;Para deploy estou utilizando o &lt;code&gt;grunt-rsync&lt;/code&gt;. Esse plugin cria uma tarefa de sincronização, tanto local como para um servidor remoto, usando o &lt;code&gt;rsync&lt;/code&gt; que já vem presente em sistemas operacionais &amp;#8220;unix like&amp;#8221;. O rsync é excelente pois mantém o diretório remoto sempre em sincronia com o diretório base, e só envia os arquivos que foram alterados, além de não enviar os arquivos um-a-um como faz o FTP. Outro ponto positivo é que ele utiliza SSH, portanto se você tiver uma chave publica adicionada as chaves autorizadas no servidor, você executa o deploy direto do Grunt e sem digitar senha.&lt;/p&gt;

&lt;p&gt;Veja a configuração da tarefa:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;rsync&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nx'&gt;dist&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;src&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;./src/&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;dest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;./dist&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;recursive&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;syncDest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;exclude&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;main.*&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='nx'&gt;deploy&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;src&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;./dist/&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;dest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/var/www&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;host&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;root@vagnersantana.com&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;recursive&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nx'&gt;syncDest&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Explicando: em dist eu estou fazendo uma sincronização local, preparando a aplicação para deploy, nela eu removo os arquivos que tem nome &amp;#8220;main&amp;#8221; pois estes foram minificados e concatenados em tarefas anteriores. Depois disso, defino a tarefa de deploy, que pega a pasta &amp;#8216;./dist&amp;#8217; que acabou de ser criada ou atualizada, e envio ela para meu servidor. A propriedade &amp;#8220;dest&amp;#8221; agora é é o diretório remoto e a propriedade &amp;#8220;host&amp;#8221; é o usuário e endereço do meu servidor remoto.&lt;/p&gt;

&lt;h2 id='como_rodar'&gt;Como rodar?&lt;/h2&gt;

&lt;p&gt;Mais simples impossível, depois de tudo configurado, você pode executar todas as tarefas descritas no &lt;code&gt;Gruntfile.js&lt;/code&gt; com o comando:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;grunt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Talvez você precise utilizar sudo caso alguma tarefa nescessite de privilégios.&lt;/p&gt;

&lt;h2 id='grunt_boilerplate'&gt;Grunt Boilerplate&lt;/h2&gt;

&lt;p&gt;Depois que comecei a utilizar o Grunt, percebi que sempre iria executar tarefas em comum para vários projetos, e isso me fez criar um padrão do Grunt com tudo que preciso em comum, e caso algum projeto necessitar de outras tarefas, é só ir lá e adicionar. Nesse boilerplate defini (por enquanto): min, cssmin e rsync. Não adicionei o JSHint pois utilizo direto no Sublime. Dessa forma com esse boilerplate pronto, para iniciar um projeto eu apenas clono o projeto grunt-boilerplate, mudo o nome da pasta, configuro o package.json, altero os caminhos e nomes de arquivos de acordo com o projeto, e pronto, é lindo =D&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Ficou com vontade de utilizar também? É só ir lá repositório no meu github, clonar o projeto e alterar para suas necessidades. Sá basta ter o grunt-cli e o node instalados para tudo funcionar.&lt;/p&gt;
&lt;br /&gt;&lt;a href='https://github.com/vagnervjs/grunt-boilerplate' title='Github' target='_blank' alt='Demo no github'&gt;
  &lt;button class='btn'&gt;Github&lt;/button&gt;
&lt;/a&gt;
&lt;p&gt;Se quiser realizar um fork, ou reportar um problema fique totalmente à vontade.&lt;/p&gt;

&lt;h2 id='concluso'&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Ferramentas como Grunt, Yeoman, Bower estão ai disponíveis e abertas para todos nós, basta sair da sua zona de conformo, perder o medo de sair do tradicional. Essas ferramentas só existem para melhorar e ajudar nosso trabalho, e se usadas de forma correta, você só irá evoluir, tanto em produção como em profissionalismo. Esperto ter ajudado um pouquinho com o Grunt nesse post. Divirtam-se!&lt;/p&gt;
&lt;h3&gt;Referências&lt;/h3&gt;&lt;ul&gt;
    &lt;li&gt;→&lt;a href='http://gruntjs.com/getting-started' title='Grunt' target='_blank' alt='Grunt'&gt; Grunt - Getting Started&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;→&lt;a href='http://net.tutsplus.com/tutorials/javascript-ajax/meeting-grunt-the-build-tool-for-javascript/' title='Meeting Grunt' target='_blank' alt='Meeting Grunt'&gt; Meet Grunt: The Build Tool for JavaScript&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;→&lt;a href='http://weblog.bocoup.com/introducing-grunt/' title='Introducing Grunt' target='_blank' alt='Introducing Grunt'&gt; Bocoup - Introducing Grunt&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;&lt;!-- Tweet Button --&gt;&lt;a href='https://twitter.com/share' class='twitter-share-button' data-lang='pt'&gt;Tweetar&lt;/a&gt;&lt;script&gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=&quot;//platform.twitter.com/widgets.js&quot;;fjs.parentNode.insertBefore(js,fjs);}}(document,&quot;script&quot;,&quot;twitter-wjs&quot;);&lt;/script&gt;&lt;!-- Facebook Like --&gt;&lt;div class='fb-like' data-send='true' data-width='450' data-layout='button_count' data-href='http://openblog.github.com/2013/03/22/grunt' data-show-faces='true' data-font='segoe ui' /&gt;
    </content>
  </entry>
  
  <entry>
    <id>http://loopinfinito.com.br/2013/03/15/player.io</id>
    <title>Player.IO - Um media player que roda no navegador, feito com Node.JS, Socket.IO e é controlado pelo seu smartphone</title>
    <updated>2013-03-15T00:00:00-07:00</updated>
    <link href="http://openblog.github.com/2013/03/15/player.io/" />
    <author>
      <name>Vagner Santana</name>
      <uri>http://twitter.com/vagnervjs</uri>
    </author>
    <content type="html">
      
      
      &lt;p&gt;&lt;img itemprop=&quot;thumbnailUrl&quot; src=&quot;http://openblog.github.com/img/posts/2013-03-13-player.io.png&quot; alt=&quot;Player.IO - Um media player que roda no navegador, feito com Node.JS, Socket.IO e é controlado pelo seu smartphone&quot; title=&quot;Player.IO - Um media player que roda no navegador, feito com Node.JS, Socket.IO e é controlado pelo seu smartphone&quot; width=&quot;700&quot; height=&quot;432&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Se você acompanha o mundo do desenvolvimento web , provavelmente já ouviu algo sobre o Node.JS e sua incrível capacidade de rodar aplicações altamente escaláveis escritas em JavaScript no servidor. Minha idéia inicial era criar um post onde abordaria como iniciar uma aplicação utilizando o Node.JS, porém quando comecei trabalhar com ele, vi que a coisa era tão bacana que acabei criando esse experimento: Um media player que roda no seu navegador, carrega arquivos de media locais utilizando a File Access API, e você pode controlar do seu smartphone trocando dados em tempo real graças ao Socket.IO.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Antes de continuar lendo o post, você pode conferir o experimento e entender melhor como o ele se comporta. É altamente recomendado utilizar o Google Chrome e arquivos nos formatos: m4a, mp3, mp4 ou webm. Vai lá e depois volte aqui, fico aguardando&amp;#8230;&lt;/p&gt;
&lt;a href='http://vagnersantana.com/player.io' title='Player.IO' target='_blank' alt='Player.IO'&gt;
&lt;button class='btn'&gt;Player.IO&lt;/button&gt;
&lt;/a&gt;&lt;a href='https://github.com/vagnervjs/player.io' title='Demo no github' target='_blank' alt='Demo no github'&gt;
&lt;button class='btn'&gt;Github&lt;/button&gt;
&lt;/a&gt;
&lt;h2 id='nodejs'&gt;Node.JS&lt;/h2&gt;

&lt;p&gt;Talvez você já saiba o que é, mas vou repetir a explicação aqui para quem não conhece.&lt;/p&gt;

&lt;p&gt;O Node.JS é um interpretador de JavaScript que utiliza a engine V8 do Google (a mesma do Chrome). Ele roda no servidor, mas não confunda ele com um Apache por exemplo, porque talvez ele seja mais que isso.&lt;/p&gt;

&lt;p&gt;Definicão oficial:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Node.js is a platform built on Chrome&amp;#8217;s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;→ &lt;a href='http://nodejs.org' target='_blank'&gt;Site oficial&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='socketio'&gt;Socket.IO&lt;/h2&gt;

&lt;p&gt;Nas especificações do HTML5 está a WebSocket API que possibilita trocar dados com um servidor e múltiplos clientes de forma assíncrona, ou seja, troca de dados em tempo real (exemplos de aplicações: chats, games), porém para essa API ainda é restrita pois nem todos os navegadores suportam WebSockets. Devido essa jovialidade do WebSocket, existem bibliotecas que fornecem a tecnologia de socket e conexão em tempo real no navegador, e uma das mais conhecidas é o Socket.IO, que inclui a biblioteca javascript no código do cliente, e roda no servidor com o node.js, dessa forma temos uma aplicação de tempo real cross-browser.&lt;/p&gt;

&lt;p&gt;→ &lt;a href='http://socket.io' target='_blank'&gt;Site oficial&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='playerio'&gt;Player.IO&lt;/h2&gt;

&lt;p&gt;Eu acredito que o experimento, apesar de simples, tem como principal objetivo mostrar como é possível criar uma interação de usuário rica utilizando apenas HTML5 e o poder do JavaScript, e isso deixa claro que, cada vez mais, a Web é a plataforma.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;A idéia é que o usuário carregue uma playlist de arquivos (áudio e vídeo) locais ou de um links diretos (ex: http://dominio.com/arquivo.mp4), após isso, abra uma página no smartphone que irá funcionar como um controle remoto. Para abrir a página o usuário tem como opção ler um &lt;code&gt;QR Code&lt;/code&gt; ou abrir um link (que também pode ser aberto na mesma máquina). Essa página envia dados para o servidor que por sua vez se comunica com a página de origem no computador e assim é possível executar comandos remotamente, como: troca de arquivo, play/pause, aumentar e diminuir volume, entrar ou sair do modo tela cheia, etc.&lt;/p&gt;

&lt;p&gt;A aplicação é multiusuário, isto é: várias pessoas podem usar o serviço simultaneamente (e o Node.JS suporta muitas conexões) e cada usuário pode enviar comandos de onde quer que esteja pois tudo é feito online.&lt;/p&gt;

&lt;h2 id='fases_de_desenvolvimento'&gt;Fases de Desenvolvimento&lt;/h2&gt;

&lt;p&gt;Antes de mostrar código, vou listar as fases mais importantes do desenvolvimento.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;→ Utilizar a API File Acces para acessar arquivos locais.&lt;/li&gt;

&lt;li&gt;→ Tratar tipos de arquivos suportados pelos navegadores.&lt;/li&gt;

&lt;li&gt;→ Gerar Blob URL para cada arquivo local (e também tratar suporte dos navegadores)&lt;/li&gt;

&lt;li&gt;→ Criar conexão com o Node.JS&lt;/li&gt;

&lt;li&gt;→ Implementar conexão com o Socket.IO e gerar array de sockets&lt;/li&gt;

&lt;li&gt;→ Servir páginas com o Node.JS utilizando o express&lt;/li&gt;

&lt;li&gt;→ Criar layout para página requisitada pelo express utilizando Jade&lt;/li&gt;

&lt;li&gt;→ Implementar evendos de servidor/cliente para troca de dados&lt;/li&gt;

&lt;li&gt;→ Criar novo cliente para página de controle&lt;/li&gt;

&lt;li&gt;→ Fazer tudo isso funcionar&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='iniciando_com_o_nodejs_e_socketio'&gt;Iniciando com o Node.JS e Socket.IO&lt;/h2&gt;

&lt;p&gt;Bom, já conversamos bastante, agora lets go to the code. Como o tópico principal do post é Node.JS e Socket.IO, não vou entrar em detalhes sobre a manipulação de arquivos utilizando a File Access API, gerar Blobs URLs e outras coisas que utilizei no experimento, o código está lá para quem quiser se divertir, aqui vou focar em como iniciar a aplicação com o Node.JS. Vamos lá… &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;O arquivo &lt;code&gt;app.js&lt;/code&gt; é onde fica o código do servidor, que é interpretado pelo Node.JS. Nele definimos as dependências que iremos utilizar (ex: socket.io, express), configurações necessárias (como a engine de templates) e claro os eventos de servidor que serão disparados, com as operações que o Node.JS terá de fazer para a aplicação. &lt;br /&gt;&lt;br /&gt; Criando conexão entre cliente e servidor com o Socket.IO&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: app.js&lt;/span&gt;

&lt;span class='c1'&gt;// Criando socket que fica aguardando na porta 8080 por conexões&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;io&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;require&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;listen&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;8080&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// Declarando array para armazenar cada cliente&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;sockets&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{};&lt;/span&gt;

&lt;span class='c1'&gt;// Evento connection: quando uma nova conexão é estabeleciada&lt;/span&gt;
&lt;span class='nx'&gt;io&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;sockets&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;on&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;socket&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;// Aguarda o evento setId que será disparado pelo cliente&lt;/span&gt;
    &lt;span class='nx'&gt;socket&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;on&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;setId&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    	&lt;span class='c1'&gt;// setId é responsável por gerar um identificador para cada conexão&lt;/span&gt;
        &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;log&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;ID : &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='c1'&gt;// a nova conexão é armazenada no array sockets com o identificador&lt;/span&gt;
        &lt;span class='nx'&gt;sockets&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;socket&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: client.js&lt;/span&gt;

&lt;span class='c1'&gt;// Definindo id para a conexão&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;randomId&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

&lt;span class='c1'&gt;// Conectando ao socket utilizando host e porta definida em app.js&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;socket&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;io&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;connect&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;http://localhost:8080&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// Emitindo evento para o servidor e passando o id como parâmetro&lt;/span&gt;
&lt;span class='nx'&gt;socket&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;setId&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bom, até agora o que aconteceu acima foi simples, criamos um socket no arquivo app.js que fica escutando conexões na porta 8080 (se você não definir uma porta pode ocorrer conflito). Declaramos um array onde cada nova conexão é armazenada, a partir do evento &lt;code&gt;conection&lt;/code&gt;. No arquivo do cliente, é feita a conexão e emitido um evento chamado &lt;code&gt;setId&lt;/code&gt; para o servidor, nesse evento do lado do servidor foi definida uma função anônima que recebe como parâmetro um &lt;code&gt;id&lt;/code&gt; que serve para identificar cada conexão.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;No arquivo index.html&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='c'&gt;&amp;lt;!-- Arquivo para conexão com o socket.io (ele é gerado automáticamente) --&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;http://localhost:8080/socket.io/socket.io.js&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class='c'&gt;&amp;lt;!-- Script do Cliente --&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;client.js&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora precisamos rodar a aplicação e testar. Você deve ter instalado o Node.JS junto do npm (gerenciador de pacotes do node). Como fazer isso é simples, e existem vários tutoriais por ai. Com o node e o npm instalados, iremos instalar as dependências:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Antes, precisamos criar o arquivo &lt;code&gt;package.json&lt;/code&gt; responsável por gerenciar as dependências do projeto, e conter suas informações.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: package.json&lt;/span&gt;

&lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Player.IO&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.1.0&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;A real-time media player...&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;repository&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;https://github.com/vagnervjs/player.io.git&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;express&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;3.x&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;socket.io&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.9.x&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
    &lt;span class='s2'&gt;&amp;quot;jade&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.28.x&amp;quot;&lt;/span&gt;
  &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Vagner Santana&amp;quot;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instalando as dependências:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// acessando pasta do projeto&lt;/span&gt;
&lt;span class='nx'&gt;cd&lt;/span&gt; &lt;span class='nx'&gt;player&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;io&lt;/span&gt; 
&lt;span class='c1'&gt;// utilize sudo Mac ou Linux&lt;/span&gt;
&lt;span class='nx'&gt;sudo&lt;/span&gt; &lt;span class='nx'&gt;npm&lt;/span&gt; &lt;span class='nx'&gt;install&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não é nescessário passar o nome do pacote que deseja instalar para o comando &lt;code&gt;npm install&lt;/code&gt;, pois estamos utilizando o arquivo &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Com as dependências instaladas, vamos rodar o arquivo &lt;code&gt;app.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;node&lt;/span&gt; &lt;span class='nx'&gt;app&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;js&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se tudo ocorreu bem, ao abrir o arquivo &lt;code&gt;index.html&lt;/code&gt; no navegador um novo socket foi criado. Lembrando que a função &lt;code&gt;randomId&lt;/code&gt; foi criada por mim, se estiver realizando este teste você pode atribuir à varíavel &lt;code&gt;id&lt;/code&gt; uma string qualquer. No console do Node.JS a saída deve conter uma linha com: &lt;code&gt;ID: &amp;lt;id que foi passado&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='servindo_pginas_com_express'&gt;Servindo páginas com Express&lt;/h2&gt;

&lt;p&gt;O Express é um framework minimalista e flexível de desenvolvimento web para o Node.JS que possui vários métodos HTTP tornando possível servir páginas a partir de requisições de usuários, tudo isso com um ótimo desempenho.&lt;/p&gt;

&lt;p&gt;→ &lt;a href='http://expressjs.com/' target='_blank'&gt;Site oficial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iremos utilizar ele para servir a página de controle. Veja:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File app.js&lt;/span&gt;

&lt;span class='c1'&gt;// solicitando dependência do express&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;express&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;require&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;express&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// criando uma aplicação express&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;app&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;express&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

&lt;span class='c1'&gt;// definindo engine para as views&lt;/span&gt;
&lt;span class='nx'&gt;app&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;set&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;view engine&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;jade&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// ao receber uma requisição com o valor /mb/:id&lt;/span&gt;
&lt;span class='c1'&gt;// onde :id é uma string &lt;/span&gt;
&lt;span class='c1'&gt;// chama uma função callback&lt;/span&gt;
&lt;span class='nx'&gt;app&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/mb/:id&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;res&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;// armazenando valor do parâmetro id&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;params&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='c1'&gt;// imprimindo&lt;/span&gt;
    &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;log&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;ID Mb: &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='c1'&gt;// chama uma a view (arquivo jade), passando algumas variáveis (id e title)&lt;/span&gt;
    &lt;span class='nx'&gt;res&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;mobile.jade&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;title&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Player.IO | Control&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;

&lt;span class='c1'&gt;// a aplicação express fica escutando na porta 8000&lt;/span&gt;
&lt;span class='nx'&gt;app&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;listen&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;8000&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Certo, neste ponto nossa aplicação já abre um socket para cada conexão, e agora acabamos de criar um servidor HTTP com o express que fica aguardando requisições na porta 8000. Lembre-se que iniciamos o socket.io e também definimos uma porta para ele, portanto a porta do express deve ser diferente da porta definida para o socket.io (no nosso caso utilizamos as portas 8000 e 8080).&lt;/p&gt;

&lt;p&gt;Com a aplicação express criada e escutando na porta 8000, ao fazermos uma requisição do tipo &lt;code&gt;localhost:8000/mb/novoId123&lt;/code&gt; o express irá chamar uma função callback, que recebe os parâmetros req e res, respectivamente: request e response. O req é um objeto que contém informações sobre a requisição HTTP, já o res é o objeto responsável por enviar uma resposta HTTP, como renderizar uma página por exemplo. &lt;br /&gt; Nesse callback armazenamos o valor do parâmetro id que foi passado na requisição, para isso utilizamos o método &lt;code&gt;param&lt;/code&gt; do objeto req. É obrigatório o uso de &lt;code&gt;:&lt;/code&gt; antes do nome do parâmetro esperado, se o paramêtro for opcional deve ser utilzado o símbolo de interrogação após o nome, ex: &lt;code&gt;:id?&lt;/code&gt;. Com o id armazenado, a próxima operação (além de imprimir o valor de id) é chamado o método &lt;code&gt;render()&lt;/code&gt; do objeto response. Ele é responsável por renderizar uma view utilizando a engine de templates definida acima em &lt;code&gt;aap.set(&amp;#39;view engine&amp;#39;, &amp;#39;jade&amp;#39;)&lt;/code&gt;. Esse método aceita três parâmetros: o primeiro e obrigatório é o nome da view a ser renderizada, os outros dois são: &lt;span&gt;opções&lt;/span&gt; para serem utilizadas na view, e uma função callback. Nesse caso não fiz callback.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Pronto, para o express é isso. O método &lt;code&gt;get()&lt;/code&gt; fica encarregado de verificar qual chamada está sendo feita, e executar seu respectivo callback. Não podemos esquecer de chamar o método &lt;code&gt;listen&lt;/code&gt; para o express funcionar, ele aceita um parâmero único que é a porta. O método listen é idêntico ao &lt;code&gt;http.Server#listen().&lt;/code&gt; do node.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Agora é só executar a aplicação novamente e testar.&lt;/p&gt;

&lt;h2 id='enviando_dados_do_controle_para_o_player'&gt;Enviando dados do controle para o player&lt;/h2&gt;

&lt;p&gt;Agora que servimos a página (que veio da requisição /mb/id), é ela que irá enviar os comandos para o player, portanto precisamos emitir eventos para o socket.io, esses valores defini como: ação e valor para a ação (caso houver). Por exemplo: para trocar de arquivo a página de controle precisa enviar para o servidor a ação que dei nome de &amp;#8220;change&amp;#8221;, e o valor que é o id do arquivo escolhido. Além desses dois valores, preciso também devolver aquele id que foi passado como opção para a view, lembram ? Esse id serve para identificar para qual socket devo enviar os comandos, do contrário, minha unica opção seria enviar os dados por bradcast, o que bloquearia a idéia da aplicação ser multiusuário. Quer ver parte do código ? Lá vai&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: mobile.jade&lt;/span&gt;

&lt;span class='c1'&gt;// Volume Up&lt;/span&gt;
&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#vol_up&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;on&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;tap&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/player/#{id}/volup&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O código acima é simples: quando houver um toque no botão de aumentar o volume (#vol_up) é chamado o método &lt;code&gt;get&lt;/code&gt; do jQuery que faz uma requisição para &lt;code&gt;localhost:8000/player/idQualquer/volup&lt;/code&gt;. Ou seja, uma requisição para o express. Não é preciso definir locaholst:8000 no código pois estamos trabalhando com caminho relativo, portanto ele irá utilizar o mesmo domínio e porta da página.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Mas, espera ai, onde foi definido esse caminho &lt;code&gt;/player/&lt;/code&gt; ? Você pode ver logo a seguir:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: app.js&lt;/span&gt;

&lt;span class='nx'&gt;app&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/player/:id/:action/:val?&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;res&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;params&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;action&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;params&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;action&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;val&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;req&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;params&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nx'&gt;sockets&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;&lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;play&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nx'&gt;action&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nx'&gt;action&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='nx'&gt;res&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;send&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O que está acontecendo ali você já viu anteriormente, o express espera por uma requisição com o valor &amp;#8220;player&amp;#8221;, dois parâmetros obrigatórios (id e action) e um opcional (val). Ali pegamos os valores, e emitimos o o evento &lt;code&gt;play&lt;/code&gt; para um único socket,. Um único socket pois a variável &lt;code&gt;sckets&lt;/code&gt; é um array, e seus índices são os ids de cada conexão, por isso devolvemos o id como um parâmetro da requisição &lt;code&gt;/player/&lt;/code&gt;. Emitimos junto do evento, os dados (action e val) e seus respectivos valores.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Agora, é só ir la no cliente (o player), e tratar esse evento &lt;code&gt;play&lt;/code&gt; certo?&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// File: client.js&lt;/span&gt;

&lt;span class='c1'&gt;// selecionando a tag &amp;lt;video&amp;gt; do arquivo index.html&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;media&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementById&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;player&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='nx'&gt;socket&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;on&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;play&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;action&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;volup&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
        &lt;span class='nx'&gt;media&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;volume&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mf'&gt;0.1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No lado do cliente, com o evento &lt;code&gt;on()&lt;/code&gt; do socket, recebemos o evento emitido pelo servidor, e chamamos uma função callback. Essa função recebe como parâmetro os dados que também foram passados pelo servidor. Assim, é só tratar os dados. Foi o que fiz para verificar qual ação foi enviada, no if comparo se o valor do dado action é igual &amp;#8216;volup&amp;#8217;, se for, aumento o volume do arquivo (utilizando a Web Audio API). Isso vale para todos os outros comandos.&lt;/p&gt;

&lt;h2 id='pedras_no_caminho'&gt;Pedras no caminho&lt;/h2&gt;

&lt;p&gt;Durante o desenvolvimento desse experimento fui descobrindo algumas coisas que talvez nunca iria descobrir se não fosse programando.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;→ A FullScreen API não aceita que seja disparado o evento &lt;code&gt;requestFullScreen()&lt;/code&gt; sem a interação do usuário, ou seja, só é possível via clique. Para resolver isso, ou tentar, fiz um full screen manual, alterando o tamanho do player para o tamanho da janela.&lt;/li&gt;

&lt;li&gt;→ O Chrome e o Firefox são os únicos navegadores que suportão reproduzir blobs urls. Os outros navegadores, mesmo tendo suporte para blobs urls, não conseguem reproduzir um vídeo o música. Foi ai que resolvi adicionar o campo para adicionar uma media por URL, dessa forma consigo reproduzir o arquivo.&lt;/li&gt;

&lt;li&gt;→ Para manter o Node.JS rodando no meu servidor (em http://vagnersantana.com/player.io), estou utilizando o &lt;code&gt;forever&lt;/code&gt;. Para instalar é só mandar o comando &lt;code&gt;npm install forever&lt;/code&gt; e para executá-lo: &lt;code&gt;forever start app.js&lt;/code&gt;. Assim o socket.io e o express ficaram escutando constantemente nas portas 8080 e 8000. Para visualizar quais arquivos o forever está executando use o comando &lt;code&gt;forever list&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='concluso'&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Tem muito mais código na aplicação toda, o post já está gigantesco, mas espero ter explicado todo o conceito de utilizar o Node.JS e o Socket.IO.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Apesar de ser um experimento simples, foi extremamente empolgante ter desenvolvido, pois só assim é possível aprender de verdade. Espero que este post ajude você de alguma forma, seja com node.js, socket.io ou express, ou seja para incentivar a desenvolver experimentos, brincar mais, fazer qualquer tipo de coisa que te faça adquirir mais conhecimento sempre, buscar mais informações, e depois, contribuir ensinando.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;O código está disponível no Github, espero que você vá até lá, de um fork, envie pull requests, reportem bugs e tudo mais que tiver direito.&lt;/p&gt;
&lt;br /&gt;&lt;a href='http://vagnersantana.com/player.io' title='Player.IO' target='_blank' alt='Player.IO'&gt;
&lt;button class='btn'&gt;Player.IO&lt;/button&gt;
&lt;/a&gt;&lt;a href='https://github.com/vagnervjs/player.io' title='Demo no github' target='_blank' alt='Demo no github'&gt;
&lt;button class='btn'&gt;Github&lt;/button&gt;
&lt;/a&gt;
&lt;h3 id='referncias'&gt;Referências&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;→ &lt;a href='http://www.html5rocks.com/en/tutorials/websockets/basics/' target='_blank'&gt;HTML5 Rocks - Introducing WebSockets: Bringing Sockets to the Web&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;→ &lt;a href='http://davidwalsh.name/websocket' target='_blank'&gt;David Walsh - WebSocket and Socket.IO&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;→ &lt;a href='http://imasters.com.br/desenvolvimento/conectando-no-socket-io-avancado/' target='_blank'&gt;iMasters - Conectando no Socket.IO – avançado&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;→ &lt;a href='http://socket.io/#how-to-use' target='_blank'&gt;Socket.IO - How to use&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;→ &lt;a href='http://www.ibm.com/developerworks/br/library/os-nodejs/' target='_blank'&gt;IBM - O que exatamente é o Node.js?&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;→ &lt;a href='http://expressjs.com/api.html' target='_blank'&gt;Express API Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- Tweet Button --&gt;&lt;a href='https://twitter.com/share' class='twitter-share-button' data-lang='pt'&gt;Tweetar&lt;/a&gt;&lt;script&gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=&quot;//platform.twitter.com/widgets.js&quot;;fjs.parentNode.insertBefore(js,fjs);}}(document,&quot;script&quot;,&quot;twitter-wjs&quot;);&lt;/script&gt;&lt;!-- Facebook Like --&gt;&lt;div class='fb-like' data-send='true' data-width='450' data-layout='button_count' data-href='http://openblog.github.com/2013/03/15/player.io' data-show-faces='true' data-font='segoe ui' /&gt;
    </content>
  </entry>
  
  <entry>
    <id>http://loopinfinito.com.br/2013/02/25/html5-web-messaging-api</id>
    <title>Web Messaging API</title>
    <updated>2013-02-25T00:00:00-08:00</updated>
    <link href="http://openblog.github.com/2013/02/25/html5-web-messaging-api/" />
    <author>
      <name>Vagner Santana</name>
      <uri>http://twitter.com/vagnervjs</uri>
    </author>
    <content type="html">
      
      
      &lt;p&gt;&lt;img itemprop=&quot;thumbnailUrl&quot; src=&quot;http://openblog.github.com/img/posts/2013-02-25-message.jpg&quot; alt=&quot;Web Messaging API&quot; title=&quot;Web Messaging API&quot; width=&quot;700&quot; height=&quot;432&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Provavelmente em algum projeto você já foi obrigado a utilizar um &lt;code&gt;iframe&lt;/code&gt; para carregar conteúdo de uma página externa, e desde então só era possível visualizar o conteúdo do mesmo, e ele funciona como uma sandbox onde não existe comunicação com sua aplicação. Nas especificações do W3C o &lt;abbr title='HyperText Markup Language 5'&gt;HTML5&lt;/abbr&gt; possui algumas &lt;abbr title='Application Program Interface'&gt;APIs&lt;/abbr&gt; para comunicação. Este post trata especificamente uma delas: a HTML5 Web Messaging API que resolve o problema descrito.&lt;/p&gt;

&lt;h2 id='api'&gt;API&lt;/h2&gt;

&lt;p&gt;Essa é uma &lt;abbr title='Application Program Interface'&gt;API&lt;/abbr&gt; simples, que resolve o problema de comunicação entre aplicações hospedadas em diferentes origens. Antes da existência dessa API, não era possível essa comunicação devido a &amp;#8220;política da mesma origem&amp;#8221;, onde não é possivel uma programação client-side de uma origem acesse ou interfira em um documento de outra origem. Resumindo: um script hopedado em um lugar não consegue acessar o DOM de um documento de outra origem. A origem pode ser 3 tipos: protocolo, host e porta. &lt;br /&gt;&lt;br /&gt; Exemplo: digamos que a origem de minha aplicação seja o URL: http://openblog.com.br/mensagem.php&lt;/p&gt;
&lt;div class='tbl'&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;th&gt;URL&lt;/th&gt;
      &lt;th&gt;Mesma origem?&lt;/th&gt;
      &lt;th&gt;Razão&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;http://openblog.com.br/recebe.php&lt;/td&gt;
      &lt;td&gt;Sim&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;http://openblog.com.br&lt;/td&gt;
      &lt;td&gt;Sim&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;https://openblog.com.br/auth.php&lt;/td&gt;
      &lt;td&gt;Não&lt;/td&gt;
      &lt;td&gt;Protocolo diferente&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;http://openblog.com.br:9000/recebe.php&lt;/td&gt;
      &lt;td&gt;Não&lt;/td&gt;
      &lt;td&gt;Porta Diferente&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;http://blog.openblog.com.br/recebe.php&lt;/td&gt;
      &lt;td&gt;Não&lt;/td&gt;
      &lt;td&gt;Host Diferente&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h2 id='mtodo_windowpostmessage'&gt;Método window.postMessage()&lt;/h2&gt;

&lt;p&gt;Este método é o responsável por criar uma mensagem a ser enviada para um objeto &lt;code&gt;window&lt;/code&gt; em uma origem diferente. O padrão do tipo da mensagem é uma &lt;i&gt;string&lt;/i&gt;. O método recebe três parâmetros: dois obrigatórios e um opcional.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;  &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;postMessage&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;mensagem&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;destino&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;portas&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt;  
  &lt;span class='c1'&gt;//mensagem: string a ser enviada&lt;/span&gt;
  &lt;span class='c1'&gt;//destino: endereço a ser enviado&lt;/span&gt;
  &lt;span class='c1'&gt;//portas: array de portas válidas para o destino&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O destino pode ser um URL absoluto, um caractere curinga &lt;code&gt;*&lt;/code&gt; que servirá para qualquer destino ou um caractere barra &lt;code&gt;/&lt;/code&gt; que adota a política da mesma origem (ou seja, apenas o mesmo host da página).&lt;/p&gt;

&lt;h2 id='evento_message'&gt;Evento message&lt;/h2&gt;

&lt;p&gt;A &lt;abbr title='Application Program Interface'&gt;API&lt;/abbr&gt; prevê o evento &lt;code&gt;message&lt;/code&gt; que é disparado no documento destino da mensagem. Quando disparado ele chama a seguinte função callback:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addEventListener&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addEventListener&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;attachEvent&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;onmessage&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
  &lt;span class='p'&gt;};&lt;/span&gt;

  &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
      &lt;span class='c1'&gt;//faça algo com a mensagem&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A função &lt;code&gt;receberMsg&lt;/code&gt; como o nome já diz, recebe um parâmetro que retorna um objeto-evento com as propriedades:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;  &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt; &lt;span class='c1'&gt;//text da mensagem&lt;/span&gt;
  &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;origin&lt;/span&gt; &lt;span class='c1'&gt;//origem da mensagem&lt;/span&gt;
  &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;lastEventId&lt;/span&gt; &lt;span class='c1'&gt;//string identificadora do último evento&lt;/span&gt;
  &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;source&lt;/span&gt; &lt;span class='c1'&gt;//retorna WindowProxy do destino&lt;/span&gt;
  &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ports&lt;/span&gt; &lt;span class='c1'&gt;//array das portas enviadas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id='mos_na_massa'&gt;Mãos na massa&lt;/h2&gt;

&lt;p&gt;Vamos criar a situação mencionada no início do post, onde um documento de origem A tenta se comunicar com um documento de origem B. A idéia é postar uma mensagem e ela aparecer no &lt;code&gt;iframe&lt;/code&gt;. Vamos lá&amp;#8230;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documento A (http://openblog.github.com/demos/html5_msg_origin)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;  &lt;span class='c1'&gt;//Javascript&lt;/span&gt;
  &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onload&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(){&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;objIframe&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementsByTagName&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;iframe&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;btnEnviar&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;  &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementsByTagName&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;button&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

    &lt;span class='nx'&gt;btnEnviar&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onclick&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(){&lt;/span&gt;
      &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;textoMsg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementsByTagName&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;input&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

      &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;textoMsg&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
        &lt;span class='nx'&gt;alert&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Digite uma mensagem!&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;objIframe&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;contentWindow&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;postMessage&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;textoMsg&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://labs.vagnersantana.com&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;  &lt;span class='c'&gt;&amp;lt;!-- HTML --&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Mensagem: &lt;span class='nt'&gt;&amp;lt;input&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;button&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;button&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;Enviar mensagem&lt;span class='nt'&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;http://labs.vagnersantana.com/html5_msg_iframe.html&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Documento B (http://labs.vagnersantana.com/html5_msg_iframe.html)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;  &lt;span class='c1'&gt;//Javascript &lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addEventListener&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
    &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addEventListener&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nb'&gt;window&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;attachEvent&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;onmessage&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
  &lt;span class='p'&gt;};&lt;/span&gt;

  &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;receberMsg&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;containerMsg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementById&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;recebe-msg&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;origin&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://openblog.github.com&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
      &lt;span class='nx'&gt;msg&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Mensagem recebida: &amp;lt;br&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='nx'&gt;msg&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Msg: &amp;#39;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;lt;br&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='nx'&gt;msg&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Origem: &amp;#39;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;origin&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

      &lt;span class='nx'&gt;containerMsg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;innerHTML&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nx'&gt;containerMsg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;innerHTML&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Origem não autorizada!&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;  //HTML
  &lt;span class='nt'&gt;&amp;lt;p&lt;/span&gt; &lt;span class='na'&gt;id=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;recebe-msg&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O Web Messaging envia uma string, porém não precisa se desesperar e pensar em ir separando os dados por &lt;code&gt;|&lt;/code&gt; ou &lt;code&gt;;&lt;/code&gt; pois felizmente existe o maravilhoso &lt;code&gt;JSON&lt;/code&gt; que oferece a funcionalidade de se transformar em string com o método &lt;code&gt;JSON.stringify&lt;/code&gt; e recuperá-lo usando o &lt;code&gt;JSON.parse()&lt;/code&gt;, desta forma podemos trocar e manipular dados de maneira fácil somando o Web Messaging com JSON.&lt;/p&gt;

&lt;h2 id='can_i_use_'&gt;Can i use ?&lt;/h2&gt;
&lt;a href='http://caniuse.com/#search=messaging' title='Can i use: Web Messaging API' target='_blank' alt='Can i use: Web Messaging API'&gt;
  &lt;img src='http://openblog.github.com/img/posts/ciu_messaging.png' alt='Can i use table of Web Messaging API' /&gt;
&lt;/a&gt;
&lt;p&gt;Para ver a &lt;abbr title='Application Program Interface'&gt;API&lt;/abbr&gt; em ação é só clicar no demo abaixo, sinta-se à vontade em inspecionar o código e também fazer um fork no github. Divirta-se.&lt;/p&gt;
&lt;a href='/demos/html5_msg_origin/' title='Demo' target='_blank' alt='Demo'&gt;
    &lt;button class='btn'&gt;DEMO&lt;/button&gt;
  &lt;/a&gt;&lt;a href='https://github.com/vagnervjs/Web-Messaging-API' title='Demo no github' target='_blank' alt='Demo no github'&gt;
    &lt;button class='btn'&gt;Github&lt;/button&gt;
  &lt;/a&gt;&lt;h3&gt;Referências&lt;/h3&gt;&lt;ul&gt;
    &lt;li&gt;→&lt;a href='http://livrohtml5.com.br/' title='Livro HTML5 do Maujor' alt='Livro HTML5 do Maujor'&gt;Livro HTML5 do Maujor, Capítulo 9&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;→&lt;a href='http://www.w3.org/TR/2010/WD-webmessaging-20101118/' title='W3C Working Draft: HTML5 Web Messaging' alt='W3C Working Draft: HTML5 Web Messaging'&gt;W3C Working Draft: HTML5 Web Messaging&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;→&lt;a href='https://github.com/DamonOehlman/talk-html5-messaging' title='Damon Oehlman: Talk HTML5 Messaging' alt='Damon Oehlman: Talk HTML5 Messaging'&gt;Damon Oehlman: Talk HTML5 Messaging&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;&lt;div class='fb-like' data-send='true' data-width='450' data-layout='button_count' data-href='http://openblog.github.com/2013/02/25/html5-web-messaging-api/' data-show-faces='true' data-font='verdana' /&gt;
    </content>
  </entry>
  
  <entry>
    <id>http://loopinfinito.com.br/2013/02/24/hello-world</id>
    <title>Hello World</title>
    <updated>2013-02-24T00:00:00-08:00</updated>
    <link href="http://openblog.github.com/2013/02/24/hello-world/" />
    <author>
      <name>Vagner Santana</name>
      <uri>http://twitter.com/vagnervjs</uri>
    </author>
    <content type="html">
      
      
      &lt;p&gt;&lt;img itemprop=&quot;thumbnailUrl&quot; src=&quot;http://openblog.github.com/img/posts/2013-02-24-hello-world.jpg&quot; alt=&quot;Hello World&quot; title=&quot;Hello World&quot; width=&quot;700&quot; height=&quot;432&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Somos alguns caras da computação, queremos bater papo, ajudar, receber ajuda, comparitlhar, criar, brincar. Afinal de contas, vocês estudam, trabalham, mas já pararam pra pensar que o que vale mesmo, é contribuir de alguma forma com o mundo? Não, não é saciar a fome na África, ou o analfabetismo no Brasil, é o seu mundo de que estou falando, é o que está próximo de ti, vamos lá, pense&amp;#8230; é isso que queremos fazer aqui, contribuir com o nosso mundo, de forma que todos podemos crescer. Abra sua mente, bora?&lt;/p&gt;
    </content>
  </entry>
  
</feed>