Pergunta

Tomando Jeff Atwood conselho, decidi usar uma biblioteca JavaScript para o aplicativo básico de lista de tarefas que estou escrevendo.Eu escolhi o Kit de ferramentas Dojo, versão 1.1.1.No início, estava tudo bem:o código de arrastar e soltar que escrevi funcionou na primeira vez, você pode arrastar tarefas na tela para alterar sua ordem de precedência e cada operação de arrastar e soltar chama um manipulador de eventos que envia uma chamada AJAX ao servidor para permitir saiba que a ordem foi alterada.

Em seguida, adicionei a funcionalidade de rastreamento de e-mail.Coisas padrão:novos e-mails recebidos têm um número de identificação exclusivo anexado à linha de assunto. Todos os e-mails subsequentes sobre esse problema podem ser rastreados simplesmente deixando esse número de identificação no assunto ao responder.Portanto, temos uma lista de tarefas abertas, cada uma com seu próprio número de identificação, e cada uma dessas tarefas possui uma lista ordenada por tempo de e-mails associados.Eu queria que o texto desses e-mails estivesse disponível para o usuário enquanto ele olhava sua lista de tarefas, então fiz de cada caixa de tarefas um controle "Árvore" Dijit - o nível superior contém a descrição da tarefa, as ramificações contêm as datas dos e-mails e um uma única "folha" de cada uma dessas ramificações contém o texto do e-mail.

Primeiro problema:Eu queria que a visualização em árvore fosse totalmente recolhida por padrão.Depois de pesquisar bastante no Google, encontrei uma série de soluções, todas elas pareciam válidas para versões anteriores do Dojo, mas não para aquela que eu estava usando.Finalmente descobri que a melhor solução seria ter um manipulador de eventos chamado quando o controle Tree fosse carregado, que simplesmente colapsasse cada ramo/folha.Infelizmente, embora o controle Tree tenha sido instanciado e seu manipulador de eventos de "inicialização" tenha sido chamado, as ramificações e folhas ainda não foram carregadas (os dados ainda estavam sendo carregados por meio de uma chamada AJAX).Então, modifiquei o sistema para que todo o texto do email e a estrutura em árvore sejam adicionados no lado do servidor.Isso significa que todo o controle Tree totalmente preenchido estará disponível quando seu manipulador de eventos de inicialização for chamado.

Portanto, o manipulador de eventos de inicialização recolhe totalmente a árvore.Em seguida, não consegui encontrar uma maneira "adequada" de ter um texto bem formatado para as folhas de e-mail.Posso colocar o texto do e-mail na folha perfeitamente, mas qualquer HTML escapa e aparece na página da web.Dê uma olhada na documentação do Dojo (tende a estar desatualizada, com código e exemplos para versões anteriores à 1.0) e no Google.Finalmente, encontrei a solução de fazer com que o JavaScript lesse o elemento SPAN que está dentro de cada nó folha e desmarcasse o código HTML escapado em seu innerHTML.Pensei em colocar código para fazer isso com o código de colapso total da árvore, no manipulador de eventos de inicialização do controle Árvore.

No entanto...acontece que o elemento SPAN não é realmente criado até que o usuário clique no expando (o pequeno símbolo "+" em uma visualização em árvore em que você clica para expandir um nó).Ok, é justo - adicionarei o código de reformatação ao manipulador de eventos onExpand() ou como for chamado.O que parece não existir.Procurei na documentação, pesquisei no Google...Provavelmente estou entendendo mal o sistema de manipulação de eventos "publicar/assinar" do Dojo, mas acho que principalmente porque não parece haver nenhuma documentação abrangente para ele em lugar nenhum (como, onde posso descobrir quais eventos posso assinar para?).

Então, no final, a melhor solução que posso encontrar é adicionar um manipulador de eventos onClick (não um evento "Dojo", mas um evento JavaScript simples sobre o qual o Dojo não sabe nada) ao nó expando de cada ramo da árvore que re -formata o HTML dentro do elemento SPAN de cada folha.Exceto...quando isso é chamado, o elemento SPAN ainda não existe (às vezes - outras vezes ele foi armazenado em cache, apenas para confundir ainda mais você).Portanto, faço com que o manipulador de eventos configure um cronômetro que chama periodicamente uma função que verifica se o elemento SPAN relevante já apareceu antes de formatá-lo novamente.

// An event handler called whenever a "email title" tree node is expanded.
function formatTreeNode(nodeID) {
    if (dijit.byId(nodeID).getChildren().length != 0) {
        clearInterval(nodeUpdateIntervalID);
        messageBody = dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML
        if (messageBody.indexOf("<b>Message text:</b>") == -1) {
            messageBody = messageBody.replace(/&gt;/g, ">");
            messageBody = messageBody.replace(/&lt;/g, "<");
            messageBody = messageBody.replace(/&amp;/g, "&");
            dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML = "<b>Message text:</b><div style=\"font-family:courier\">"+messageBody+"</div>";
        }
    }
}

// An event handler called when a tree node has been set up - we changed the default fully-expanded to fully-collapsed.
function setupTree(theTree) {
    dijit.byId("tree-"+theTree).rootNode.collapse();

    messageNode = dijit.byId("tree-"+theTree).rootNode.getChildren();
    for (pl = 0; pl < messageNode.length; pl++) {
        messageNode[pl].collapse();
        messageNode[pl].expandoNode.onclick = eval("nodeUpdateIntervalID = setInterval(\"formatTreeNode('"+messageNode[pl].id+"')\",200); formatTreeNode('"+messageNode[pl].id+"');");
    }
}

O que foi dito acima dá a sensação de um hack verdadeiramente horrível, e tenho certeza de que devo ter tomado o caminho errado em algum lugar no início do meu processo de pensamento.Alguém pode me dizer:

  • A maneira correta de colocar texto bem formatado dentro de um controle Dojo/Dijit Tree.
  • A maneira correta de lidar com eventos do Dojo, por exemplo, onde posso descobrir quais eventos estão disponíveis para assinatura.
  • Uma biblioteca JavaScript melhor para usar (posso fazer o que quero com JQuery e evitar a abordagem geral vista acima?).

PS:Se você estiver nomeando um projeto de software, pense na exclusividade de seu nome no Google - tenho certeza de que pesquisar a documentação do "Dojo" no Google seria mais fácil sem que todos os resultados das artes marciais atrapalhassem.

PPS:O corretor ortográfico do Firefox sabe escrever "Atwood", corrigindo-me quando coloco dois 'T's em vez de um.Jeff é tão famoso agora?

Foi útil?

Solução

Presumo que você seguiu o dijit.Tree e dojo.data no Dojo 1.1 tutorial que orientou você a passar os dados para o controle de árvore usando um armazenamento de dados.Isso me fez bater a cabeça em uma parede de tijolos por um tempo.

Não é realmente uma ótima abordagem e a alternativa não está muito bem documentada.Você precisa criar um modelo de uso.Incluí abaixo um exemplo de um modelo de árvore que criei para exibir a estrutura de um diretório LDAP.

Você encontrará a implementação padrão do modelo em sua distribuição dojo em ./dijit/_tree/model.js.Os comentários devem ajudá-lo a compreender as funções suportadas pelo modelo.

A classe IDirectoryService, o código abaixo, são stubs para Java POJOs do lado do servidor gerados por Comunicação remota direta pela Web (DWR).Eu recomendo fortemente o DWR se você pretende fazer muita interação cliente-servidor.

dojo.declare("LDAPDirectoryTreeModel", [ dijit.tree.model ], {
    getRoot : function(onItem) {
        IDirectoryService.getRoots( function(roots) {
            onItem(roots[0])
        });
    },

    mayHaveChildren : function(item) {
        return true;
    },

    getChildren : function(parentItem, onComplete) {
        IDirectoryService.getChildrenImpl(parentItem, onComplete);
    },

    getIdentity : function(item) {
        return item.dn;
    },

    getLabel : function(item) {
        return item.rdn;
    }
});

E aqui está um extrato da minha página JSP onde criei o modelo e usei-o para preencher o controle de árvore.

<div
  dojoType="LDAPDirectoryTreeModel"
  jsid="treeModel"
  id="treeModel">
</div>
<div
  jsid="tree"
  id="tree"
  dojoType="dijit.Tree" model="treeModel"
  labelAttr="name"
  label="${directory.host}:${directory.port}">
</div>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top