1 /* This file is a part of CanDyDOC fileset.
2 File is written by Victor Nakoryakov and placed into the public domain.
4 This file is javascript with classes that represents native style tree control. */
\r
14 function TreeView(hrefMode)
\r
16 this.domEntry = document.createElement("div");
\r
17 this.children = new Array();
\r
18 this.selection = null;
\r
19 this.hrefMode = hrefMode;
\r
21 this.createBranch = function(text, iconSrc)
\r
23 var root = new TreeNode(text, iconSrc, this.hrefMode);
\r
25 this.children[ this.children.length ] = root;
\r
26 this.domEntry.appendChild( root.domEntry );
\r
30 this.branch = function(text)
\r
33 for (var i = 0; i < this.children.length; ++i)
\r
34 if (this.children[i].textElement.data == text)
\r
36 ret = this.children[i];
\r
43 this.domEntry.style.fontSize = "10px";
\r
44 this.domEntry.style.cursor = "default";
\r
45 this.domEntry.style.whiteSpace = "nowrap";
\r
49 function TreeNode(text, iconSrc, hrefMode)
\r
51 this.id = idCounter++;
\r
52 this.parentNode = null;
\r
53 this.children = new Array();
\r
54 this.domEntry = document.createElement("div");
\r
55 this.icon = document.createElement("img");
\r
56 this.textElement = document.createTextNode(text);
\r
57 this.textSpan = document.createElement("span");
\r
58 this.lineDiv = document.createElement("div");
\r
59 this.hierarchyImgs = new Array();
\r
60 this.onclick = null;
\r
62 function createIcon()
\r
64 var img = document.createElement("img");
\r
65 img.style.verticalAlign = "middle";
\r
66 img.style.position = "relative";
\r
67 img.style.top = "-1px";
\r
73 function createHierarchyImage()
\r
75 var img = createIcon();
\r
76 img.pointsTop = false;
\r
77 img.pointsBottom = false;
\r
78 img.pointsRight = false;
\r
79 img.pmState = pmNone;
\r
83 function genHierarchyImageSrc(hierarchyImg)
\r
86 if (hierarchyImg.pointsTop)
\r
89 if (hierarchyImg.pointsBottom)
\r
92 if (hierarchyImg.pointsRight)
\r
95 if (hierarchyImg.pmState == pmPlus)
\r
97 else if (hierarchyImg.pmState == pmMinus)
\r
103 return "../../candydoc/img/tree/" + name + ".gif";
\r
106 function setSrc(icon, src)
\r
109 // After src change width and height are reseted in IE.
\r
115 this.createChild = function(text, iconSrc)
\r
117 var child = new TreeNode(text, iconSrc, this.owner.hrefMode);
\r
118 this.children[ this.children.length ] = child;
\r
119 this.domEntry.appendChild( child.domEntry );
\r
120 child.parentNode = this;
\r
121 child.owner = this.owner;
\r
123 // insert hierarchy images according to deepness level
\r
124 // of created child.
\r
126 if (this.children.length > 1)
\r
128 // there were already added child before. So copy `level-1`
\r
129 // hierarchy images from it.
\r
131 var prevAddedChild = this.children[ this.children.length - 2 ];
\r
133 for (var i = 0; i < prevAddedChild.hierarchyImgs.length - 1; ++i)
\r
135 var prevAddedChildImg = prevAddedChild.hierarchyImgs[i];
\r
136 var img = createHierarchyImage();
\r
137 setSrc(img, prevAddedChildImg.src);
\r
138 img.pointsTop = prevAddedChildImg.pointsTop;
\r
139 img.pointsBottom = prevAddedChildImg.pointsBottom;
\r
140 img.pointsRight = prevAddedChildImg.pointsRight;
\r
141 img.pmState = prevAddedChildImg.pmState;
\r
143 child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
\r
144 child.lineDiv.insertBefore(img, child.icon);
\r
147 // change last hierarchy image of prevAddedChild from |_ to |-
\r
148 var lastHierarchyImg = prevAddedChild.hierarchyImgs[ prevAddedChild.hierarchyImgs.length - 1 ];
\r
149 lastHierarchyImg.pointsBottom = true;
\r
150 setSrc(lastHierarchyImg, genHierarchyImageSrc(lastHierarchyImg));
\r
152 // change hierarchy images of prevAddedChild's children on it's last
\r
154 prevAddedChild.addHierarchyTBLine(prevAddedChild.hierarchyImgs.length - 1);
\r
158 // this is a first child. So copy `level-2`
\r
159 // hierarchy images from parent, i.e. this.
\r
161 for (var i = 0; i < this.hierarchyImgs.length - 1; ++i)
\r
163 var parentImg = this.hierarchyImgs[i];
\r
164 var img = createHierarchyImage();
\r
165 setSrc(img, parentImg.src);
\r
166 img.pointsTop = parentImg.pointsTop;
\r
167 img.pointsBottom = parentImg.pointsBottom;
\r
168 img.pointsRight = parentImg.pointsRight;
\r
169 img.pmState = parentImg.pmState;
\r
171 child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
\r
172 child.lineDiv.insertBefore(img, child.icon);
\r
175 if (this.hierarchyImgs.length > 0) // we are not root
\r
177 // change last hierarchy image of parent (i.e. this): add minus to it
\r
178 var lastHierarchyImg = this.hierarchyImgs[ this.hierarchyImgs.length - 1];
\r
179 lastHierarchyImg.pmState = pmMinus;
\r
180 setSrc(lastHierarchyImg, genHierarchyImageSrc(lastHierarchyImg));
\r
181 lastHierarchyImg.owner = this;
\r
182 lastHierarchyImg.onclick = new Function("e", "this.owner.processPMClick(e);");
\r
184 // make decision on image on `level-1`. It depends on parent's (ie this)
\r
185 // image on same level.
\r
186 var parentL1HierarchyImg = lastHierarchyImg;
\r
187 var l1HierarchyImg = createHierarchyImage();
\r
188 if (parentL1HierarchyImg.pointsBottom)
\r
190 l1HierarchyImg.pointsTop = true;
\r
191 l1HierarchyImg.pointsBottom = true;
\r
193 setSrc(l1HierarchyImg, genHierarchyImageSrc(l1HierarchyImg));
\r
194 child.hierarchyImgs[ child.hierarchyImgs.length ] = l1HierarchyImg;
\r
195 child.lineDiv.insertBefore(l1HierarchyImg, child.icon);
\r
199 // in any case on last level our child will have icon |_
\r
200 var img = createHierarchyImage();
\r
201 img.pointsTop = true;
\r
202 img.pointsRight = true;
\r
203 setSrc(img, genHierarchyImageSrc(img));
\r
205 child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
\r
206 child.lineDiv.insertBefore(img, child.icon);
\r
211 this.lastChild = function()
\r
213 return this.children[ this.children.length - 1 ];
\r
216 this.child = function(text)
\r
219 for (var i = 0; i < this.children.length; ++i)
\r
220 if (this.children[i].textElement.data == text)
\r
222 ret = this.children[i];
\r
229 this.addHierarchyTBLine = function(level)
\r
231 for (var i = 0; i < this.children.length; ++i)
\r
233 var img = this.children[i].hierarchyImgs[level];
\r
234 img.pointsTop = true;
\r
235 img.pointsBottom = true;
\r
236 setSrc(img, genHierarchyImageSrc(img));
\r
237 this.children[i].addHierarchyTBLine(level);
\r
241 this.expand = function()
\r
243 var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
\r
245 if (img.pmState == pmPlus)
\r
247 img.pmState = pmMinus;
\r
248 setSrc(img, genHierarchyImageSrc(img));
\r
250 for (var i = 0; i < this.children.length; ++i)
\r
251 this.children[i].domEntry.style.display = "";
\r
255 this.collapse = function()
\r
257 var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
\r
259 if (img.pmState == pmMinus)
\r
261 img.pmState = pmPlus;
\r
262 setSrc(img, genHierarchyImageSrc(img));
\r
264 for (var i = 0; i < this.children.length; ++i)
\r
265 this.children[i].domEntry.style.display = "none";
\r
269 this.toggle = function()
\r
271 var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
\r
272 if (img.pmState == pmMinus)
\r
278 this.select = function()
\r
280 if (this.owner.selection != this)
\r
282 if (this.owner.selection)
\r
283 this.owner.selection.setHighlight(hlNone);
\r
285 this.owner.selection = this;
\r
286 this.setHighlight(hlSelected);
\r
290 this.setHighlight = function(mode)
\r
292 if (mode == hlNone)
\r
294 this.textSpan.style.backgroundColor = "";
\r
295 this.textSpan.style.color = "";
\r
296 this.textSpan.style.border = "";
\r
298 else if (mode == hlGrey)
\r
300 this.textSpan.style.backgroundColor = "#aaaaaa";
\r
301 this.textSpan.style.color = "";
\r
302 this.textSpan.style.border = "";
\r
304 else if (mode == hlSelected)
\r
306 this.textSpan.style.backgroundColor = "3399cc";
\r
307 this.textSpan.style.color = "white";
\r
308 this.textSpan.style.border = "dotted 1px red";
\r
312 this.setOnclick = function(proc)
\r
314 this.onclick = proc;
\r
317 this.setRef = function(url)
\r
320 this.anchor.href = url;
\r
323 this.processPMClick = function(e)
\r
327 // prevent this line selection, stop bubbling
\r
329 e.stopPropagation(); // Mozilla way
\r
331 window.event.cancelBubble = true; // IE way
\r
334 this.processOnclick = function()
\r
337 if (this.onclick instanceof Function)
\r
341 ///////////////////////////////////////////////////////////////////////////
\r
343 this.icon.src = iconSrc;
\r
346 this.icon.width = 0;
\r
347 this.icon.height = 0;
\r
350 this.icon.style.verticalAlign = "middle";
\r
351 this.icon.style.position = "relative";
\r
352 this.icon.style.top = "-1px";
\r
353 this.icon.style.paddingRight = "2px";
\r
357 this.textSpan.appendChild( this.textElement );
\r
361 this.anchor = document.createElement("a");
\r
362 this.anchor.appendChild( this.textElement );
\r
363 this.textSpan.appendChild( this.anchor );
\r
366 this.lineDiv.appendChild( this.icon );
\r
367 this.lineDiv.appendChild( this.textSpan );
\r
368 this.domEntry.appendChild( this.lineDiv );
\r
370 this.lineDiv.owner = this;
\r
373 this.lineDiv.onclick = new Function("this.owner.processOnclick();");
\r