1 // (c) BenoƮt PIN 2006
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 req
.open("POST", obUrl
+ "/xml_nav_tree", true);
67 req
.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
68 req
.send("filter=" + this.filter
);
70 target
.src
= this.baseImgUrl
+ "mi_ani.gif";
71 this._lastAniImg
= target
;
74 window
.setTimeout(function(){tm
._removeLastAniImg();}, 500);
79 this.removeChildNodes(parentRow
);
80 target
.src
= this.baseImgUrl
+ "pl_ani.gif";
81 this._lastAniImg
= target
;
83 window
.setTimeout(function(){tm
._removeLastAniImg();}, 500);
85 } // end switch (imgId)
87 disablePropagation(evt
);
92 TreeMaker
.prototype._removeLastAniImg = function() {
93 if (this._lastAniImg
) {
94 this._lastAniImg
.src
= this._lastAniImg
.src
.replace("_ani", "");
100 * expand the tree: sends request and imports rows based on xml response.
102 TreeMaker
.prototype.importRows = function(req
, parentRow
) {
103 var rows
= req
.responseXML
.documentElement
.getElementsByTagName("row");
104 var clickedCells
= parentRow
.getElementsByTagName("TD");
105 var row
, newRow
, indentCell
, stateCell
, linkCell
, img
, a
, indentValue
, colspan
,
106 incTableDepth
=false, cols
, linkCellColSpan
;
108 for (var i
= 0 ; i
< rows
.length
; i
++ ) {
112 newRow
= document
.createElement("TR");
113 indentCell
= document
.createElement("TD");
114 stateCell
= document
.createElement("TD");
115 stateCell
.width
= "16";
116 linkCell
= document
.createElement("TD");
117 linkCell
.width
= "99%";
120 if (clickedCells
.length
== 3) {
121 indentValue
= parseInt(clickedCells
[0].getAttribute("colspan"));
122 colspan
= parseInt(clickedCells
[2].getAttribute("colspan"));
126 colspan
= parseInt(clickedCells
[1].getAttribute("colspan"));
129 cols
= indentValue
+ colspan
;
132 incTableDepth
= true;
134 indentCell
.colSpan
= indentValue
+ 1;
135 if (!this.depthCpt
[indentValue
])
136 this.depthCpt
[indentValue
] = 1;
138 this.depthCpt
[indentValue
] += 1;
140 // IE : it's not possible to set colSpan attr to 0 :-(((
141 linkCellColSpan
= cols
- indentValue
- 1
142 if (linkCellColSpan
== 0)
143 linkCell
.nullColSpan
= true;
145 linkCell
.colSpan
= linkCellColSpan
;
147 img
= document
.createElement("IMG");
148 img
.src
= row
.getAttribute("icon");
149 img
.height
= row
.getAttribute("height");
150 img
.width
= row
.getAttribute("width");
151 a
= document
.createElement("A");
153 a
.setAttribute("href", row
.getAttribute("url"));
154 a
.setAttribute("title", row
.getAttribute("description"));
155 a
.innerHTML
= row
.childNodes
[0].nodeValue
;
157 if (row
.getAttribute("state") == "-1") {
158 var stateLink
= document
.createElement("A");
159 stateLink
.href
= ".";
160 var stateImg
= document
.createElement("IMG");
161 stateImg
.src
= this.baseImgUrl
+ "pl.gif";
162 stateImg
.border
= "0";
163 stateImg
.height
= "16";
164 stateImg
.width
= "16";
165 stateLink
.appendChild(stateImg
)
166 stateCell
.appendChild(stateLink
);
169 stateCell
.innerHTML
= " ";
171 linkCell
.appendChild(img
);
172 linkCell
.appendChild(a
);
173 newRow
.appendChild(indentCell
);
174 newRow
.appendChild(stateCell
);
175 newRow
.appendChild(linkCell
);
178 this.root
.insertBefore(newRow
, parentRow
.nextSibling
);
182 var rows
= this.root
.getElementsByTagName("TR");
183 var cells
, lastCell
, lastColspan
;
184 for (var i
= 0 ; i
< rows
.length
; i
++) {
185 cells
= rows
[i
].getElementsByTagName("TD");
186 lastCell
= cells
[cells
.length
- 1];
188 if (lastCell
.nullColSpan
) {
189 lastCell
.nullColSpan
= false;
193 lastColspan
= parseInt(lastCell
.getAttribute("colspan"));
195 lastCell
.colSpan
= lastColspan
+ 1;
201 * collapse the tree: removes deeper rows after the 'baseRow' passed.
203 TreeMaker
.prototype.removeChildNodes = function(baseRow
) {
204 var baseCells
= baseRow
.getElementsByTagName("TD");
205 var baseColSpan
= baseCells
[baseCells
.length
-1].colSpan
;
206 var nextRow
= baseRow
.nextSibling
;
207 var tbody
= baseRow
.parentNode
;
208 var depthCpt
= this.depthCpt
;
209 var nextCells
, nextRow2
;
212 if (nextRow
.nodeType
== 1) {
213 nextCells
= nextRow
.getElementsByTagName("TD");
214 if (nextCells
.length
== 3 && nextCells
[2].colSpan
< baseColSpan
) {
215 nextRow2
= nextRow
.nextSibling
;
216 depthCpt
[nextCells
[0].colSpan
-1] -= 1;
217 tbody
.removeChild(nextRow
);
223 nextRow
= nextRow
.nextSibling
; // text node
226 // recalc colspans for Safari
227 var maxDepth
= depthCpt
.length
- 1;
228 var depthReduction
= 0;
229 while (depthCpt
[maxDepth
- depthReduction
] == 0) {
234 if (depthReduction
) {
235 var rows
= tbody
.getElementsByTagName("TR");
236 var cells
, lastCell
, lastColspan
;
237 for (var i
= 0 ; i
< rows
.length
; i
++) {
238 cells
= rows
[i
].getElementsByTagName("TD");
239 lastCell
= cells
[cells
.length
- 1];
240 lastCell
.colSpan
= parseInt(lastCell
.colSpan
) - depthReduction
;