【发布时间】:2010-09-07 10:03:47
【问题描述】:
以 Jeff Atwood 的 advice 为例,我决定将 JavaScript 库用于我正在编写的非常基本的待办事项列表应用程序。我选择了Dojo toolkit,版本 1.1.1。一开始,一切都很好:我写的拖放代码第一次工作,你可以在屏幕上拖动任务来改变它们的优先顺序,每个拖放操作都会调用一个发送 AJAX 的事件处理程序调用服务器,让它知道订单已更改。
然后我去添加电子邮件跟踪功能。标准的东西:新收到的电子邮件在其主题行上附加了一个唯一的 ID 号,所有有关该问题的后续电子邮件都可以通过在您回复时简单地在主题中留下该 ID 号来跟踪。因此,我们有一个打开的任务列表,每个任务都有自己的 ID 号,每个任务都有一个按时间排序的关联电子邮件列表。我希望用户在查看任务列表时可以使用这些电子邮件的文本,因此我将每个任务框设为 Dijit“树”控件 - 顶层包含任务描述,分支包含电子邮件日期,以及每个分支的单个“叶子”包含电子邮件文本。
第一个问题:我希望树视图默认完全折叠。在 Google 上进行了相当广泛的搜索后,我发现了许多解决方案,所有这些似乎都适用于以前版本的 Dojo,但不是我使用的那个。我最终发现最好的解决方案似乎是在加载 Tree 控件时调用一个事件处理程序,该处理程序只是折叠每个分支/叶子。不幸的是,即使 Tree 控件已经被实例化并调用了它的“启动”事件处理程序,分支和叶子仍然没有加载(数据仍然通过 AJAX 调用加载)。因此,我修改了系统,以便在服务器端添加所有电子邮件文本和树结构。这意味着当调用其启动事件处理程序时,整个完全填充的 Tree 控件都可用。
因此,启动事件处理程序完全折叠树。接下来,我找不到一种“正确”的方式来为电子邮件留下漂亮的格式化文本。我可以将电子邮件文本很好地放在叶子中,但是任何 HTML 都会被转义并显示在网页中。更多地在 Dojo 的文档(往往已经过时,包含 1.0 之前的版本的代码和示例)和 Google 周围寻找更多信息。我最终想出了让 JavaScript 去读取每个叶节点内部的 SPAN 元素并在其 innerHTML 中取消转义转义的 HTML 代码的解决方案。我想我应该在 Tree 控件的启动事件处理程序中使用完全折叠树代码来执行此操作。
但是...事实证明,直到用户单击 expando(单击以展开节点的树视图中的小“+”符号),才真正创建 SPAN 元素。好的,很公平 - 我将重新格式化代码添加到 onExpand() 事件处理程序,或者它被调用的任何东西。这似乎不存在。我搜索了文档,搜索了谷歌......我很可能误解了 Dojo 的“发布/订阅”事件处理系统,但我认为这主要是因为似乎没有任何全面的文档它可以在任何地方(例如,我在哪里可以找到我可以订阅的事件?)。
所以,最后,我能想出的最佳解决方案是向每个 Tree 的 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(/>/g, ">");
messageBody = messageBody.replace(/</g, "<");
messageBody = messageBody.replace(/&/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 做我想做的事并避免上面看到的全方位方法吗?)。
PS:如果您要命名一个软件项目,请考虑其名称在 Google 中的独特性 - 我确信在 Google 中搜索“Dojo”文档会更容易,而不会妨碍所有武术结果。
PPS:Firefox 拼写检查器知道如何拼写“Atwood”,当我输入两个“T”而不是一个时纠正了我。杰夫现在就那么出名了吗?
【问题讨论】:
标签: javascript dojo