以杰夫·阿特伍德为例 建议, ,我决定使用 JavaScript 库来编写我正在编写的非常基本的待办事项列表应用程序。我选择了 道场工具包, ,版本1.1.1。起初,一切都很好:我编写的拖放代码第一次工作,您可以将任务拖到屏幕上以更改其优先顺序,并且每个拖放操作都会调用一个事件处理程序,该事件处理程序将 AJAX 调用发送到服务器以使其知道顺序已更改。

然后我添加了电子邮件跟踪功能。标准的东西:新收到的电子邮件的主题行中附有一个唯一的 ID 号,您只需在回复时将该 ID 号留在主题中即可跟踪有关该问题的所有后续电子邮件。因此,我们有一个未完成任务的列表,每个任务都有自己的 ID 号,并且每个任务都有一个按时间顺序排列的关联电子邮件列表。我希望用户在查看任务列表时可以看到这些电子邮件的文本,因此我将每个任务框设为 Dijit“树”控件 - 顶层包含任务描述,分支包含电子邮件日期,以及每个分支的单个“叶子”包含电子邮件文本。

第一个问题:我希望树视图默认完全折叠。在 Google 上进行了大量搜索后,我发现了许多解决方案,所有这些解决方案似乎都适用于以前版本的 Dojo,但不适用于我正在使用的版本。我最终发现最好的解决方案似乎是在加载树控件时调用一个事件处理程序,简单地折叠每个分支/叶子。不幸的是,即使 Tree 控件已经实例化并且调用了它的“启动”事件处理程序,分支和叶子仍然没有加载(数据仍然通过 AJAX 调用加载)。因此,我修改了系统,以便将所有电子邮件文本和树结构添加到服务器端。这意味着当调用其启动事件处理程序时,整个完全填充的 Tree 控件都可用。

因此,启动事件处理程序完全折叠树。接下来,我找不到一种“正确”的方法来为电子邮件留下漂亮的格式化文本。我可以将电子邮件文本放在叶子中,但任何 HTML 都会被转义并显示在网页中。请更多地翻阅 Dojo 的文档(往往已经过时,包含 1.0 之前版本的代码和示例)和 Google。我最终想出了一个解决方案,让 JavaScript 读取每个叶节点内的 SPAN 元素,并在其 innerHTML 中取消转义转义的 HTML 代码。我想我应该将代码与完全折叠树代码一起放入树控件的启动事件处理程序中。

然而...事实证明,直到用户单击“展开”(单击以展开节点的树视图中的小“+”符号)后,SPAN 元素才真正创建。好吧,很公平 - 我会将重新格式化代码添加到 onExpand() 事件处理程序或任何名称的事件处理程序中。这似乎不存在。我搜索过文档,搜索过谷歌......我很可能误解了 Dojo 的“发布/订阅”事件处理系统,但我认为这主要是因为在任何地方似乎都没有任何全面的文档(例如,我在哪里可以找到我可以订阅哪些事件)到?)。

因此,最后,我能想到的最佳解决方案是向每个树分支的 Expando 节点添加一个 onClick 事件处理程序(不是“Dojo”事件,而是 Dojo 一无所知的纯 JavaScript 事件)。 -格式化每个叶子的 SPAN 元素内的 HTML。除了...当调用它时,SPAN 元素仍然不存在(有时 - 其他时候它已被缓存,只是为了进一步迷惑您)。因此,我让事件处理程序设置一个计时器,定期调用一个函数,检查相关的 SPAN 元素是否已出现,然后重新格式化它。

// 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+"');");
    }
}

上面的内容给人一种真正可怕的黑客攻击的感觉,我确信我在思考过程的早期一定是走错了方向。有人可以告诉我吗:

  • 将格式良好的文本放入 Dojo/Dijit Tree 控件中的正确方法。
  • 处理 Dojo 事件的正确方法,例如我可以在其中找出可供我订阅的事件。
  • 一个更好的 JavaScript 库(我可以用 JQuery 做我想做的事情并避免上面看到的全屋方法吗?)。

附:如果您要命名一个软件项目,请考虑其名称在 Google 中的唯一性 - 我确信在 Google 中搜索“Dojo”文档会更容易,而不会受到所有武术结果的影响。

聚苯醚:Firefox 拼写检查器知道如何拼写“Atwood”,当我输入两个“T”而不是一个“T”时,它会纠正我。杰夫现在这么出名了吗?

有帮助吗?

解决方案

我假设你遵循 Dojo 1.1 中的 dijit.Tree 和 dojo.data 教程指导您使用数据存储将数据传递到树控件。这让我有一段时间用头撞砖墙。

这并不是一个很好的方法,并且替代方案也没有得到很好的记录。您需要创建一个使用模型。下面是我为显示 LDAP 目录结构而创建的树模型示例。

您将在 dojo 发行版的 ./dijit/_tree/model.js 中找到该模型的默认实现。注释应该可以帮助您理解模型支持的功能。

IDirectoryService 类(下面的代码是由以下代码生成的服务器端 Java POJO 的存根) 直接 Web 远程处理 (DWR)。如果您要进行大量客户端-服务器交互,我强烈推荐 DWR。

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;
    }
});

下面是我的 JSP 页面的摘录,我在其中创建了模型并使用它来填充树控件。

<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>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top