Avançar para a área de conteúdo

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

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

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

  • Fechar [x]

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.

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

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

  • Fechar [x]

Desenvolvendo Widgets com o Dojo 1.x

Marco Lerro, Staff Engineer, IBM
Photo of Marco Lerro
Marco é um engenheiro da equipe do Laboratório Tivoli da IBM Roma desde 1999. Atualmente está envolvido no design e desenvolvimento do TDWC. Sua área de interesse atual é desenvolvimento em Web 2.0, com ênfase especial em tecnologias baseadas em Dojo e padrões de design baseados em experiência de usuário.
Roberto Longobardi, Interaction Solution Designer, IBM Tivoli Software
Roberto Longobardi
Roberto trabalha na área de desenvolvimento de software há doze anos, cobrindo diversas funções, desde desenvolvedor, analista, designer de interface da Web até designer de interação. Trabalha atualmente na organização Tivoli como um designer de interface com o usuário da Web para os produtos Tivoli Workload Scheduler e Dynamic Workload Broker. Dessa forma, também está frequentemente envolvido nas atividades diretas com o cliente, como reunir requisitos, validar o design e ativar as vendas. Roberto publicou diversos artigos no developerWorks, apresentados em conferências de IEEE, e está envolvido em diversas colaborações acadêmicas.
Gianluca Perreca, Staff Engineer, IBM Tivoli Software
Gianluca Perreca's photo
Gianluca Perreca é um engenheiro da equipe do Laboratório Tivoli da IBM Roma. É membro da equipe de desenvolvimento do Tivoli Workload Scheduler e está envolvido ativamente no design e implementação do IBM Tivoli Dynamic Workload Console, a interface da Web para o IBM Tivoli Workload Scheduler.
Alessandro Scotti, Advisory Software Engineer, IBM
Photo of Alessandro Scotti
Alessandro Scotti é o designer chefe do IBM Tivoli Dynamic Workload Console, uma interface da Web para o IBM Tivoli Workload Scheduler que usa o AUIML Toolkit, assim como AUIML e outras tecnologias Web 2.0. Alessandro foi autor ou contribuiu para diversos projetos de software livre, principalmente nas áreas de interface gráfica com o usuário, alto desempenho e programação em tempo real.

Resumo:  Aprenda o básico do desenvolvimento de widgets de HTML usando o kit de ferramentas Dojo JavaScript. Este artigo fornece uma introdução e diversos exemplos para ajudá-lo no processo—começando com widgets de amostra e chegando a widgets mais complexos, enquanto ressalta e soluciona problemas comuns que podem ser encontrados na fase de desenvolvimento.

Data:  28/Abr/2009
Nível:  Introdutório
Atividade:  2192 visualizações
Comentários:  


Introdução

O objetivo deste artigo é fornecer o básico para desenvolver widgets de HTML usando o kit de ferramentas Dojo JavaScript, a partir da versão 1.0. O artigo também descreve diversos exemplos, iniciando com widgets simples e chegando aos mais complexos, enquanto soluciona problemas comuns que podem ser encontrados no desenvolvimento de widgets.


O que É o Kit de Ferramentas Dojo?

Dojo é um kit de ferramentas de software livre baseado em JavaScript para desenvolver aplicativos da Web de HTML dinâmicos. Permite construir rapidamente widgets que podem ser mais complexos do que widgets de HTML padrão. Usar os componentes que Dojo fornece torna suas interfaces com o usuário da Web mais usáveis, responsivas e funcionais. Camadas de nível inferior de API e compatibilidade fornecidas pelo Dojo ajudam a gravar aplicativos compatíveis com diversos navegadores.


Antes de Começar

Antes de iniciar, primeiro, será necessário configurar o ambiente de desenvolvimento. Para fazer isso:

  1. Faça download da versão mais recente liberada do kit de ferramentas Dojo (dojo-release-1.x.x-src.zip ou dojo-release-1.x.x-src.tar.gz) a partir do site do projeto Dojo. (Consulte Recursos para obter um link.)
  2. Descompacte o conteúdo do archive em uma pasta, prestando atenção ao local onde o arquivo dojo.js é descompactado. O sistema do pacote gerencia o carregamento de todos os módulos após dojo.js ter sido carregado na página.

Quando você tiver concluído, a estrutura das pastas será como aquelas mostradas na Figura 1.


Figura 1. Estrutura de Pasta do Arquivo Dojo Expandido
Estrutura de pasta mostrando raiz, com subpasta dojo1.x.x, com subpastas adicionais dijit, dojo, dojox e util.

Dijit é um sistema de widget em camadas sobre o dojo. Através de seu tema, tundra, fornece um design e um esquema de cores comum para todos os seus widgets. Dojox é um pacote de desenvolvimento de extensões para o kit de ferramentas Dojo. É direcionado a alguém que esteja procurando funções que não estão nas coletas comuns.


Widgets do Dojo

Ao navegar nos Web sites, é possível ver centenas de widgets passando por sua tela. Cada botão de seu navegador da Web é um widget. Cada caixa de entrada de texto é um widget. O HTML padrão fornece um conjunto limitado de widgets: uma caixa de entrada, um botão e um hyperlink.

Os widgets do Dojo pegam um item como uma caixa de entrada de texto e incluem funções para um objeto mais fácil e simples, como um calendário gráfico para escolher uma data. Fazem isso sem interromper o item original no qual a nova função é construída.

Um widget do Dojo encapsula componentes da Web visuais para fácil reutilização. É definido por três arquivos:

  • Um arquivo JavaScript que contém a lógica do widget
  • Um arquivo HTML opcional que fornece um modelo semelhante a HTML para o widget
  • Um arquivo CSS, geralmente comum para todos os widgets (o tema), que contém estilos visuais a serem aplicados aos modelos HTML do widget

Importando o Kit de Ferramentas do Dojo

A Lista 2 mostra um esqueleto HTML básico que pode ser usado para importar um widget em uma página da Web normal.


Lista 1. Código HTML para Importar um Widget para uma Página da Web
<html>
   <head>
      <title>Dojo Toolkit Test Page</title>

      <style type="text/css">
         /* código de estilo CSS */
      </style>

 <script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"
 djConfig="parseOnLoad:true, isDebug:true"></script>

      <script type="text/javascript">
         /* código Javascript */
      </script>
   </head>
   <body>
      /* código de definição de Widgets */
   </body>
</html>
            

A primeira tag do script inicializa o kit de ferramentas Dojo simplesmente carregando o arquivo de autoinicialização dojo.js. As propriedades parseOnLoad e isDebug do objeto djConfig são as duas opções de configuração mais comuns que o Dojo examina no tempo de execução. parseOnLoad alterna a análise de marcação no tempo de carregamento, enquanto que isDebug ativa ou desativa as mensagens de depuração. O objeto djConfig também pode ser configurado como uma variável global antes do arquivo dojo.js ser carregado:


Lista 2. Código para Configurar Variáveis Globais com djConfig
<script type="text/javascript">
   var djConfig = {
      isDebug:true, parseOnLoad:true
   };
</script>
<script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"></script>
            

O Sistema de Pacote do Dojo

Dojo possui um sistema de pacote para estruturar as classes do aplicativo em arquivos e carregá-los através da função dojo.require . Essa função permite carregar partes do kit de ferramentas Dojo que ainda não foram fornecidas na base dojo.js.

Para criar um widget, você deve importar a declaração do widget incluindo as linhas da Lista 3.


Lista 3. Código para Importar uma Declaração do Widget
<script type="text/javascript">
   dojo.require("widgets.Button");
</script>
             

Agora, é possível inserir o código a seguir na seção body:

<body>
   <div dojoType="widgets.Button">My Button</div>
</body>
            

O atributo dojoType faz com que o Dojo gerencie a tag de maneira especial. No tempo de carregamento da página, o analisador do Dojo procura a declaração do widget especificada no atributo dojoType , instancia o widget e substitui a tag pelo nó DOM do widget obtido.

Declarando um Widget

Agora, vamos dar uma olhada no exemplo do widget TextBox , definindo um arquivo JavaScript, um arquivo de modelo e um arquivo de estilo CSS.

Primeiro, você deve criar o arquivo JavaScript, TextBox.js, contendo a definição e a lógica do widget. (Consulte a Lista 4.)


Lista 4. Contestações do Arquivo JavaScript TextBox.js
dojo.provide("widgets.TextBox");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare(
    "widgets.TextBox",
    [dijit._Widget, dijit._Templated],
    {
        /** o caminho do modelo */
        templatePath: dojo.moduleUrl("widgets", "templates/TextBox.html"),
        /** o nó DOM de entrada */
        inputNode: null,
        /** o rótulo */
        label: "",

        /** manipulador onkeyup */
        onKeyUp: function() {
            // forneça uma oportunidade ao navegador para atualizar o DOM
            setTimeout(dojo.hitch(this, this.validate), 0);
        },

        /** valide a função */
        validate: function() {
            if ( this.inputNode.value === "Ok" ) {
                // o texto está correto
                dojo.addClass(this.inputNode, "inputOk");
                dojo.removeClass(this.inputNode, "inputError");
            } else {
                 // o texto está incorreto
                 dojo.removeClass(this.inputNode, "inputOk");
                 dojo.addClass(this.inputNode, "inputError");
              }
           }
      }
);
               

dojo.provide() define o nome do novo widget e registra a declaração da classe. Observe que:

  • dijit._Widget e dijit._Templated são superclasses para o widget TextBox
  • templatePath, inputNode e label são atributos do widget
  • onKeyUp() e validate() são as funções que definem a lógica do widget

Agora, é possível definir o arquivo de modelo TextBox.html, conforme mostrado na Lista 5.


Lista 5. Conteúdo do TextBox.html
<span class="textBox">
   ${label}:
   <input
       type="text"
       class="inputOk"
       dojoAttachPoint="inputNode"
       dojoAttachEvent="onkeyup: onKeyUp">
   </input>
</span>
            

A ${label} será substituído pela propriedade label da instância do widget.

A declaração dojoAttachPoint fará com que a propriedade do widget inputNode seja configurada para o nó DOM correspondente à tag de entrada.

A declaração dojoAttachEvent fará com que os eventos onkeyup (vindos do nó de entrada) acionem as chamadas de método do widget onKeyUp .

A classe textBox e inputOk se referem a nomes de classes CSS definidos no arquivo TextBox.css. Consulte a Lista 6.


Lista 6. Nomes de Classes CSS no TextBox.css
.ibm .textBox {
   margin: 5px;
   padding: 5px;
   background-color: #eee;
}

.ibm .inputOk {
   border: 1px solid green;
}

.ibm .inputError {
   border: 1px solid red;
}
            

Como os nomes de classes precisam ser exclusivos no projeto, eles geralmente têm um seletor de CSS (ibm na amostra).

Por fim, o widget pode ser criado na página HTML, conforme mostrado na Lista 7.


Lista 7. Código para Criar o Widget na Página HTML


<html>
   <head>
      <!-- título da página -->
      <title>TextBox Widget</title>
      <!-- inclua o DOJO -->
      <script type="text/javascript" src="../dojo-1.0.0/dojo/dojo.js"
      		djConfig="isDebug: true, parseOnLoad: true">
      </script>

      <!-- importe CSS base do DOJO, tema DIJIT e CSS do widget -->
      <style type="text/css">
         @import "../dojo-1.0.0/dojo/resources/dojo.css";
         @import "../dojo-1.0.0/dijit/themes/tundra/tundra.css";
         @import "templates/TextBox.css";
      </style>

      <!-- importe as coisas do DOJO -->
      <script type="text/javascript">
         dojo.require("dojo.parser");
         <!-- registre nosso caminho do módulo -->
         dojo.registerModulePath("widgets", "../../widget");
         <!-- importe nossas coisas -->
         dojo.require("widgets.TextBox");
      </script>
   </head>

   <body class="tundra ibm" style="padding:5px">
   <br/>
      <!-- declare o widget DOJO -->
      <div
         dojoType="widgets.TextBox"
         label="Name">
      </div>
   </body>
</html>
            

A Figura 2 mostra o widget TextBox .


Figura 2. Caixa de Texto do Widget
Caixa mostando duas caixas de texto menores; uma destacada em verde com ok, uma destacada em vermelho com erro

Declarativo versus Programático

O Dojo suporta dois modelos de programação, declarativo e programático. Ambos os modelos podem ser usados na mesma página se necessário. Na Lista 7, o widget é criado em um modelo declarativo.

<div dojoType="widgets.TextBox" label="Name"></div>

O mesmo widget poderia ser criado em um modelo programático, conforme mostrado na Lista 8.


Lista 8. Criação Programática do Widget TextBox
<html>
   <head>
      <!-- título da página -->
      <title>TextBox Widget</title>
      <!-- inclua o DOJO -->
      <script type="text/javascript" src="../dojo-1.0.0/dojo/dojo.js"
      		djConfig="isDebug: true, parseOnLoad: true">
      </script>

      <!-- importe CSS base do DOJO, tema DIJIT e CSS do widget -->
      <style type="text/css">
         @import "../dojo-1.0.0/dojo/resources/dojo.css";
         @import "../dojo-1.0.0/dijit/themes/tundra/tundra.css";
         @import "templates/TextBox.css";
      </style>

      <!-- importe as coisas do DOJO -->
      <script type="text/javascript">
         dojo.require("dojo.parser");
         <!-- registre nosso caminho do módulo -->
         dojo.registerModulePath("widgets", "../../widget");
         <!-- importe nossas coisas -->
         dojo.require("widgets.TextBox");
      </script>
	
      <script type="text/javascript">
         function createWidget()
         {
            var widget = new widgets.TextBox();
            widget.label = "Name";
            widget.startup();
         }
      </script>
   </head>

   <body class="tundra ibm" style="padding:5px">
   <br/>
      <!-- declare o widget DOJO -->
      <script type="text/javascript">
         createWidget();
      </script>
   </body>
</html>
            


Mais sobre Widgets do Dojo

Conforme afirmado anteriormente, um widget do Dojo é uma declaração de classe do Dojo herdada de uma classe especial: a classe dijit._Widget . Essa classe define o comportamento básico de um widget e fornece as funções comuns compartilhadas por todas as implementações do widget. As tarefas mais importantes implementadas pela classe _Widget são:

  • Definir o método create , que é chamado automaticamente quando o widget for instanciado; esse método executa todas as etapas de criação necessárias
  • Definir alguns métodos template , que fornecem ganchos especiais para implementadores de widgets, fornecendo a eles a chance de implementar ações de inicialização especiais em uma fase de criação específica
  • Definir diversos métodos destroy , que limpam os recursos alocados do widget
  • Definir métodos event management , que ligam os métodos de widgets a eventos de chamada do nó/método DOM

A Fase de Criação do Widget

O método create executa as seguintes etapas básicas para a inicialização do widget:

Criar um ID exclusivo para o widget, se não fornecido

Todos os widgets do Dojo devem ser identificados por um ID exclusivo. Quando um widget é instanciado, um ID de widget pode ser fornecido. Caso contrário, o Dojo cria um ID com o seguinte formato:

packageName_className_number

Por exemplo, um botão poderia ter o seguinte ID gerado automaticamente: dijit_form_Button_0.

Um packageName é o pacote do widget com o ponto substituído por sublinhados (por exemplo, dijit_form) e number é um número progressivo incrementado com base nos widgets.

Registre o widget no registro do widget global

Widgets podem ser consultados posteriormente usando o método dijit.byId , que retorna o objeto de widget correspondente ao ID fornecido. O registro é um Objeto que vive no espaço global em dijit.registry_hash. Penetrar esse registro usando ferramentas de depuração, como o FireBug (consulte Recursos), poderia ser útil para controlar, por exemplo, fuga de widgets.

Mapeie os atributos

As propriedades do widget podem ser remapeadas para nós definidos pelo usuário do modelo do widget. Os atributos a mapear e seu destino podem ser listados no objeto attributeMap. Cada propriedade desses objetos define um mapeamento da seguinte forma:

  1. O nome da propriedade identifica o nome da propriedade do widget onde o valor a configurar está armazenado.
  2. O valor da propriedade identifica o nome da propriedade do widget onde o nó DOM de destino está armazenado. Se uma cadeia vazia for especificada domNode é usado.

A Lista 9 mostra um exemplo.


Lista 9. Declarando um Widget do Dojo
dojo.declare(
 "MyWidget",
   dijit._Widget,
 {
 // o atributo a mapear (nome e valor)
 title: "myTitle",

 // o nó DOM a ser usado para configurar o
 // atributo title para o valor "myTitle"
 titleNode: null,

 // o mapa do atributo
 // o atributo title é mapeado para titleNode
      attributeMap: {title: "titleNode"},
// a cadeia de modelo
      templateString: "<div><span dojoAttachPoint=\"titleNode\"></span></div>",
            

O modelo do widget resultante será:

<div><span title="myTitle"></span></div>

Observe que como a classe base _Widget já mapeia alguns atributos HTML básicos (como o ID, a classe, o estilo), implementadores não devem substituir a propriedade attributeMap . Em vez disso, devem combinar a propriedade attributeMap da classe base com seus valores. A Lista 10 mostra um exemplo recuperado da classe _FormWidget .


Lista 10. Combinando a Propriedade attributeMap da Classe Base com Valores Customizados
attributeMap:
 dojo.mixin(
 dojo.clone(dijit._Widget.prototype.attributeMap),
 {id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}
),
            

Os Métodos de Modelo

Durante a fase de criação do widget, alguns métodos são chamados para fornecerem aos implementadores uma chance de executar algumas ações em fases de inicialização específicas. Os métodos a seguir são chamados:

  1. postMixInProperties: Esse método é chamado após todos os parâmetros do widget terem sido configurados (combinados) como propriedades da instância do widget. Essa é uma boa hora para executar inicializações de propriedades adicionais, se baseado em propriedades fornecidas pela instanciação.
  2. buildRendering: Esse método é chamado quando estiver na hora de produzir renderização para o widget. Esse gancho é implementado pela classe de combinação dijit._Templated , que estende widgets expostos com modelos HTML. Implementadores podem fornecer, potencialmente, sua implementação para refinar a tarefa da classe _Templated .
  3. postCreate: O método é chamado após o DOM do widget estar pronto e inserido na página. O implementador pode operar na estrutura do DOM do widget neste momento. Os widgets filhos ainda não foram iniciados.
  4. startup: A chance final de operar no widget. Nesse momento, os widgets filhos foram iniciados.
  5. uninitialize: Chamado quando o widget está sendo destruído. O implementador tem uma chance de executar alguma limpeza não-automática.

Os métodos de template podem ser fornecidos pelo implementador, que não deve se esquecer de que a superclasse pode, potencialmente, ter implementado seus métodos de template. Para garantir a inicialização correta para todas as classes da cadeia, o implementador deve codificar manualmente a chamada do método de superclasse, conforme mostrado na Lista 11.


Lista 11. Exemplo de Chamada do Método de Superclasse
startup: function()
{
 // chame o método da superclasse
   this.inherited("startup", arguments);
 // seu código aqui
}
            

Como convenção geral, para todos os métodos de criação (todos os métodos de template, exceto uninitialize), o método de superclasse deve ser chamado como primeiro para assegurar que os itens da superclasse sejam inicializados corretamente antes de trabalhar nos mesmos.

A regra inversa deve ser seguida pelo método uninitialize .

Uma nota final deve ser feita para o método startup . Não se esqueça de que o método de inicialização é chamado automaticamente pelo método dojo.parser.parse , caso o widget esteja sendo criado através de uma declaração. Isso não é feito se o widget for criado de forma programática e deve ser feito manualmente como no exemplo abaixo.

var w = new MyWidget({});
w.startup();
            

A Fase de Destruição do Widget

Após ser criado, os widgets vivem até um pedido explícito de destruição ser executado. Os implementadores são responsáveis por gerenciar todo o ciclo de vida do widget, inclusive a destruição do widget. Caso contrário, isso resultará em uma fuga de widget até que ocorra toda a limpeza da página. O widget fornece quatro métodos de destruição:

  • destroyRendering: Esse método limpa os itens de renderização do widget. A menos que o implementador precise de uma limpeza parcial, geralmente é chamado pelos outros métodos de destruição.
  • destroyDescendants: Destrói todos os widgets filhos. A menos que o implementador precise de uma limpeza parcial, o método é chamado pelo método destroyRecursive .
  • destroy: Destrói os itens do widget (não os widgets filhos).
  • destroyRecursive: Destrói os itens do widget e os widgets filhos. Esse método deve ser chamado se o widget contiver widgets internos.

No caso em que o widget contém widgets internos (por exemplo, há alguns widgets em seu template), o implementador não deve se esquecer de acionar os filhos, destruindo-os de alguma forma sem fazer com que o usuário do widget decida qual método de destruição chamar. A Lista 12 mostra uma maneira possível de fazer isso.


Lista 12. Exemplo de Acionar a Destruição de um Widget
uninitialize: function()
{
 // destrua os descendentes
 this.destroyDescendants();
 // chame o método da superclasse
   this.inherited("uninitialize", arguments);
}
            

Gerenciamento de Eventos

Um widget do Dojo pode reagir a eventos externos que poderiam vir de nós e objetos DOM. Esses eventos podem ser conectados manualmente usando-se o método connect do widget, que tem a seguinte assinatura (que é bem semelhante ao método dojo.connect ):

connect: function(/*Object|null*/ obj, /*String*/ event, /*String|Function*/ method);

Ou podem ser conectados automaticamente declarando-se a conexão no template usando o atributo dojoAttachEvent . Em ambos os casos, a conexão é controlada internamente pelo widget na array _connects. Todas as conexões serão desconectadas automaticamente na hora da destruição. Dessa forma, as referências entre o widget e os nós DOM são interrompidas.

Se, durante o ciclo de vida do widget, algumas conexões não forem mais necessárias, o implementador podem desconectá-las manualmente chamando o método disconnect para reduzir a manipulação de eventos.

Template de Widget

Conforme visto anteriormente, widgets devem ser herdados da classe dijit._Widget , que define e fornece o comportamento básico para um widget do Dojo. Essa classe base define o método buildRendering que é responsável por construir os elementos de renderização do widget. Por exemplo, um implementador de widget pode criar nesse método a marcação do widget e configurá-la no nó DOM do widget. Outra opção poderia ser criar a estrutura do widget usando a API do DOM. Em ambos os casos, o implementador deve programar da mesma forma o método buildRendering .

O Dojo fornece uma poderosa abstração que separa a definição de renderização do widget da implementação de comportamento do widget: a classe de combinação dijit­._Templated . Implementadores que desejam explorar uma abstração como esta precisam herdar da classe _Templated , como na Lista 13.


Lista 13. Código para Herdar da Classe _Templated
dojo.declare(
 "widgets.MyWidget",
   dijit._Widget, dijit._Templated
 {
 templatePath: dojo.moduleUrl("widgets", "templates/MyWidget.html"),
 }
);
            

A classe _Templated fornece sua própria implementação de buildRendering que usa uma definição semelhante a HTML. Essa definição pode, potencialmente, residir em dois locais diferentes.

  1. Um arquivo externo. Neste caso, o arquivo é referido pela propriedade templatePath .
  2. Uma propriedade de cadeia interna. Neste caso, o template é definido diretamente no widget na propriedade templateString . Se o botão templateString for especificado, templatePath é ignorada, mesmo se especificada.

A primeira opção representa a maneira mais limpa de organizar o código de origem do widget, pois a marcação pode ser gravada em um arquivo diferente, pode ser formatada de forma legível sem preocupação com concatenação de cadeia e delimitadores de cadeia não devem ter escape. Por outro lado, a segunda opção tem melhor desempenho, pois um segundo arquivo não precisa ser carregado a partir do navegador. No entanto, você não deve se preocupar com isso, pois o Dojo fornece uma ferramentas de construção que internaliza modelos externos no código de origem do widget.

Um modelo pode ser parametrizado fazendo referência a propriedades do widget. Isso é útil quando o widget expõe alguns parâmetros de configuração que afetam diretamente a marcação ou se a marcação precisar ser produzida condicionalmente dependendo das preferências externas. As propriedades do widget são referidas usando-se a sintaxe a seguir: ${propertyName}.

Os modelos podem conter outras declarações de widget. No entanto, para que sejam consideradas, o desenvolvedor do widget deve configurar a propriedade widgetsInTemplate para true, que por padrão está configurada para false, para ignorar um processamento que pode não ser necessário.

Os modelos podem conter as duas declarações de atributos especiais a seguir:

  • dojoAttachPoint: Esse atributo de tag, se especificado, deve ser configurado para um nome de propriedade do widget. O DOM correspondente à tag será configurado para a propriedade do widget. Diversas tags do template podem ter um ou mais pontos de conexão.
  • dojoAttachEvent: Esse atributo de tag lista métodos de widget que devem ser chamados de volta quando um evento DOM for acionado.

A Lista 14 mostra um exemplo de template.


Lista 14. Exemplo de Template de Declarações de Atributos Especiais
<span
 class="textInputDefault"
 dojoAttachEvent="onclick:_onClick">
 <img
 class="textInputIcon"
 src="${constants.DEFAULT_ICON}"
 dojoAttachPoint="_iconNode"/>
 <input
 class="textInputNode"
 size="${size}"
 type="${type}"
 value=""
 dojoAttachPoint="_inputNode, _focusNode"
 dojoAttachEvent="onkeyup:_onKeyUp, onkeypress:_onKeyPress, onchange:_onChange"
 />
 <span
 class="textInputRight">&nbsp;
 </span>
</span>
            


Tivoli Dynamic Workload Console e Dojo

O Tivoli Dynamic Workload Console (TDWC) é a interface gráfica com o usuário do Tivoli Workload Scheduler (TWS). Esta seção mostra como o TDWC v.8.5 tira proveito da capacidade do Dojo.

Introdução ao Tivoli Workload Scheduler

O TWS é uma solução de automação de produção projetada para ajudar a gerenciar cargas de trabalho em ambientes operacionais complexos dos dias de hoje. Os principais elementos de planejamento são tarefas e fluxos de tarefas. Uma tarefa é a representação de uma tarefa, como um arquivo executável, um programa ou um comando. Um fluxo de tarefas representa um contêiner para tarefas relacionadas e organiza as mesmas em termos de tempo de execução, sequência, limitações de simultaneidade e repetições. O TWS ajuda a planejar tarefas para execução, resolve interdependências, ativa e controla cada tarefa. Isso se deve às tarefas serem iniciadas assim que suas dependências forem atendidas; portanto, o tempo inativo é minimizado e o rendimento melhora de forma significativa. As tarefas nunca são executadas fora de sequência e, se uma tarefa falhar, o TWS trata do processo de recuperação com pouca ou nenhuma intervenção do operador.

Usando o Dojo

O TDWC v.8.5 inclui um editor de carga de trabalho completo gravado inteiramente em JavaScript usando o kit de ferramentas Dojo. Esse tipo de implementação permitiu colocar "inteligência" e comportamento mais próximos do usuário, usando código que é executado o máximo possível dentro do navegador.

Dê uma olhada em um exemplo de um painel de propriedades de um fluxo de tarefas do RWS exibido pelo TDWC. A Figura 3 representa o painel da Web das propriedades gerais definidas para o fluxo de tarefas PAYROLL.


Figura 3. Painel da Web para o Fluxo de Tarefas PAYROLL
Captura de tela do fluxo de tarefas para PAYROLL mostrando o nome PAYROLL e a estação de trabalho como LAB132079_DM1_85.  Válido  do campo de data está sendo editado, com um calendário popout.  O Válido Para e campos de comentários estão em branco.

Em um artigo anterior ("O Kit de Ferramentas da Web da Abstract User Interface Markup Language: Um Rederizador de AUIML para JavaScript e Dojo", consulte Recursos), descrevemos como projetar o painel usando o kit de ferramentas AUIML e como implementar o código lógico em JavaScript usando o AUIML Web Toolkit (AWT). A Figura 4 representa o painel AUIML:


Figura 4. Painel AUIML
 Uma captura de tela do painel AUIML mostrando os campos de entrada em branco Nome, Estação de Trabalho, Válido de, Válido para, Descrição, Tabela de Variável, Monitorado, Rascunhos e Comentários

Vamos focar o campo Válido desde . Foi definido como Caixa de Edição, Data no editor de AUIML; o AWT acopla esse elemento ao código HTML mostrado na Lista 15.


Lista 15. Código HTML para Acoplar o Elemento
<span type='text' dojoType='ajaxcommon.widgets.DateInputBox' id='validFrom'>
<script type='dojo/method'event='onValueChanged'>AWT.dispatchOnChange(this.id);</script>
</span>
            

O widget ajaxcommon.widgets.DateInputBox é definido na Lista 16:


Lista 16. Código para definir ajaxcommon.widgets.DateInputBox
dojo.provide("ajaxcommon.widgets.DateInputBox");

dojo.require("ajaxcommon.resources.Images");
dojo.require("ajaxcommon.widgets._DateTimePicker");
dojo.require("ajaxcommon.widgets.picker.PickerInputBox");
dojo.require("ajaxcommon.widgets.picker.DatePicker");
dojo.declare(
   "ajaxcommon.widgets.DateInputBox",
     [ajaxcommon.widgets.picker.PickerInputBox,
      ajaxcommon.widgets._DateTimePicker],
     {
      /** o ícone do selecionador */
      pickerIcon: ajaxcommon.resources.Images.get()["CALENDAR_ICON"],
      /** o ícone desativado do selecionador */
      pickerDisabledIcon: ajaxcommon.resources.Images.get()["DISABLED_CALENDAR_ICON"],
      /** o título do ícone do selecionador */
      pickerIconTitle: ajaxcommon.resources.Labels.get()["PICK_DATE"],
      /** limitadores */
      constraints: {selector: "date", formatLength: "short", wideYear: true},

      /**
       * Construtor.
       */
      constructor: function()
      {
         // mesmo se o comprimento do formato for curto, assegure o ano amplo (yyyy)
         // substituindo o datePattern
         if (this.constraints.formatLength === "short" && this.constraints.wideYear) {
            this.constraints.datePattern = this._getWideDatePattern();
         }
         // configure o regex para o texto
         this.textRegExp = "^(" + dojo.date.locale.regexp(this.constraints) + "){0,1}$";
         // configure a mensagem do para o texto
         this.textRegExpMessage =
            this._labels.format("DATE_INVALID_VALUE", {example: this._getExampleValue()});
         // configure a classe do selecionador
         this.pickerClass = "ajaxcommon.widgets.picker.DatePicker";
      },

      /**
       * Retorna o padrão de data com o ano amplo (yyyy)
       */
      _getWideDatePattern: function()
      {
         // obtenha o pacote configurável
         var bundle = dojo.date.locale._getGregorianBundle();
         // obtenha o padrão
           var pattern = bundle["dateFormat-short"];
           // substitua yy por yyyy se ainda não for yyyy
           if ( pattern.search(/yyyy/gi) === -1 ) {
              // o ano não está no formato amplo
              pattern = pattern.replace(/yy/gi, "yyyy");
           }
           return pattern;
      },
     /**
       * Retorna uma cadeia contendo um exemplo de valor aceito. 
       */
      _getExampleValue: function()
      {
         // obtenha um objeto de data de amostra (meu aniversário!!!)
         var d = new Date();
         d.setDate(15);
         d.setMonth(4);
         d.setYear(1971);
         // formate a data no código do idioma local e retorne
         return dojo.date.locale.format(d, this.constraints);
      }
   }
);
         

O construtor permite a inicialização das propriedades do widget declaradas no widget de superclasse ajaxcommon.widgets.picker.PickerInputBox definido na Lista 17.

A Lista 18 mostra o template relacionado do widget.


Lista 18. Template de Widget para ajaxcommon.widgets.picker.PickerInputbox
<span
    class="picker"
    ><span
        tabindex="${tabindex}"
        dojoType="${_textBoxWidget}"
        dojoAttachPoint="_textNode,_focusNode"
        required="${required}"
        size="${size}"
        minLength="${textMinLength}"
        maxLength="${textMaxLength}"
        regExp="${textRegExp}"
        regExpReference="${textRegExpReference}"
        regExpMessage="${textRegExpMessage}"
        minWidth="${minWidth}"
    ></span
    ><span
        dojoAttachPoint="_pickerButtonContainer">
        <img
            tabindex="${tabindex}"
            src="${pickerIcon}"
            dojoAttachPoint="_pickerButtonNode"
            dojoAttachEvent="onclick:_onClick,onkeyup:_onKeyUp"
            class="pickerButton"
            title="${pickerIconTitle}"
    /></span>
</span>
            

A Figura 5 mostra a vantagem de delegar a lógica do widget para o lado do navegador. O widget foi implementado para exibir a mensagem de erro relacionada e para alterar a aparência e sensação caso qualquer erro ocorra ao configurar seu valor.


Figura 5. Painel Mostrando Lógica de Widget do Lado do Navegador
Uma repetição da captura de tela da Figura 3, agora mostrando o conjunto de campos Válido De para 15 de maio de 1971

Conclusão

Este artigo descreveu conceitos básicos para desenvolver widgets de HTML usando o kit de ferramentas Dojo JavaScript, a partir da versão 1.0 e iniciando com widgets simples e chegando aos mais complexos (como os widgets implementados no TDWC v.8.5). O artigo também ressaltou os pontos fortes do kit de ferramentas Dojo.

Em um próximo artigo, vamos revisar armadilhas comuns do desempenho encontradas durante o desenvolvimento de aplicativos ricos da Internet e mostraremos como abordá-las usando as boas práticas desenvolvidas, baseadas principalmente no kit de ferramentas Dojo.


Recursos

Sobre os autores

Photo of Marco Lerro

Marco é um engenheiro da equipe do Laboratório Tivoli da IBM Roma desde 1999. Atualmente está envolvido no design e desenvolvimento do TDWC. Sua área de interesse atual é desenvolvimento em Web 2.0, com ênfase especial em tecnologias baseadas em Dojo e padrões de design baseados em experiência de usuário.

Roberto Longobardi

Roberto trabalha na área de desenvolvimento de software há doze anos, cobrindo diversas funções, desde desenvolvedor, analista, designer de interface da Web até designer de interação. Trabalha atualmente na organização Tivoli como um designer de interface com o usuário da Web para os produtos Tivoli Workload Scheduler e Dynamic Workload Broker. Dessa forma, também está frequentemente envolvido nas atividades diretas com o cliente, como reunir requisitos, validar o design e ativar as vendas. Roberto publicou diversos artigos no developerWorks, apresentados em conferências de IEEE, e está envolvido em diversas colaborações acadêmicas.

Gianluca Perreca's photo

Gianluca Perreca é um engenheiro da equipe do Laboratório Tivoli da IBM Roma. É membro da equipe de desenvolvimento do Tivoli Workload Scheduler e está envolvido ativamente no design e implementação do IBM Tivoli Dynamic Workload Console, a interface da Web para o IBM Tivoli Workload Scheduler.

Photo of Alessandro Scotti

Alessandro Scotti é o designer chefe do IBM Tivoli Dynamic Workload Console, uma interface da Web para o IBM Tivoli Workload Scheduler que usa o AUIML Toolkit, assim como AUIML e outras tecnologias Web 2.0. Alessandro foi autor ou contribuiu para diversos projetos de software livre, principalmente nas áreas de interface gráfica com o usuário, alto desempenho e programação em tempo real.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

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.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=394408
ArticleTitle=Desenvolvendo Widgets com o Dojo 1.x
publish-date=04282009
author1-email=marco.lerro@it.ibm.com
author1-email-cc=
author2-email=roberto.longobardi@it.ibm.com
author2-email-cc=clarkega@us.ibm.com
author3-email=gianluca.perreca@it.ibm.com
author3-email-cc=
author4-email=alessandro.scotti@it.ibm.com
author4-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).