JSF 2 fu: Componentes Compostos HTML5, Parte 1

Comece a implementar uma biblioteca de componentes HTML5 com o JSF 2

O HTML5 dá aos aplicativos baseados em navegador recursos ricos que rivalizam com os dos softwares de desktop. Nesta parte sobre JSF 2 fu , você verá como aproveitar ao máximo o Java™ e o HTML5 ao implementar um componente composto de HTML5 com JavaServer Faces (JSF) 2.

David Geary, President, Clarity Training, Inc.

David GearyO autor, palestrante e consultor David Geary é o presidente da Clarity Training, Inc. onde ensina desenvolvedores a implementarem aplicativos da Web usando JSF e Google Web Toolkit (GWT). Ele fez parte dos Grupos de Especialistas do JSTL 1.0 e do JSF 1.0/2.0, foi coautor do Exame de Certificação de Desenvolvedor da Web da Sun e contribuiu para projetos de software livre, incluindo o Apache Struts e o Apache Shale. Graphic Java Swing de David foi um dos livros de Java mais vendidos de todos os tempos e Core JSF (coescrito com Cay Horstman) é o livro de JSF mais vendido. David fala frequentemente em conferências e para grupos de usuários. É frequentador assíduo do tour de NFJS desde 2003, deu cursos na Java University e foi duas vezes votado como JavaOne rock star.



14/Abr/2011

O HTML5 é, evidentemente, o próximo grande "astro" do desenvolvimento de software. Originalmente conhecido como Web Applications, o HTML5 finalmente traz toda a capacidade dos aplicativos de desktop — completa, com recursos como arrastar e soltar, telas, vídeo e áudio — para o navegador. O HTML5 é uma coleção de tecnologias (mais especificamente, especificações) que formam uma API potente que engloba HTML, JavaScript, e Cascading Stylesheets (CSS). Estes são os destaques do HTML5:

Sobre esta série

A série JSF 2 fu , uma sequência da introdução de três artigos de David Geary com o mesmo nome, ajudará a desenvolver e aperfeiçoar as suas qualificações na estrutura JSF 2 como um mestre de kung fu. A série atual se aprofunda na estrutura e em seu ecossistema circundante. Além disso, usa a criatividade ao mostrar como algumas tecnologias Java EE, como injeção de contextos e dependência, se integram ao JSF.

  • Tela
  • Arrastar e soltar
  • Geolocalização*
  • Edição sequencial
  • Web Workers*
  • Armazenamento na Web*
  • Sistema de mensagens
  • Aplicativos off-line
  • Vídeo e áudio*
  • Soquetes da Web*

Observe os recursos vanguardistas como geolocalização e aplicativos off-line. (Os recursos marcados com um asterisco não fazem parte da especificação HTML5 sob o ponto de vista técnico, mas o termo HTML5 é usado de forma coloquial para englobar todos os que eu listei. Consulte a seção Recursos para obter mais informações.)

Em alguns aspectos, o HTML5 é o próximo Java. No final da década de 90, a linguagem Java se tornou imensamente difundida — em grande parte, porque o recurso escreva uma vez, execute em qualquer lugar livrou os desenvolvedores de ter que portar ou escolher entre Windows®, Mac ou Linux®. o HTML5 permite escrever uma vez e executar em qualquer navegador (moderno), para que você não precise escolher entre iOS, Android e Chrome.

Escreva uma vez, depure em qualquer lugar?

A tecnologia Java permite escrever um aplicativo para diversos sistemas operacionais, mas não faz isso com perfeição. O HTML5 também não. O HTML5 não oferece alguns dos recursos que os sistemas operacionais nativos fornecem, como a interação com um acelerômetro (embora existam kits de ferramentas — com o PhoneGap [consulte Recursos ] — que preenchem essa lacuna). Essas imperfeições sempre farão com que alguns desenvolvedores prefiram os aplicativos nativos e não o HTML5. Porém, para diversos aplicativos, o HTML5 fornece um retorno sobre investimento melhor.

Surge a tecnologia Java

O HTML5 pode ser o próximo Java, mas não irá substituí-lo. A tecnologia Java fornece um ecossistema rico para a programação no lado do servidor. O JSF — que, para começo de conversa, é baseado em HTML, permite usar o HTML5 com a mesma facilidade com o qual você vem usando o HTML4 com JSF até agora. Você obtém todos os recursos potentes do JSF, como modelos de facelets, componentes compostos e Ajax integrado, além do HTML5.

Neste artigo, você aprenderá a criar componentes compostos HTML5 com o JSF2. No próximo artigo sobre JSF 2 fu , eu mostrarei como criar uma biblioteca de componentes HTML5.

Iniciação em HTML5

O uso do HTML5 envolve muito mais JavaScript que HTML. Isso significa que é necessário ter um bom depurador de JavaScript. Eu recomendo o que vem com as Developer Tools integradas ao Google Chrome (consulte Recursos ), mostrado na Figura 1:

Figura 1. Depurando o JavaScript com Chrome Developer Tools
Depurando o JavaScript com Chrome Developer Tools

No depurador do Chrome mostrado na Figura 1, um painel que contém o código JavaScript aparece abaixo do componente de tela exibido.

Agora que você tem um bom depurador de Javascript, só precisa de um navegador habilitado para HTML5. A maioria das versões mais recentes dos navegadores mais conhecidos oferecem um bom suporte para HTML5. (Aparentemente, a Microsoft terá um bom suporte para HTML5 no Internet Explorer 9, que será lançado em breve.)


Usando a tela do HTML5

A tela do HTML5 é uma superfície de desenho em 2D completa, que é suficientemente rica para oferecer suporte a jogos como Plants vs. Zombies e Quake II. o meu uso da tela do HTML5, mostrado na Figura 2, talvez não seja tão convincente, mas é suficiente para fins instrutivos:

Figura 2. Um exemplo simples de tela do HTML5
Um exemplo simples de tela do HTML5

Acrescentei um pouco de JavaScript a uma tela do HTML5 para implementar o aplicativo simples de colorir mostrado na Figura 2. Conforme você move o mouse, as coordenadas do mouse são mostradas na parte superior esquerda da tela. Ao arrastar o mouse na tela, você pinta com um pincel azul.

O aplicativo mostrado na Figura 2 é um aplicativo JSF. A Figura 3 mostra a sua estrutura de diretório:

Figura 3. Estrutura de diretório do exemplo de tela
Estrutura de diretório do exemplo de tela

O facelet único do aplicativo é definido em web/WEB-INF/index.xhtml, e o Javascript do aplicativo está em web/resources/application/paintingCanvas.js. A Listagem 1 mostra o index.xhtml:

Listagem 1. Usando a tag <canvas> (WEB-INF/index.xhtml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html">

   <h:head>
      <title>#{msgs.windowTitle}</title>
   </h:head>
   
   <h:body style="background: #fefeef">
      <h:outputScript library="application" name="paintingCanvas.js" 
                       target="head" />
      
      <h3>#{msgs.heading}</h3>
   
   
      <canvas width="400px" height="400px" id="paintingCanvas">

         Canvas not supported. 
         
      </canvas>     
   </h:body>  
   
</html>

O arquivo index.xhtml da Listagem 1 é chamado de documento poliglota HTML5 (consulte Recursos ), porque tem tipo de documento/namespace HTML5 e uma sintaxe bem-formada de XHTML — exatamente o que é necessário para a minha mistura de facelets e HTML5.

Eu importo o Javascript correspondente com a tag <h:outputScript> . Finalmente, eu me aprofundo e uso o elemento de tela do HTML5. Se o navegador não entende a tag <canvas> , ele exibe a mensagem Canvas not supported . A tag <canvas> é despretensiosa — todo o código interessante está no Javascript correspondente, mostrado na Listagem 2:

Listagem 2. Javascript da tela de colorir (resources/application/paintingCanvas.js)
window.addEventListener("load", function() {
   var canvas, context, painting;
   
   function init() {
      canvas = document.getElementById("paintingCanvas");
      if (canvas == null) return;
      
      context = canvas.getContext("2d");
      if (context == null) return;
   
      painting = false;
      
      context.strokeStyle = "#00f";
      context.lineWidth = 3;
      context.font = "15px Helvetica";
   }

   init();
   
   canvas.addEventListener("mousedown", function(ev) {
      painting = true;
      context.beginPath();
      context.moveTo(ev.offsetX, ev.offsetY);
   }, false);
   
   canvas.addEventListener("mousemove", function(ev) {
      updateReadout(ev.offsetX, ev.offsetY);

      if (painting) {
        paint(ev.offsetX, ev.offsetY);
      }
      function updateReadout(x, y) {
         context.clearRect(0, 0, 100, 20);
         context.fillText("x: " + x + ",  y: " + y, 5, 15);
      }
      function paint(x, y) {
         context.lineTo(ev.offsetX, ev.offsetY);
         context.stroke();
      }
         
   }, false);
   
   canvas.addEventListener("mouseup", function() {
      painting = false;
      context.closePath();
   }, false);
   
   
 }, false);

Executando o código de amostra

O código dessa série é baseado no JSF 2 em execução em um contêiner corporativo, como o GlassFish ou Resin. Consulte a primeira parte da série, "JSF 2 fu: Componentes Ajax"para obter um tutorial passo a passo sobre como instalar e executar o código desta série com GlassFish. Consulte a seção Download para obter o código de amostra deste artigo.

A Listagem 2 implementa pintura simples com um uma leitura do cursor do mouse, como mostra a Figura 2. Quando a página carrega, eu obtenho uma referência à tela com document.getElementById(). A partir da tela, eu obtenho a referência ao contexto da tela. Uso esse contexto em manipuladores de eventos subsequentes, que implemento usando encerramentos de JavaScript ou aquilo que os desenvolvedores de Java chamam de classes internas anônimas.

Se você já usou o Abstract Window Toolkit (AWT), deve notar que o contexto da tela lembra bastante o contexto gráfico do AWT. Afinal, não há muitos modos diferentes de desenhar formas, imagens e texto em duas dimensões. Na Listagem 2, eu inicializo o contexto com um estilo de traço azul e defino a largura da linha e a fonte. Desse ponto em diante, é só uma questão de mover, traçar, repetir, quando o mouse desce, arrasta e sobe respectivamente.

Agora que você aprendeu os fundamentos da tela do HTML5, eu mostrarei como criar um componente composto JSF 2 HTML5.


Um componente de tela de JSF 2 HTML5

Em seguida, implementarei um componente composto JSF 2 que usa uma tela HTML5. Preciso do componente composto para preencher estes requisitos:

  • Ter largura, altura, cor de caneta, largura da linha e estilo de CSS configuráveis (por meio de atributos de tag).
  • Usar o corpo da tag do componente como a mensagem canvas not supported
  • Incluir automaticamente o Javascript da tela
  • Suportar diversos componentes de tela em uma única página

A Figura 4 mostra um aplicativo que usa o componente composto de tela:

Figura 4. O componente de composto de tela em ação
O componente de composto de tela em ação

O aplicativo mostrado na Figura 4 tem três componentes de tela, cada um configurado de forma diferente. Começando da esquerda, os dois primeiros são telas de colorir, semelhantes ao que é mostrado na Figura 2. A tela que está mais à direita simplesmente colore um rosto sorridente.

A Listagem 3 mostra a marcação da página mostrada na Figura 4:

Listagem 3. Usando o componente composto de tela (WEB-INF/index.xhtml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:h5="http://java.sun.com/jsf/composite/html5">

   <h:head>
      <meta charset="UTF-8" />
      <title>#{msgs.windowTitle}</title>
   </h:head>
   
   <h:body style="background: #fefeef">
      
      <h3>#{msgs.heading}</h3>
   
      <h5:canvas id="paintingCanvas" width="300px" height="300px" 
                 penColor="#7F7" lineWidth="7">
              
         #{msgs.canvasUnsupported}

      </h5:canvas>     
      
      <h5:canvas id="secondPaintingCanvas" width="300px" height="300px"
                 style="border: thick solid red">

         #{msgs.canvasUnsupported}

      </h5:canvas>  
      
      <h5:canvas id="smileyCanvas" library="application" script="smiley.js"
                 width="300px" height="300px"
                 style="border: thin solid red">

         #{msgs.canvasUnsupported}

      </h5:canvas>
   </h:body>  
   
</html>

Na Listagem 3, o componente de tela importa o Javascript adequado — diferentemente da Listagem 1, na qual eu uso o HTML5 a mão e preciso importar explicitamente o Javascript associado. Os autores de página podem usar a biblioteca opcional do componente de tela e os atributos de script para especificar o Javascript da tela ou podem se basear no Javascript padrão. Na Listagem 3, eu uso o atributo script para a tela do rosto sorridente. Uso o Javascript padrão (resources/html5/canvasDefault.js, que implementa a tela de colorir) nas duas telas do exemplo que estão mais à esquerda.

A Listagem 4 mostra a implementação do componente composto de tela:

Listagem 4. O componente de composto de tela (resources/html5/canvas.xhtml)
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="id"/>  
    <composite:attribute name="width"/>
    <composite:attribute name="height"/>   
    <composite:attribute name="library"  default="html5"/>
    <composite:attribute name="script"   default="canvasDefault.js"/>
    <composite:attribute name="style"    default="border: thin solid blue"/>
    <composite:attribute name="penColor" default="#7777FF"/>
    <composite:attribute name="lineWidth" default="2"/>
  </composite:interface>
  
  <composite:implementation>
      <canvas id="#{cc.id}"
           width="#{cc.attrs.width}" 
          height="#{cc.attrs.height}"
           style="#{cc.attrs.style}">
                                
      <composite:insertChildren/>
           
     </canvas>
    
    <h:outputScript library="#{cc.attrs.library}" 
                       name="#{cc.attrs.script}"/>
                       
    <script>
      #{cc.attrs.script}.init('#{cc.id}', 
                              '#{cc.attrs.penColor}', 
                              '#{cc.attrs.lineWidth}')
    </script>                                                 
  </composite:implementation>
</html>

Na Listagem 4, eu declaro oito atributos para o componente composto de tela — cinco deles com os valores padrão. A implementação do componente contém uma tela HTML5 com ID, largura, altura e estilo configurados a partir dos atributos relevantes do componente. Isso preenche o primeiro requisito (atributos configuráveis) do componente de tela.

O componente composto de tela insere os seus filhos — ou seja, qualquer coisa que esteja no corpo da tag <h5:canvas>— na tag da tela HTML5 (<canvas>). Isso significa que qualquer texto que esteja no corpo da tag será exibido se o navegador não oferecer suporte a telas HTML5. Isso preenche o segundo requisito (usar o corpo da tag do componente para a mensagem canvas not supported ).

O componente de tela contém uma tag <h:outputScript> que importa o Javascript da tela, que é especificado com a biblioteca e o script do componente de tela. Observe que os atributos de biblioteca e script adotam por padrão html5 e canvasDefault.js, respectivamente. Isso preenche o terceiro requisito (importar automaticamente o JavaScript da tela).

Finalmente, o componente de tela chama um método de JavaScript denominado init(),, passando o ID, cor da caneta e largura da linha da tela. O método init(), obtém e inicializa o contexto da tela. Observe que eu disse método, não função, porque o método init(), pertence a um objeto. O nome desse objeto é derivado do atributo de script do componente de tela. Por exemplo: na tela do rosto sorridente da Listagem 3, eu especifico o valor de script de smiley.js; portanto, o componente de tela do rosto sorridente chamará smiley.js.init()— o método init(), de um objeto chamado js, contido em um objeto chamado smiley. Se você não especifica o valor de script explicitamente, ele adota por padrão canvasDefault.js. Consequentemente, o método JavaScript seria canvasDefault.js.init(). O fato de chamar esses métodos em vez de funções globais permite preencher o quarto requisito: oferecer suporte a diversas telas em uma única página.

O JavaScript padrão para o componente de tela é mostrado na Listagem 5:

Listagem 5. O Javascript padrão da tela (resources/html5/canvasDefault.js)
if (!canvasDefault) var canvasDefault = {}

if (!canvasDefault.js) {
  canvasDefault.js = {
    init : function(canvasId, penColor, lineWidth) {
      var canvas, context, painting;

      canvas = document.getElementById(canvasId);
      if (canvas == null) {
        alert("Canvas " + canvasId + " not found")
      }

      context = canvas.getContext("2d")
      if (context == null)
        return;

      painting = false;

      context.strokeStyle = penColor
      context.lineWidth = lineWidth
      context.font = "15px Helvetica"

      canvas.addEventListener("mousedown", function(ev) {
        painting = true
        context.beginPath()
        context.moveTo(ev.offsetX, ev.offsetY)
      }, false)

      canvas.addEventListener("mousemove", function(ev) {
        updateReadout(ev.offsetX, ev.offsetY)

        if (painting) {
          paint(ev.offsetX, ev.offsetY)
        }
        function updateReadout(x, y) {
          context.clearRect(0, 0, 100, 20)
          context.fillText("x: " + x + ",  y: " + y, 5, 15)
        }
        function paint(x, y) {
          context.lineTo(ev.offsetX, ev.offsetY)
          context.stroke()
        }

      }, false)

      canvas.addEventListener("mouseup", function() {
        painting = false
        context.closePath()
      }, false)
    }
  }
}

Na Listagem 5, eu crio um objeto chamado canvasDefault, que contém um objeto chamado js, o qual contém um método init(), . Eu faço isso com o namespace o método init(), para que não seja substituído por outra função global init(), . Dessa forma, posso colocar diversas telas em uma única página, todas com as suas próprias implementações de uma função init(), .

A Listagem 6 mostra o JavaScript referente à tela do rosto sorridente:

Listagem 6. O Javascript da tela do rosto sorridente (resources/application/smiley.js)
if (!smiley) var smiley = {}

if (!smiley.js) {
  smiley.js = {
    init : function(canvasId, penColor, lineWidth) {
      var canvas, context

      canvas = document.getElementById(canvasId);
      if (canvas == null) {
        alert("Canvas " + canvasId + " not found")
      }

      context = canvas.getContext("2d");
      if (context == null)
        return

      // smiley face code originally downloaded
      // from thinkvitamin.com
        
      // Create the face

      context.strokeStyle = "#000000";
      context.fillStyle = "#AAAAFF";
      context.beginPath();
      context.arc(100,100,50,0,Math.PI*2,true);
      context.closePath();
      context.stroke();
      context.fill();
      
      // eyes              
      context.strokeStyle = "#000000";
      context.fillStyle = "#FFFFFF";
      context.beginPath();
      context.arc(80,80,8,0,Math.PI*2,true);
      context.closePath();
      context.stroke();
      context.fill();
      
      context.fillStyle = "#0000FF";
      context.beginPath();
      context.arc(80,80,5,0,Math.PI*2,true);
      context.closePath();
      context.fill();
      
      context.strokeStyle = "#000000";
      context.fillStyle = "#FFFFFF";
      context.beginPath();
      context.arc(120,80,8,0,Math.PI*2,true);
      context.closePath();
      context.stroke();
      context.fill();
      
      context.fillStyle = "#0000FF";
      context.beginPath();
      context.arc(120,80,5,0,Math.PI*2,true);
      context.closePath();
      context.fill();
      
      // nose
      context.fillStyle = "#000000";
      context.beginPath();
      context.moveTo(93,100);
      context.lineTo(100,93);
      context.lineTo(107,100);
      context.closePath();
      context.fill();

      // smile              
      context.strokeStyle = "#000000";
      context.beginPath();
      context.moveTo(70,110);

      context.quadraticCurveTo(100,150,130,110);       
      context.closePath();
      context.stroke();    
    }
  }
}

A Listagem 6 cumpre a mesma convenção de namespacing usada na Listagem 5. O Javascript subsequente dos outros tipos de telas deve seguir a mesma convenção.


Conclusão

Neste artigo, apresentei a você o HTML5 e mostrei como implementar uma componente composto de tela JSF 2 HTML5 que facilita o uso das telas HTML5 por parte dos desenvolvedores de JSF e autores de páginas. Mostrei como passar informações, obtidas a partir da linguagem de expressão, para o JavaScript associado a um componente composto e como fazer o namespace das funções de JavaScript para que as funções com nomes iguais não prejudiquem umas às outras. Na próxima parte do JSF 2 fu, mostrarei como implementar outro componente HTML5 e como colocar diversos componentes HTML5 em uma biblioteca reutilizável que pode ser distribuída a outros desenvolvedores em um arquivo JAR.


Download

DescriçãoNomeTamanho
Sample code for this articlej-jsf2fu-1010.zip49KB

Recursos

Aprender

Discutir

  • Participe do comunidade do My developerWorks. Entre em contato com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=647309
ArticleTitle=JSF 2 fu: Componentes Compostos HTML5, Parte 1
publish-date=04142011