cda2925cb91beff15c3f5af855a019367b6ba485
[MosaicDocument.git] / default_blocks / tree_block_script.js
1 // (c) BenoƮt PIN 2006
2 // http://plinn.org
3 // Licence GPL
4
5 var TreeMaker;
6
7 (function() {
8 /* root -> base node (typically a tbody or a table)
9 * filter -> comma separated list of portal_types
10 */
11 TreeMaker = function (root, filter, baseImgUrl) {
12 this.root = root;
13 var tm = this;
14 this.root.onclick = function(evt) { tm.refreshTree(evt); };
15 this.filter = filter;
16 this.baseImgUrl = baseImgUrl;
17 this.depthCpt = new Array();
18 this._lastAniImg = null;
19
20 // preload images
21 var images = ['pl.gif', 'pl_ani.gif', 'mi.gif', 'mi_ani.gif'], img;
22 for (var i=0 ; i < images.length ; i++) {
23 img = new Image();
24 img.src = this.baseImgUrl + images[i];
25 }
26 }
27
28 /*
29 * expand / collapse handler
30 * object loading trigger
31 */
32 TreeMaker.prototype.refreshTree = function (evt) {
33 var target = getTargetedObject(evt);
34 if (target.blur)
35 target.blur();
36
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;
43
44
45 switch (imgId) {
46 case "pl.gif" :
47 case "pl_ani.gif" :
48 var linkCell = parentTd.nextSibling;
49 while (linkCell.nodeType != 1)
50 linkCell = linkCell.nextSibling;
51
52 var obUrl = linkCell.getElementsByTagName("A")[0].href;
53
54 var req = new XMLHttpRequest();
55 var tm = this;
56 req.onreadystatechange = function() {
57 switch (req.readyState) {
58 case 1:
59 showProgressImage();
60 break;
61 case 4:
62 hideProgressImage();
63 tm.importRows(req, parentRow);
64 };
65 };
66 target.src = this.baseImgUrl + "mi_ani.gif";
67 this._lastAniImg = target;
68 window.setTimeout(function(){tm._removeLastAniImg();}, 500);
69
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()));
75
76 break;
77
78 case "mi.gif" :
79 case "mi_ani.gif" :
80 this.removeChildNodes(parentRow);
81 target.src = this.baseImgUrl + "pl_ani.gif";
82 this._lastAniImg = target;
83 var tm = this;
84 window.setTimeout(function(){tm._removeLastAniImg();}, 500);
85 document.cookie = encodeURIComponent(this.root.id) + '-state=' + encodeURIComponent(this.getExpansion()) +
86 ';path=/';
87 break;
88 } // end switch (imgId)
89 disableDefault(evt);
90 disablePropagation(evt);
91 }
92 };
93
94
95 TreeMaker.prototype._removeLastAniImg = function() {
96 if (this._lastAniImg) {
97 this._lastAniImg.src = this._lastAniImg.src.replace("_ani", "");
98 }
99 };
100
101 TreeMaker.prototype.getExpansion = function() {
102 var rows = this.root.getElementsByTagName('TR');
103 var row, cells, stateCell, button, expid, node_depth, last_depth = -1, dd, step;
104 var steps = new Array();
105 steps.push(this.root.getAttribute('name'));
106
107 var expanded = (/.*mi\.gif$|.*mi_ani\.gif$/);
108 for(i=0 ; i < rows.length ; i++) {
109 row = rows[i];
110 cells = row.getElementsByTagName('TD');
111 stateCell = cells[cells.length-2]; // cell where the +/- button is
112 button = stateCell.getElementsByTagName('IMG');
113 if (! button.length)
114 continue;
115 button = button[0];
116 if (expanded.test(button.src)) {
117 expid = button.parentNode.getAttribute("name");
118 node_depth = cells[0].getAttribute('colspan') || 0;
119 dd = last_depth - node_depth + 1;
120 last_depth = node_depth;
121 if (dd > 0) {
122 step = '';
123 for (var j = 0 ; j < dd ; j++)
124 step = step + '_';
125 steps.push(step);
126 }
127 steps.push(expid);
128 }
129 }
130 return steps.join(':');
131 };
132
133
134 /*
135 * expand the tree: sends request and imports rows based on xml response.
136 */
137 TreeMaker.prototype.importRows = function(req, parentRow) {
138 var rows = req.responseXML.documentElement.getElementsByTagName("row");
139 var clickedCells = parentRow.getElementsByTagName("TD");
140 var row, newRow, indentCell, stateCell, linkCell, img, a, indentValue, colspan,
141 incTableDepth=false, cols, linkCellColSpan;
142
143 for (var i = 0 ; i < rows.length ; i++ ) {
144 row = rows[i];
145
146
147 newRow = document.createElement("TR");
148 indentCell = document.createElement("TD");
149 stateCell = document.createElement("TD");
150 stateCell.width = "16";
151 linkCell = document.createElement("TD");
152 linkCell.width = "99%";
153
154
155 if (clickedCells.length == 3) {
156 indentValue = parseInt(clickedCells[0].getAttribute("colspan"));
157 colspan = parseInt(clickedCells[2].getAttribute("colspan"));
158 }
159 else {
160 indentValue = 0;
161 colspan = parseInt(clickedCells[1].getAttribute("colspan"));
162 }
163
164 cols = indentValue + colspan;
165
166 if (colspan == 1)
167 incTableDepth = true;
168
169 indentCell.colSpan = indentValue + 1;
170 if (!this.depthCpt[indentValue])
171 this.depthCpt[indentValue] = 1;
172 else
173 this.depthCpt[indentValue] += 1;
174
175 // IE : it's not possible to set colSpan attr to 0 :-(((
176 linkCellColSpan = cols - indentValue - 1
177 if (linkCellColSpan == 0)
178 linkCell.nullColSpan = true;
179 else
180 linkCell.colSpan = linkCellColSpan;
181
182 img = document.createElement("IMG");
183 img.src = row.getAttribute("icon");
184 img.height = row.getAttribute("height");
185 img.width = row.getAttribute("width");
186 a = document.createElement("A");
187
188 a.setAttribute("href", row.getAttribute("url"));
189 a.setAttribute("title", row.getAttribute("description"));
190 a.innerHTML = row.childNodes[0].nodeValue;
191
192 if (row.getAttribute("state") == "-1") {
193 var stateLink = document.createElement("A");
194 stateLink.href = ".";
195 stateLink.setAttribute("name", row.getAttribute("name"));
196 var stateImg = document.createElement("IMG");
197 stateImg.src = this.baseImgUrl + "pl.gif";
198 stateImg.border = "0";
199 stateImg.height = "16";
200 stateImg.width = "16";
201 stateLink.appendChild(stateImg)
202 stateCell.appendChild(stateLink);
203 }
204 else
205 stateCell.innerHTML = "&nbsp;&nbsp;";
206
207 linkCell.appendChild(img);
208 linkCell.appendChild(a);
209 newRow.appendChild(indentCell);
210 newRow.appendChild(stateCell);
211 newRow.appendChild(linkCell);
212
213
214 this.root.insertBefore(newRow, parentRow.nextSibling);
215 } //end for
216
217 if (incTableDepth) {
218 var rows = this.root.getElementsByTagName("TR");
219 var cells, lastCell, lastColspan;
220 for (var i = 0 ; i < rows.length ; i++) {
221 cells = rows[i].getElementsByTagName("TD");
222 lastCell = cells[cells.length - 1];
223
224 if (lastCell.nullColSpan) {
225 lastCell.nullColSpan = false;
226 lastColspan = 0;
227 }
228 else
229 lastColspan = parseInt(lastCell.getAttribute("colspan"));
230
231 lastCell.colSpan = lastColspan + 1;
232 }
233 }
234 };
235
236 /*
237 * collapse the tree: removes deeper rows after the 'baseRow' passed.
238 */
239 TreeMaker.prototype.removeChildNodes = function(baseRow) {
240 var baseCells = baseRow.getElementsByTagName("TD");
241 var baseColSpan = baseCells[baseCells.length-1].colSpan;
242 var nextRow = baseRow.nextSibling;
243 var tbody = baseRow.parentNode;
244 var depthCpt = this.depthCpt;
245 var nextCells, nextRow2;
246
247 while (nextRow) {
248 if (nextRow.nodeType == 1) {
249 nextCells = nextRow.getElementsByTagName("TD");
250 if (nextCells.length == 3 && nextCells[2].colSpan < baseColSpan) {
251 nextRow2 = nextRow.nextSibling;
252 depthCpt[nextCells[0].colSpan-1] -= 1;
253 tbody.removeChild(nextRow);
254 nextRow = nextRow2;
255 continue;
256 }
257 break;
258 }
259 nextRow = nextRow.nextSibling; // text node
260 }
261
262 // recalc colspans for Safari
263 var maxDepth = depthCpt.length - 1;
264 var depthReduction = 0;
265 while (depthCpt[maxDepth - depthReduction] == 0) {
266 depthCpt.pop();
267 depthReduction++;
268 }
269
270 if (depthReduction) {
271 var rows = tbody.getElementsByTagName("TR");
272 var cells, lastCell, lastColspan;
273 for (var i = 0 ; i < rows.length ; i++) {
274 cells = rows[i].getElementsByTagName("TD");
275 lastCell = cells[cells.length - 1];
276 lastCell.colSpan = parseInt(lastCell.colSpan) - depthReduction;
277 }
278 }
279 };
280 })();