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 iniciar, primeiro, será necessário configurar o ambiente de desenvolvimento. Para fazer isso:
- 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.)
- 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
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.
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>
|
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.
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._Widgetedijit._Templatedsão superclasses para o widget TextBox -
templatePath,inputNodeelabelsão atributos do widget -
onKeyUp()evalidate()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
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>
|
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
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:
- O nome da propriedade identifica o nome da propriedade do widget onde o valor a configurar está armazenado.
- 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"}
),
|
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:
-
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. -
buildRendering: Esse método é chamado quando estiver na hora de produzir renderização para o widget. Esse gancho é implementado pela classe de combinaçãodijit._Templated, que estende widgets expostos com modelos HTML. Implementadores podem fornecer, potencialmente, sua implementação para refinar a tarefa da classe_Templated. -
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. -
startup: A chance final de operar no widget. Nesse momento, os widgets filhos foram iniciados. -
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étododestroyRecursive. -
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);
}
|
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.
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.
- Um arquivo externo. Neste caso, o arquivo é referido pela propriedade templatePath .
- Uma propriedade de cadeia interna. Neste caso, o template é definido diretamente no widget na propriedade
templateString. Se o botãotemplateStringfor 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">
</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.
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
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
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
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.
- Verifique blogs do developerWorks
e envolva-se com a comunidade do developerWorks.
- 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).
- Faça download do
FireBug em Web site do projeto
.

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 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 é 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 é 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.