8 /* root -> base node (typically a tbody or a table)
9 * filter -> comma separated list of portal_types
11 TreeMaker = function (root
, filter
, baseImgUrl
) {
14 this.root
.onclick = function(evt
) { tm
.refreshTree(evt
); };
16 this.baseImgUrl
= baseImgUrl
;
17 this.depthCpt
= new Array();
18 this._lastAniImg
= null;
21 var images
= ['pl.gif', 'pl_ani.gif', 'mi.gif', 'mi_ani.gif'], img
;
22 for (var i
=0 ; i
< images
.length
; i
++) {
24 img
.src
= this.baseImgUrl
+ images
[i
];
29 * expand / collapse handler
30 * object loading trigger
32 TreeMaker
.prototype.refreshTree = function (evt
) {
33 var target
= getTargetedObject(evt
);
37 if (target
.tagName
== 'IMG') {
38 target
.parentNode
.blur();
39 var srcParts
= target
.src
.split("/");
40 var imgId
= srcParts
[srcParts
.length
-1];
41 var parentTd
= target
.parentNode
.parentNode
;
42 var parentRow
= parentTd
.parentNode
;
48 var linkCell
= parentTd
.nextSibling
;
49 while (linkCell
.nodeType
!= 1)
50 linkCell
= linkCell
.nextSibling
;
52 var obUrl
= linkCell
.getElementsByTagName("A")[0].href
;
54 var req
= new XMLHttpRequest();
56 req
.onreadystatechange = function() {
57 switch (req
.readyState
) {
63 tm
.importRows(req
, parentRow
);
66 target
.src
= this.baseImgUrl
+ "mi_ani.gif";
67 this._lastAniImg
= target
;
68 window
.setTimeout(function(){tm
._removeLastAniImg();}, 500);
70 req
.open("POST", obUrl
+ "/xml_nav_tree", true);
71 req
.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
72 req
.send("filter=" + encodeURIComponent(this.filter
) +
73 "&root_name=" + encodeURIComponent(this.root
.id
) +
74 "&expansion=" + encodeURIComponent(this.getExpansion()));
80 this.removeChildNodes(parentRow
);
81 target
.src
= this.baseImgUrl
+ "pl_ani.gif";
82 this._lastAniImg
= target
;
84 window
.setTimeout(function(){tm
._removeLastAniImg();}, 500);
86 } // end switch (imgId)
88 disablePropagation(evt
);
93 TreeMaker
.prototype._removeLastAniImg = function() {
94 if (this._lastAniImg
) {
95 this._lastAniImg
.src
= this._lastAniImg
.src
.replace("_ani", "");
99 TreeMaker
.prototype.getExpansion = function() {
100 var rows
= this.root
.getElementsByTagName('TR');
101 var row
, cells
, stateCell
, button
, expid
, node_depth
, last_depth
= -1, dd
, step
;
102 var steps
= new Array();
103 steps
.push(this.root
.getAttribute('name'));
105 var expanded
= (/.*mi\.gif$|.*mi_ani\.gif$/);
106 for(i
=0 ; i
< rows
.length
; i
++) {
108 cells
= row
.getElementsByTagName('TD');
109 stateCell
= cells
[cells
.length
-2]; // cell where the +/- button is
110 button
= stateCell
.getElementsByTagName('IMG');
114 if (expanded
.test(button
.src
)) {
115 expid
= button
.parentNode
.getAttribute("name");
116 node_depth
= cells
[0].getAttribute('colspan') || 0;
117 dd
= last_depth
- node_depth
+ 1;
118 last_depth
= node_depth
;
121 for (var j
= 0 ; j
< dd
; j
++)
128 return steps
.join(':');
133 * expand the tree: sends request and imports rows based on xml response.
135 TreeMaker
.prototype.importRows = function(req
, parentRow
) {
136 var rows
= req
.responseXML
.documentElement
.getElementsByTagName("row");
137 var clickedCells
= parentRow
.getElementsByTagName("TD");
138 var row
, newRow
, indentCell
, stateCell
, linkCell
, img
, a
, indentValue
, colspan
,
139 incTableDepth
=false, cols
, linkCellColSpan
;
141 for (var i
= 0 ; i
< rows
.length
; i
++ ) {
145 newRow
= document
.createElement("TR");
146 indentCell
= document
.createElement("TD");
147 stateCell
= document
.createElement("TD");
148 stateCell
.width
= "16";
149 linkCell
= document
.createElement("TD");
150 linkCell
.width
= "99%";
153 if (clickedCells
.length
== 3) {
154 indentValue
= parseInt(clickedCells
[0].getAttribute("colspan"));
155 colspan
= parseInt(clickedCells
[2].getAttribute("colspan"));
159 colspan
= parseInt(clickedCells
[1].getAttribute("colspan"));
162 cols
= indentValue
+ colspan
;
165 incTableDepth
= true;
167 indentCell
.colSpan
= indentValue
+ 1;
168 if (!this.depthCpt
[indentValue
])
169 this.depthCpt
[indentValue
] = 1;
171 this.depthCpt
[indentValue
] += 1;
173 // IE : it's not possible to set colSpan attr to 0 :-(((
174 linkCellColSpan
= cols
- indentValue
- 1
175 if (linkCellColSpan
== 0)
176 linkCell
.nullColSpan
= true;
178 linkCell
.colSpan
= linkCellColSpan
;
180 img
= document
.createElement("IMG");
181 img
.src
= row
.getAttribute("icon");
182 img
.height
= row
.getAttribute("height");
183 img
.width
= row
.getAttribute("width");
184 a
= document
.createElement("A");
186 a
.setAttribute("href", row
.getAttribute("url"));
187 a
.setAttribute("title", row
.getAttribute("description"));
188 a
.innerHTML
= row
.childNodes
[0].nodeValue
;
190 if (row
.getAttribute("state") == "-1") {
191 var stateLink
= document
.createElement("A");
192 stateLink
.href
= ".";
193 stateLink
.setAttribute("name", row
.getAttribute("name"));
194 var stateImg
= document
.createElement("IMG");
195 stateImg
.src
= this.baseImgUrl
+ "pl.gif";
196 stateImg
.border
= "0";
197 stateImg
.height
= "16";
198 stateImg
.width
= "16";
199 stateLink
.appendChild(stateImg
)
200 stateCell
.appendChild(stateLink
);
203 stateCell
.innerHTML
= " ";
205 linkCell
.appendChild(img
);
206 linkCell
.appendChild(a
);
207 newRow
.appendChild(indentCell
);
208 newRow
.appendChild(stateCell
);
209 newRow
.appendChild(linkCell
);
212 this.root
.insertBefore(newRow
, parentRow
.nextSibling
);
216 var rows
= this.root
.getElementsByTagName("TR");
217 var cells
, lastCell
, lastColspan
;
218 for (var i
= 0 ; i
< rows
.length
; i
++) {
219 cells
= rows
[i
].getElementsByTagName("TD");
220 lastCell
= cells
[cells
.length
- 1];
222 if (lastCell
.nullColSpan
) {
223 lastCell
.nullColSpan
= false;
227 lastColspan
= parseInt(lastCell
.getAttribute("colspan"));
229 lastCell
.colSpan
= lastColspan
+ 1;
235 * collapse the tree: removes deeper rows after the 'baseRow' passed.
237 TreeMaker
.prototype.removeChildNodes = function(baseRow
) {
238 var baseCells
= baseRow
.getElementsByTagName("TD");
239 var baseColSpan
= baseCells
[baseCells
.length
-1].colSpan
;
240 var nextRow
= baseRow
.nextSibling
;
241 var tbody
= baseRow
.parentNode
;
242 var depthCpt
= this.depthCpt
;
243 var nextCells
, nextRow2
;
246 if (nextRow
.nodeType
== 1) {
247 nextCells
= nextRow
.getElementsByTagName("TD");
248 if (nextCells
.length
== 3 && nextCells
[2].colSpan
< baseColSpan
) {
249 nextRow2
= nextRow
.nextSibling
;
250 depthCpt
[nextCells
[0].colSpan
-1] -= 1;
251 tbody
.removeChild(nextRow
);
257 nextRow
= nextRow
.nextSibling
; // text node
260 // recalc colspans for Safari
261 var maxDepth
= depthCpt
.length
- 1;
262 var depthReduction
= 0;
263 while (depthCpt
[maxDepth
- depthReduction
] == 0) {
268 if (depthReduction
) {
269 var rows
= tbody
.getElementsByTagName("TR");
270 var cells
, lastCell
, lastColspan
;
271 for (var i
= 0 ; i
< rows
.length
; i
++) {
272 cells
= rows
[i
].getElementsByTagName("TD");
273 lastCell
= cells
[cells
.length
- 1];
274 lastCell
.colSpan
= parseInt(lastCell
.colSpan
) - depthReduction
;