|
Conteúdo
Para seguir este tutorial, você precisa dos seguintes recursos e softwares.
| NetBeans IDE |
Web e Java EE versão 6.1 ou 6.0 |
| Java Development Kit (JDK) |
Versão 6 ou
versão 5 |
Componentes do JavaServer Faces/
Plataforma Java EE |
1.1 com J2EE 1.4
|
| Servidor da aplicação GlassFish |
V2 |
| Banco de dados Viagem |
Não é necessário |
Requisitos do tutorial
Antes de começar, você deve instalar o seguinte software no seu computador:
- NetBeans IDE 6.0 ou 6.1 com a funcionalidade Web e Java EE (incluída no download Web e Java EE e no download completo). (download)
- Plug-in de amostras do Visual Web. Este plug-in inclui a biblioteca do componente Dynamic Faces (0.2). Siga as instruções na seção chamada "Instalando o plug-in" em Instalando o Plug-in de amostras do Visual Web. Garanta a seleção das entradas das amostras da versão de postagem do Visual Web JSF e do kit de compatibilidade com versões anteriores do Visual Web JSF.
Criando o projeto
- No menu principal, escolha Arquivo > Novo arquivo.
- No assistente para Novo projeto, selecione Web na lista Categorias, selecione Aplicação Web na lista Projetos e clique em Próximo.
- Chame o projeto de AjaxChatRoom e escolha uma localização do projeto.
Selecione Servidor da aplicação Sun Java System para o servidor, J2EE 1.4 para a versão Java EE, e garanta que as caixas de verificação para Definir nível do código-fonte para 1.4 e Definir como projeto principal são selecionados. Em seguida clique em Próximo.
- Selecione JavaServer Faces Visual Web e clique em Terminar.
Configurando o descritor de deployment
A tecnologia Dynamic Faces requer um parâmetro de inicialização no descritor de deployment da aplicação Web.
- Na janela Projetos, expanda o nó Páginas da Web > WEB-INF.
- Clique duas vezes para abri-lo no editor web.xml.
Na barra de ferramentas Editor, clique em Servlets e no botão Adicionar que aparece sob Parâmetros de inicialização na figura seguinte.
Na caixa de diálogo Adicionar parâmetro de inicialização, digite javax.faces.LIFECYCLE_ID na caixa de texto Nome do parâmetro, digite com.sun.faces.lifecycle.PARTIAL na caixa de texto Valor do parâmetro e clique em OK.
O novo parâmetro aparece no editor.
- Clique em XML na barra de ferramentas de edição e procure por
lifecycle para ver as alterações no XML puro.
- Clique em Ctrl-S para salvar suas alterações no arquivo web.xml e feche a aba do arquivo para fechar o arquivo.
Adicionando a biblioteca do componente Dynamic Faces ao projeto
Na janela Projetos, clique com o botão direito do mouse no nó Bibliotecas do componente e escolha Adicionar biblioteca do componente, como mostrado abaixo.
Na caixa de diálogo Adicionar biblioteca de componentes, selecione Componentes Dynamic Faces (0.2), e clique em Adicionar biblioteca do componente para fechar a caixa de diálogo.
Uma nova seção Dynamic Faces aparece na janela Paleta.
Adicionando o código ao bean de aplicativo
- Na janela Projetos, expanda o nó Pacotes de códigos-fonte > ajaxchatroom do projeto e clique duas vezes em ApplicationBean1.java para abrir o arquivo no editor de código-fonte.
Role para baixo de ApplicationBean1.java e adicione o código seguinte antes do colchete de fechamento final.
| Amostra de código 1: Código do bean de aplicativo para armazenar comentários e nomes de usuário anônimos |
private int nextAnonIndex;
private final int MAX_ENTRIES = 100;
//list of String arrays, with each array of length 2
private List entryList = new LinkedList();
//array containing same contents as entryList
private String[][] entries;
public String[][] getEntries() {
synchronized(this.entryList) {
return this.entries;
}
}
public void addEntry(String username, String comment) {
if (comment == null || comment.length() < 1) {
return;
}
if (username == null) {
username = "anonymous";
}
synchronized(this.entryList) {
if (this.entryList.size() == MAX_ENTRIES) {
this.entryList.remove(0);
}
String[] entry = new String[]{username, comment};
this.entryList.add(entry);
this.entries =
(String[][])this.entryList.toArray(
new String[this.entryList.size()][entry.length]);
}
}
public synchronized String getNextAnonUsername() {
nextAnonIndex++;
return "anonymous" + nextAnonIndex;
} |
Neste código, você armazena cada comentário e seu nome de usuário associado como uma transcrição entry, ou seja, um objeto String[] de tamanho 2. Você armazena as entradas na variável entryList e na variável entries. Ao adicionar um comentário através do método addEntry ou obtendo as entradas de transcrição através do método getEntries, o código do cliente deve obter o monitor (ou seja, sincronizar) em this.entryList, necessariamente impactando o desempenho mas preservando a integridade dos dados. Você mantém um número máximo de entradas na transcrição, como determinado por MAX_ENTRIES.
Os usuários serão capazes de acessar o aplicativo através de uma URL no formato http://server-ip-address:8080/AjaxChatRoom?username=someuser. O nome de usuário especificado aparecerá junto com quaisquer comentários enviados pelo usuário. Se um usuário acessar o aplicativo através de uma URL que não especifique um nome de usuário, aparecerá um nome de usuário anônimo junto com os comentários do usuário. Nesse caso, uma chamada do método getNextAnonUsername irá gerar um nome de usuário anônimo que é único no aplicativo.
Clique com o botão direito do mouse no código-fonte e escolha Corrigir importações.
Como há mais de uma opção para a classe Lista, a caixa de diálogo Corrigir importações aparece.
- Clique em OK para aceitar java.util.List como o nome totalmente qualificado de Lista.
- Feche e salve o arquivo.
Adicionando o código para armazenar o nome do usuário
- Na janela Projetos, clique duas vezes em Pacotes de códigos-fonte > ajaxchatroom > SessionBean1.java para abrir o arquivo no editor de código-fonte.
Role para baixo de SessionBean1.java e adicione o código seguinte antes do colchete de fechamento final.
| Amostra de código 2: Código do bean de sessão para armazenar o nome de usuário |
private String username;
public synchronized String getUsername() {
return username;
}
public synchronized void setUsername(String username) {
this.username = username;
} |
Como você verá na Amostra de código 5, quando o usuário envia um comentário, um método de ação recupera o nome do usuário do escopo da sessão para registrar junto com o comentário. Já que vários threads associados à mesma sessão devem acessar os métodos getter e setter, os métodos são sincronizados.
- Feche e salve o arquivo.
- Na janela Projetos, clique duas vezes em Pacotes de códigos-fonte > ajaxchatroom > Page1.java e abra o código-fonte Java da página.
Na janela Navegador, clique duas vezes em prerender() para navegar para esse método no editor de código-fonte.
Adicione o seguinte código mostrado em negrito ao método prerender:
| Amostra de código 3: Código de Page1 para armazenar o nome de usuário |
public void prerender() {
String username = (String)getExternalContext().getRequestParameterMap().get("username");
if (username != null) {
getSessionBean1().setUsername(username);
}
else if (getSessionBean1().getUsername() == null) {
getSessionBean1().setUsername(getApplicationBean1().getNextAnonUsername());
}
} |
Se a página for inicialmente renderizada durante a solicitação atual e o usuário especificou um nome de usuário na URL, o mapa do parâmetro de solicitação conterá esse nome de usuário. Nesse caso, você armazena o nome de usuário no bean de sessão. Se o mapa do parâmetro de solicitação não contém um nome de usuário, existem duas possibilidades: a página está sendo renderizada inicialmente e o usuário não especificou um nome de usuário na URL ou, alternativamente, a solicitação atual é do Ajax. No caso anterior, se não tiver armazenado anteriormente um nome de usuário no bean de sessão, você gera e armazena um nome de usuário anônimo. No caso de uma solicitação do Ajax, você já terá armazenado um nome de usuário no bean de sessão quando a página foi inicialmente renderizada.
Adicionando a propriedade transcript ao Page1.java
Role para baixo de SessionBean1.java e adicione o código seguinte antes do colchete de fechamento final.
Amostra de código 4: código da propriedade transcript |
public String getTranscript() {
String[][] entries =
getApplicationBean1().getEntries();
if (entries == null) {
return null;
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < entries.length; i++) {
String entryUsername = entries[i][0];
String comment = entries[i][1];
String color = "purple";
String username = getSessionBean1().getUsername();
if (username.equals(entryUsername)) {
color = "blue";
}
sb.append(
"<div><span style=\"font-weight:bold;color:");
sb.append(color);
sb.append("\">[");
sb.append(entryUsername);
sb.append("]</span> ");
sb.append(comment);
sb.append("</div>");
}
return sb.toString();
} |
Esse método fornece o conteúdo da transcrição como um objeto String, formatando o nome de usuário de uma entrada em azul, se ele for o mesmo nome de usuário armazenado em SessionBean1, caso contrário, em roxo. Isso tem o efeito de exibir as próprias entradas do usuário em azul, enquanto exibe as entradas dos outros participantes da sala de bate-papo em roxo.
- (Opcional) Clique com o botão direito do mouse e escolha Formatar código e clique no botão Salvar tudo na barra de ferramentas principal para salvar suas alterações.
Criando a interface de usuário
- Retorne ao Visual Designer da Page1.
- Arraste um Painel de layout da seção Layout da paleta.
No Visual Designer, selecione o componente Painel de layout e arraste a caixa de dimensionamento inferior direita para baixo e para a direita até que o componente tenha aproximadamente 14 quadrados de largura e 10 quadrados de altura.
- Na janela Propriedades, altere a propriedade
id do componente Painel de layout para comment.
Clique no botão de reticências (...) da propriedade style, anexe as seguintes regras ao estilo CSS e clique em OK.
; overflow: auto; border: 2px solid black;
Definir a propriedade de estilo overflow como auto faz com que a transcrição da sala de bate-papo exiba uma barra de rolagem, se necessário. Observe que a propriedade panelLayout do Painel de layout transcriptPanel está definida como flow, que é o padrão. Nas etapas 6 a 10 abaixo, adicionamos um componente Texto estático como um filho do Painel de layout transcriptPanel e vinculamos a propriedade text do Texto estático à propriedade transcript de Page1.
- Arraste um componente Texto estático da seção Básico da Paleta para o Painel de layout transcriptPanel. Verifique se o contorno do transcriptPanel está realçado em azul antes de liberar o botão do mouse, de forma que o componente transcriptPanel contenha o componente Texto estático.
Na janela Propriedades, altere a propriedade id do componente Texto estático para transcriptText, e limpe a caixa de verificação de escape para definir essa propriedade como false.
Definir a propriedade escape como false faz com que o navegador avalia quaisquer marcas incorporadas no texto. Isso garante que as entradas da transcrição apareçam com a formatação desejada, tal como cor de texto azul ou roxo.
- No Visual Designer, clique com o botão direito do mouse no componente Texto estático transcriptText e selecione Vincular aos dados.
- Na caixa de diálogo Vincular aos dados, clique na aba Vincular a um objeto.
Selecione Page1 > transcrição, e clique em OK.
- Arraste um componente Campo de texto da seção Básico da Paleta e solte-o abaixo do componente transcriptPanel.
- Na janela Propriedades, altere a propriedade
id do componente Campo de texto para comment.
- Altere a propriedade
columns do Campo de texto de comentário para60.
- Arraste e solte um componente Botão da seção Básico da Paleta para a direita do Campo de texto de comentário, digite
Enviar, e pressione Enter.
Clique no botão de reticências (...) da propriedade style, anexe as seguintes regras ao estilo CSS e clique em OK.
; width:70px
Na janela Propriedades, altere a propriedade id do componente Botão para comment.
A Page1 deve ser semelhante à figura seguinte.
No Visual Designer, clique duas vezes no componente Botão.
O IDE cria um método de ação para o botão Enviar e exibe o método no editor de código-fonte.
Adicione o seguinte código mostrado em negrito ao método.
| Amostra de código 5: manipulador de ação Botão |
public String send_action() {
String comment = (String)getComment().getText();
String username = getSessionBean1().getUsername();
getApplicationBean1().addEntry(username, comment);
return null;
} |
Esse código recupera qualquer texto que o usuário tenha indicado no Campo de texto de comentário e fornece esse texto para o método addEntry, adicionando efetivamente o comentário do usuário para a transcrição da sala de bate-papo.
O componente Transação do Ajax incluído com a biblioteca do componente Dynamic Faces (0.2) permite que você configure visualmente a funcionalidade do Ajax no tempo de design, exibindo vários componentes com as bordas codificadas por cor no Visual Designer. No mínimo, você especifica os componentes que enviam entrada para o servidor quando a Transação do Ajax é acionada, assim como os componentes que se renderizam novamente quando o cliente recebe a resposta do Ajax. Os componentes que enviam entrada para o servidor são exibidos com uma borda sólida no Visual Designer; os componentes que se renderizam novamente são exibidos com uma borda pontilhada. Além disso, você deve codificar uma linha de JavaScript para acionar a Transação do Ajax.
Nesta seção, você configura duas Transações do Ajax, uma para enviar comentários e outra para fazer polling do servidor. A Transação do Ajax commentTx é acionada em resposta quando o usuário clica no botão Enviar ou pressiona a tecla Enter. Quando commentTx é acionado, o Campo de texto de comentário e o botão Enviar enviam sua entrada para o servidor por meio de uma solicitação do Ajax, e o Texto estático transcriptText se renderiza novamente quando o cliente recebe a resposta do Ajax. A Transação do Ajax pollTx é acionada inicialmente quando a página é carregada. Conseqüentemente, quando o cliente recebe uma resposta do Ajax associada à Transação do Ajax pollTx, pollTx é acionado novamente depois de um breve atraso. Dessa forma, você consulta o servidor continuamente. Quando pollTx é acionado, nenhum componente envia entrada por meio da solicitação do Ajax (já que você está meramente buscando, e não modificando, os dados da transcrição), e o Texto estático transcriptText se renderiza novamente quando o cliente recebe a resposta do Ajax. Como resultado, a transcrição dos comentários é atualizada continuamente no navegador.
- Retorne ao Visual Designer da Page1.
Na barra de ferramentas do Visual Designer, clique no botão Mostrar formulários virtuais .
O componente Transação do Ajax fornece funcionalidade do Ajax semelhante à fornecida por formulários virtuais para envios convencionais. Clicar no botão Mostrar formulários virtuais mostra os formulários virtuais e as Transações do Ajax configuradas para a página.
Expanda a seção Dynamic Faces na Paleta e arraste um componente Transação do Ajax da seção Dynamic Faces para o Visual Designer.
Na parte inferior do Visual Designer, aparece uma legenda da Transação do Ajax e mostra a Transação do Ajax ajaxTransaction1 associada à cor azul.
No Visual Designer, selecione o Campo de texto de comentário e o botão Enviar. Em seguida, clique com o botão direito do mouse e selecione Configurar transações do Ajax.
A caixa de diálogo Configurar transação do Ajax aparece. Na parte superior da caixa de diálogo, send e comment aparecem, indicando que você está configurando as Transações do Ajax do botão Enviar e o Campo de texto de comentário.
- Na caixa de diálogo Configurar transações do Ajax, clique duas vezes no campo Nome, digite
commentTx para renomear a Transação do Ajax e pressione Enter.
Defina o campo Enviar entrada como Sim, e clique em OK para fechar a caixa de diálogo.
O Campo de texto de comentário e o botão Enviar com uma borda azul sólida no Visual Designer, indicando que esses componentes enviam sua entrada para o servidor através de uma solicitação do Ajax quando a Transação do Ajax commentTx é acionada. O botão Enviar deve enviar sua entrada para o servidor a fim de informar ao servidor que o Botão foi clicado. Na seção Adicionando JavaScript abaixo, você adicionará uma linha de código JavaScript que aciona a Transação do Ajax commentTx em resposta quando o usuário clica no botão Enviar ou pressiona a tecla Enter.
Selecione o Texto estático transcriptText no designer. Clique com o botão direito do mouse e selecione Configurar transações do Ajax.
A caixa de diálogo Configurar transação do Ajax aparece. Na parte superior da caixa de diálogo, transcriptText aparece, indicando que você está configurando as Transações do Ajax para o Texto estático transcriptText.
- Na caixa de diálogo Configurar transações do Ajax, clique em Novo para configurar uma nova Transação do Ajax.
- Selecione vermelho como a cor associada à nova Transação do Ajax.
- Clique duas vezes no campo Nome da nova Transação do Ajax, digite
pollTx, e pressione Enter.
Defina o campo Renderizar novamente das Transações do Ajax commentTx e pollTx como Sim, e clique em OK para fechar a caixa de diálogo.
O Texto estático transcriptText aparece com uma borda pontilhada azul e uma borda pontilhada vermelha, indicando que o componente se renderiza novamente sempre que o cliente recebe uma resposta do Ajax associada às Transações do Ajax commentTx ou pollTx. Na seção Adicionando JavaScript abaixo, você adicionará a lógica de JavaScript que consulta o servidor, acionando a Transação do Ajax pollTx.
- Na janela Navegador, expanda o nó Page1 > page1 > html1 > head1 e selecione a Transação do Ajax commentTx.
Na janela Propriedades, defina a propriedade postReplace do componente Transação do Ajax commentTx como customPostReplaceForCommentTx.
Aqui você especifica que o cliente deve chamar a função JavaScript customPostReplaceForCommentTx depois de receber uma resposta do Ajax associada com a Transação do Ajax commentTx e rendereizando novamente os componentes apropriados (ou seja, apenas o Texto estático transcriptText). Você verá essa função JavaScript na seção Adding JavaScript abaixo.
- Na janela Navegador, abaixo do nó Page1 > page1 > html1 > head1, selecione a Transação do Ajax pollTx.
Na janela Propriedades, defina as propriedades inputs e execute do componente Transação do Ajax pollTx como none.
Essa etapa configura explicitamente a Transação do Ajax pollTx de forma que quando a Transação do Ajax é acionada, nenhum componente envia sua entrada na solicitação do Ajax ou é processado no servidor.
Defina a propriedade postReplace da Transação do Ajax pollTx como customPostReplaceForPollTx e a propriedade replaceElement como customReplaceForPollTx.
Aqui você especifica que a função JavaScript customReplaceForPollTx implementa a lógica de nova renderização quando o cliente recebe uma resposta do Ajax associada à Transação do Ajax pollTx. Você também especifica que o cliente deve chamar a função JavaScript customPostReplaceForPollTx depois de renderizar novamente os componentes apropriados (ou seja, apenas o Texto estático transcriptText). Você verá essas funções de JavaScript na seção Adicionando JavaScript abaixo.
Definindo as propriedades de JavaScript dos componentes Corpo e Formulário
- Na janela Navegador, abaixo do nó Page1 > page1 > html1, selecione o componente Corpo body1.
Na janela Propriedades, defina a propriedade onLoad do componente Corpo body1 como handleOnLoad() e a propriedade onUnload como handleOnUnload().
Você verá essas funções de JavaScript na seção Adicionando JavaScript abaixo.
- Na janela Navegador, abaixo do nó Page1 > page1 > html1 > body1, selecione o componente Formulário form1.
Na janela Propriedades, defina a propriedade onSubmit do componente Formulário form1 como return interceptFormSubmit().
Você verá a função JavaScript interceptFormSubmit na seção Adicionando JavaScript abaixo. Quando o usuário clica no botão Enviar ou pressiona a tecla Enter, essa função JavaScript impede o envio convencional do formulário e, em vez disso, aciona a Transação do Ajax commentTx.
Adicionando JavaScript
Agora você cria o arquivo JavaScript ajaxchatroom.js.
Na janela Projeto, expanda o nó Páginas da Web, clique com o botão direito do mouse na pasta de recursos, e selecione Novo > Outro.
- No assistente para Novo arquivo, selecione Outro na lista Categorias e Arquivo vazio na lista Projetos e clique em Próximo.
- Chame o arquivo de
ajaxchatroom.js e clique em Terminar.
Adicione o código JavaScript seguinte ao arquivo:
Amostra de código 6: ajaxchatroom.js |
var pollDelay = 1000;
var continuePolling = false;
var mouseDownOnTranscript = false; //whether the user has performed a mousedown on the transcript (including any scrollbar)
//and not yet performed a mouseup
function customPostReplaceForCommentTx(element, markup) {
//scroll to the bottom of the transcript
var transcriptPanel = document.getElementById('form1:transcriptPanel');
transcriptPanel.scrollTop = transcriptPanel.scrollHeight;
//clear the text field
var commentTextField = document.getElementById('form1:comment');
commentTextField.value = '';
//place focus in the text field
commentTextField.focus();
}
function handleOnLoad() {
//handle mousedown on the transcript
var transcriptPanel = document.getElementById('form1:transcriptPanel');
transcriptPanel.onmousedown = handleMouseDown;
//handle mouseup anywhere on the page
document.onmouseup = handleMouseUp;
//turn autocomplete off for the text field
document.getElementById('form1:comment').setAttribute('autocomplete','off');
//start polling
continuePolling = true;
poll();
}
function handleOnUnload() {
//stop polling
continuePolling = false;
}
function poll() {
//fire the pollTx Ajax Transaction
DynaFaces.Tx.fire('pollTx');
}
function customReplaceForPollTx(element, markup) {
//provided that the user is not performing an operation such as selecting transcript text or scrolling the transcript,
//perform replacement (re-rendering) for this poll request,
//and scroll the transcript as appropriate after the replacement
if (!mouseDownOnTranscript) {
var transcriptPanel = document.getElementById('form1:transcriptPanel');
//scrollTop: distance between top of transcript and top of the portion currently visible
//scrollHeight: total height of transcript, including any portion not visible due to scrolling
//clientHeight: height of the visible portion of the transcript
//capture whether scrollbar exists before replacement.
//scrollbar exists if the scrollHeight exceeds the clientHeight
var scrollbarExistsBeforeReplacement = transcriptPanel.scrollHeight > transcriptPanel.clientHeight;
//capture whether the transcript is scrolled to the bottom before replacement
var scrolledToBottomBeforeReplacement = false;
if (scrollbarExistsBeforeReplacement) {
//transcript is scrolled to the bottom if the sum of scrollTop and clientHeight equals scrollHeight
if (transcriptPanel.scrollTop + transcriptPanel.clientHeight == transcriptPanel.scrollHeight) {
scrolledToBottomBeforeReplacement = true;
}
}
//capture the scrollTop before replacement
var scrollTopBeforeReplacement = transcriptPanel.scrollTop;
//invoke default replacement function to perform actual replacement of transcript content
DynaFaces.replace(element, markup);
//capture whether scrollbar exists after replacement
var scrollbarExistsAfterReplacement = transcriptPanel.scrollHeight > transcriptPanel.clientHeight;
//scroll to the bottom of the transcript if it was scrolled to the bottom before replacement
//or if the scrollbar did not exist before replacement and it now exists after replacement.
//otherwise, scroll the transcript to the same place it was before replacement
if (scrolledToBottomBeforeReplacement || (!scrollbarExistsBeforeReplacement && scrollbarExistsAfterReplacement)) {
transcriptPanel.scrollTop = transcriptPanel.scrollHeight; //scroll to the bottom of the transcript
}
else {
transcriptPanel.scrollTop = scrollTopBeforeReplacement; //scroll transcript to the place it was before replacement
}
}
}
function handleMouseDown() {
//if the mousedown occurs on the transcript's scrollbar,
//IE will not invoke the corresponding mouseup event handler when the mouse is released.
//in such a case, do not set mouseDownOnTranscript to true, since nothing will set it back to false.
//instead, just perform replacement in customReplaceForPollTx even though the user is scrolling the transcript,
//as this does not seem to cause a problem on IE anyway
if (document.all) {
var transcriptPanel = document.getElementById('form1:transcriptPanel');
var scrollBarExists = transcriptPanel.scrollHeight > transcriptPanel.clientHeight;
if (scrollBarExists) {
if (window.event.offsetX > transcriptPanel.clientWidth) {
//mousedown occurred on the scrollbar
return;
}
}
}
mouseDownOnTranscript = true;
}
function handleMouseUp() {
mouseDownOnTranscript = false;
}
function customPostReplaceForPollTx(element, markup) {
//send the next poll request
if (continuePolling) {
setTimeout(poll, pollDelay);
}
}
function interceptFormSubmit() {
//if the text field is not blank, fire commentTx
if (document.getElementById('form1:comment').value != '') {
DynaFaces.Tx.fire('commentTx');
}
//prevent conventional form submission
return false;
} |
Como você define a propriedade postReplace da Transação do Ajax commentTx como customPostReplaceForCommentTx, o cliente chama a função customPostReplaceForCommentTx depois de receber uma resposta do Ajax associada a commentTx e renderiza novamente os componentes apropriados (ou seja, apenas o Texto estático transcriptText). O Dynamic Faces usa os termos "replacement" (substituição) e "re-rendering" (nova renderização) mais ou menos com o mesmo sentido. Quando o usuário envia um comentário clicando no botão Enviar ou pressionando a tecla Enter, a função customPostReplaceForCommentTx rola para a parte inferior da transcrição, limpa o Campo de texto de comentário, e coloca o foco dentro do Campo de texto de comentário.
Como você define a propriedade onLoad do componente Página page1 como handleOnLoad, o cliente chama a função handleOnLoad logo após carregar inicialmente a página. Essa função atribui uma referência de função handleMouseDown ao manipulador de eventos transcriptPanel.onmousedown e uma referência de função handleMouseUp ao manipulador de eventos document.onmouseup. A função handleMouseDown reage aos eventos mousedown no elemento transcriptPanel; a função handleMouseUp reage a eventos mouseup em qualquer local na página. Ambas as funções, junto com a função customReplaceForPollTx, trabalham juntas para garantir que a nova renderização em resposta a solicitações de consulta não ocorram se o usuário tiver pressionado o mouse na transcrição (incluindo qualquer barra de rolagem) e ainda não tiver liberado. Em tal momento, se o usuário estiver no processo de selecionar parte do texto da transcrição (por exemplo, em preparação de uma operação de cópia), a nova renderização da transcrição efetivamente impedirá a seleção; semelhantemente, se o usuário estiver rolando a transcrição no Firefox, renderizar novamente a transcrição fará com que a barra de rolagem congele. A função handleMouseUp manipula eventos mouseup no objeto document e não meramente no elemento transcriptPanel, já que o usuário poderia potencialmente pressionar o mouse na barra de rolagem da transcrição, arrastar o mouse para fora da área de transcrição e liberar o mouse. Em tal caso, a lógica precisa reagir ao evento mouseup embora ele não esteja na transcrição em si. Além dessas atribuições de função, a função handleOnLoad também desativa o recurso auto-completar do navegador do Campo de texto de comentário e inicia a consulta ao servidor.
A função poll aciona a Transação do Ajax pollTx, que envia uma solicitação do Ajax ao servidor. A resposta do Ajax correspondente irá disparar a nova renderização do Texto estático transcriptText.
Como você define a propriedade replaceElement da Transação do Ajax pollTx como customReplaceForPollTx, o cliente chama a função customReplaceForPollTx em vez da função de substituição padrão (ou seja, DynaFaces.replace) sempre que o cliente recebe uma resposta do Ajax associada a pollTx. Fornecer a função de substituição personalizada customReplaceForPollTx permite que você chame a função de substituição padrão condicionalmente com base em se o usuário estiver realizando certas operações na transcrição (ou seja, selecionando o texto da transcrição ou rolando a transcrição) assim como capture a posição de rolagem antes da substituição e role programaticamente, como apropriado, depois da substituição. Antes da substituição, use as propriedades scrollTop, scrollHeight e clientHeight do elemento transcriptPanel para determinar se existe uma barra de rolagem, e, nesse caso, se a transcrição for rolada para baixo. Em seguida, delegue a substituição real do conteúdo da transcrição para a função de substituição padrão (DynaFaces.replace). Após a substituição, role a transcrição para a mesma posição que ela estava antes da substituição, exceto sob certas condições. Especificamente, role a transcrição para baixo caso ela tenha sido rolada para baixo antes da substituição ou se agora houver uma barra de rolagem que não existia antes da substituição. No caso anterior, se você não rolar programaticamente a transcrição para baixo, quaisquer novas entradas da transcrição não aparecerão na visualização. No último caso, se você não rolar programaticamente a transcrição para baixo, ela permanecerá rolada para cima, obrigando o usuário efetivamente a rolar a transcrição para baixo manualmente.
Na função handleMouseDown, o Internet Explorer requer alguma lógica adicional. Se o usuário pressionar o mouse na barra de rolagem da transcrição, o Internet Explorer não chamará o manipulador de eventos atribuído a document.onmouseup quando o usuário liberar o mouse. Conseqüentemente, você não pode definir mouseDownOnTranscript como true, pois a liberação do mouse pelo usuário não chamará handleMouseUp e, portanto, mouseDownOnTranscript permanecerá true. Sob tais circunstâncias, a função customReplaceForPollTx passará por uma nova renderização até que a operação do mouse subseqüente dispare a função handleMouseup. Uma melhor abordagem é simplesmente retornar da função handleMouseDown sem definir mouseDownOnTranscript como true. Conseqüentemente, a função customReplaceForPollTx renderizará novamente a transcrição no Internet Explorer mesmo quando o usuário estiver rolando a transcrição. Entretanto, isso não representa qualquer problema, já que renderizar novamente a transcrição enquanto o usuário estiver rolando faz com que a barra de rolagem congele somente no Firefox, não no Internet Explorer.
Como você definiu a propriedade postReplace da Transação do Ajax pollTx como customPostReplaceForPollTx, o cliente chama a função customPostReplaceForPollTx depois de receber uma resposta do Ajax associada a pollTx e chamar a função customReplaceForPollTx. Desde que a variável continuePolling seja true (de forma que a página não esteja descarregando), a função customPostReplaceForPollTx envia a próxima solicitação de consulta após um atraso especificado pela variável pollDelay.
Como você definiu a propriedade onSubmit do componente Formulário form1 como return interceptFormSubmit, o cliente chama a função interceptFormSubmit quando o usuário clica no botão Enviar ou pressiona a tecla Enter. Desde que o Campo de texto de comentário não esteja vazio, a função interceptFormSubmit aciona a Transação do Ajax commentTx (que envia uma solicitação do Ajax) e retorna false a fim de impedir o envio convencional do formulário.
- Expanda a seção Avançado na Paleta e arraste um componente Script da seção Avançado para o Visual Designer.
- Na janela Navegador, abaixo do nó Page1 > page1 > html1 > head1, selecione o componente Script script1.
Na janela Propriedades, clique no botão de reticências (...) da propriedade url do componente Script script1. Na caixa de diálogo, selecione recursos > ajaxchatroom.js de forma que /resources/ajaxchatroom.js apareça no campo URL, e clique em OK.
Você configurou o componente Script script1 para emitir uma marca <script> para o arquivo JavaScript ajaxchatroom.js que você criou anteriormente.
Implantando o projeto
Essa aplicação Web foi testada com o Firefox e o Internet Explorer 7.
Na janela Projetos, clique com o botão direito do mouse no nó do projeto e escolha Executar para construir, implantar e iniciar a aplicação Web.
Seu navegador navega para http://localhost:8080/AjaxChatRoom/.
Indique um comentário no Campo de texto de comentário e pressione a tecla Enter ou clique no botão Enviar.
A entrada aparece na transcrição em azul, e seu nome de usuário é anonymous1.
Na barra de endereço do navegador, altere a URL para http://localhost:8080/AjaxChatRoom/?username=jack.
Sua entrada anterior agora aparece em roxo, já que você agora é reconhecido como jack em vez de anonymous1.
- Indique outro comentário no Campo de texto de comentário e pressione a tecla Enter ou clique no botão Enviar. A nova entrada aparece na transcrição em azul, e o seu nome de usuário é
jack.
- Determine seu endereço IP abrindo uma janela (ou comando) do terminal e adotando um dos seguintes procedimentos:
- Solaris/Linux/MAC. Digite
ifconfig -a e pressione Enter.
- Windows. Digite
ipconfig e pressione Enter.
Abra uma segunda janela do navegador ou aba e digite http://seu-endereço-ip:8080/AjaxChatRoom?username=jill.
As entradas enviadas por anonymous1 e jack aparecem em roxo.
Indique outro comentário no Campo de texto de comentário e pressione a tecla Enter ou clique no botão Enviar.
A nova entrada aparece na transcrição em azul, e seu nome de usuário é jill.
Alterne de volta para a janela ou aba do navegador original.
A entrada enviada por jill aparece em roxo.
- Continue a conversa entre
jack e jill até que a transcrição exiba uma barra de rolagem.
Role para o início do conteúdo da transcrição, mantendo o mouse pressionado, como se fosse reler o início da conversa. Aguarde alguns segundos antes de liberar o mouse.
O comportamento difere ligeiramente dependendo do navegador. No Firefox, a transcrição não é novamente renderizada em resposta a solicitações de consulta enquanto o mouse é pressionado. No Internet Explorer, a transcrição continua a se renderizar novamente enquanto o mouse é pressionado. Isso acontece porque a função handleMouseDown define a variável mouseDownOnTranscript como true no Internet Explorer. Essa diferença sutil no comportamento não é dectada durante o teste do aplicativo, como descrito nesta seção. Para observar a diferença no comportamento, você deve incluir uma pessoa adicional ao bate-papo, enviando comentários enquanto você realize essa etapa.
Selecione algum texto na transcrição, mas faça isso sem ainda liberar o botão do mouse. Use um atalho de teclado para copiar o texto para a área de transferência. Em seguida, libere o mouse, observando que o texto é desmarcado depois que você faz isso.
Enquanto você pressiona o mouse, a transcrição é renderizada novamente em resposta às solicitações de consulta. Entretanto, quando você libera o mouse, as solicitações de consulta subseqüentes fazem com que a transcrição seja novamente renderizada. A nova renderização da transcrição faz com que qualquer seleção feita seja perdida. O aplicativo poderia ser aprimorado adicionando-se a lógica na função customReplaceForPollTx para capturar informações sobre a seleção antes da substituição e do restabelecimento da seleção após a substituição. Nesse caso, quando o usuário selecionou algum texto, você poderia desmarcar o texto em resposta à próxima operação mousedown em qualquer local do documento. Você poderia fazer isso adicionando uma função que desmarcasse todo texto na transcrição e atribuindo uma referência à função no manipulador de eventos document.onmousedown.
Veja também
|