문제
Jeff Atwood를 복용 조언, 저는 제가 작성하고 있는 매우 기본적인 할 일 목록 애플리케이션에 JavaScript 라이브러리를 사용하기로 결정했습니다.내가 골랐어 Dojo 툴킷, 버전 1.1.1.처음에는 모든 것이 괜찮았습니다.제가 작성한 드래그 앤 드롭 코드는 처음에는 제대로 작동했습니다. 화면에서 작업을 드래그하여 우선 순위를 변경할 수 있으며, 각 드래그 앤 드롭 작업은 서버에 AJAX 호출을 보내는 이벤트 핸들러를 호출하여 이를 허용합니다. 순서가 변경된 것으로 알고 있습니다.
그런 다음 이메일 추적 기능을 추가했습니다.표준 사항:새로 수신되는 이메일에는 제목 줄에 고유 ID 번호가 첨부되어 있으며, 해당 문제에 대한 모든 후속 이메일은 회신할 때 제목에 해당 ID 번호를 남겨두기만 하면 추적할 수 있습니다.따라서 우리는 각각 고유한 ID 번호가 있는 미결 작업 목록을 갖고 있으며, 각 작업에는 시간순으로 정렬된 관련 이메일 목록이 있습니다.사용자가 작업 목록을 볼 때 해당 이메일의 텍스트를 사용할 수 있기를 원했기 때문에 각 작업 상자를 Dijit "트리" 컨트롤로 만들었습니다. 최상위 수준에는 작업 설명이 포함되고 분기에는 이메일 날짜가 포함됩니다. 각 분기의 단일 "리프"에는 이메일 텍스트가 포함됩니다.
첫 번째 문제:기본적으로 트리 보기가 완전히 접혀 있기를 원했습니다.Google을 상당히 광범위하게 검색한 후 여러 가지 솔루션을 찾았는데, 모두 이전 버전의 Dojo에는 유효한 것처럼 보였지만 내가 사용했던 솔루션에는 적용되지 않았습니다.나는 결국 가장 좋은 해결책은 단순히 각 분기/리프를 축소하는 Tree 컨트롤이 로드되었을 때 호출되는 이벤트 핸들러를 갖는 것인 것 같다는 것을 알아냈습니다.불행하게도 Tree 컨트롤이 인스턴스화되고 "시작" 이벤트 핸들러가 호출되었음에도 불구하고 가지와 잎은 여전히 로드되지 않았습니다(데이터는 여전히 AJAX 호출을 통해 로드되고 있었습니다).그래서 모든 이메일 텍스트와 트리 구조가 서버 측에 추가되도록 시스템을 수정했습니다.이는 시작 이벤트 핸들러가 호출될 때 완전히 채워진 전체 Tree 컨트롤을 사용할 수 있음을 의미합니다.
따라서 시작 이벤트 핸들러는 트리를 완전히 축소합니다.다음으로, 나는 이메일 잎에 대한 좋은 형식의 텍스트를 갖는 "적절한" 방법을 찾을 수 없었습니다.이메일 텍스트를 리프에 넣을 수는 있지만 모든 HTML은 이스케이프되어 웹 페이지에 표시됩니다.Dojo의 문서(1.0 이전 버전의 코드와 예제가 포함되어 오래된 경향이 있음)와 Google에 대해 더 자세히 알아보세요.나는 결국 JavaScript가 각 리프 노드 내부에 있는 SPAN 요소를 읽고 innerHTML에서 이스케이프된 HTML 코드를 이스케이프 해제하도록 하는 솔루션을 생각해냈습니다.나는 Tree 컨트롤의 시작 이벤트 처리기에서 완전히 축소된 트리 코드를 사용하여 이 작업을 수행하는 코드를 넣을 것이라고 생각했습니다.
하지만...SPAN 요소는 사용자가 확장(노드를 확장하기 위해 클릭하는 트리 보기의 작은 "+" 기호)을 클릭할 때까지 실제로 생성되지 않는 것으로 나타났습니다.좋아요, 공평합니다. onExpand() 이벤트 핸들러나 그 이름이 무엇이든 다시 형식 지정 코드를 추가하겠습니다.존재하지 않는 것 같습니다.문서를 검색하고 Google을 검색했습니다.나는 Dojo의 "게시/구독" 이벤트 처리 시스템을 잘못 이해하고 있을 가능성이 높습니다. 하지만 주로 이에 대한 포괄적인 문서가 어디에도 없는 것 같기 때문에 그렇게 생각합니다. 에게?).
그래서 결국 제가 생각해 낼 수 있는 최선의 해결책은 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로 원하는 것을 수행하고 위에서 본 만능 접근 방식을 피할 수 있습니까?)
추신:소프트웨어 프로젝트의 이름을 지정하는 경우 Google에서 해당 이름의 고유성을 고려하세요. 모든 무술 결과를 방해하지 않고 Google에서 "Dojo" 문서를 검색하는 것이 더 쉬울 것이라고 확신합니다.
조달청:Firefox 맞춤법 검사기는 "Atwood" 철자를 아는 방법으로 'T'를 하나 대신 두 개 넣으면 수정해 줍니다.제프가 이제 그렇게 유명해졌나요?
해결책
나는 당신이 따라했다고 가정합니다 Dojo 1.1의 dijit.Tree 및 dojo.data 데이터 저장소를 사용하여 트리 컨트롤에 데이터를 전달하도록 지시한 튜토리얼입니다.그 때문에 한동안 벽돌 벽에 머리를 부딪히게 되었습니다.
실제로는 훌륭한 접근 방식이 아니며 대안이 실제로 잘 문서화되어 있지 않습니다.대신 사용 모델을 만들어야 합니다.아래에는 LDAP 디렉터리의 구조를 표시하기 위해 만든 트리 모델의 예가 포함되어 있습니다.
./dijit/_tree/model.js의 Dojo 배포판에서 모델의 기본 구현을 찾을 수 있습니다.설명은 모델에서 지원하는 기능을 이해하는 데 도움이 됩니다.
아래 코드의 IDirectoryService 클래스는 다음에서 생성된 서버측 Java POJO용 스텁입니다. 직접 웹 원격 (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>